summaryrefslogtreecommitdiffstats
path: root/xmloff/source/text
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /xmloff/source/text
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'xmloff/source/text')
-rw-r--r--xmloff/source/text/XMLAnchorTypePropHdl.hxx43
-rw-r--r--xmloff/source/text/XMLAutoMarkFileContext.cxx81
-rw-r--r--xmloff/source/text/XMLAutoMarkFileContext.hxx48
-rw-r--r--xmloff/source/text/XMLAutoTextContainerEventImport.cxx63
-rw-r--r--xmloff/source/text/XMLAutoTextContainerEventImport.hxx58
-rw-r--r--xmloff/source/text/XMLAutoTextEventExport.cxx216
-rw-r--r--xmloff/source/text/XMLAutoTextEventExport.hxx88
-rw-r--r--xmloff/source/text/XMLAutoTextEventImport.cxx93
-rw-r--r--xmloff/source/text/XMLAutoTextEventImport.hxx59
-rw-r--r--xmloff/source/text/XMLCalculationSettingsContext.cxx73
-rw-r--r--xmloff/source/text/XMLCalculationSettingsContext.hxx38
-rw-r--r--xmloff/source/text/XMLChangeElementImportContext.cxx93
-rw-r--r--xmloff/source/text/XMLChangeElementImportContext.hxx80
-rw-r--r--xmloff/source/text/XMLChangeImportContext.cxx82
-rw-r--r--xmloff/source/text/XMLChangeImportContext.hxx67
-rw-r--r--xmloff/source/text/XMLChangeInfoContext.cxx86
-rw-r--r--xmloff/source/text/XMLChangeInfoContext.hxx69
-rw-r--r--xmloff/source/text/XMLChangedRegionImportContext.cxx176
-rw-r--r--xmloff/source/text/XMLChangedRegionImportContext.hxx82
-rw-r--r--xmloff/source/text/XMLComplexColorContext.cxx172
-rw-r--r--xmloff/source/text/XMLComplexColorExport.cxx97
-rw-r--r--xmloff/source/text/XMLFootnoteBodyImportContext.cxx47
-rw-r--r--xmloff/source/text/XMLFootnoteBodyImportContext.hxx49
-rw-r--r--xmloff/source/text/XMLFootnoteConfigurationImportContext.cxx335
-rw-r--r--xmloff/source/text/XMLFootnoteImportContext.cxx168
-rw-r--r--xmloff/source/text/XMLFootnoteImportContext.hxx72
-rw-r--r--xmloff/source/text/XMLIndexAlphabeticalSourceContext.cxx212
-rw-r--r--xmloff/source/text/XMLIndexAlphabeticalSourceContext.hxx73
-rw-r--r--xmloff/source/text/XMLIndexBibliographyConfigurationContext.cxx215
-rw-r--r--xmloff/source/text/XMLIndexBibliographyEntryContext.cxx156
-rw-r--r--xmloff/source/text/XMLIndexBibliographyEntryContext.hxx70
-rw-r--r--xmloff/source/text/XMLIndexBibliographySourceContext.cxx80
-rw-r--r--xmloff/source/text/XMLIndexBibliographySourceContext.hxx57
-rw-r--r--xmloff/source/text/XMLIndexBodyContext.cxx52
-rw-r--r--xmloff/source/text/XMLIndexBodyContext.hxx63
-rw-r--r--xmloff/source/text/XMLIndexChapterInfoEntryContext.cxx185
-rw-r--r--xmloff/source/text/XMLIndexChapterInfoEntryContext.hxx67
-rw-r--r--xmloff/source/text/XMLIndexIllustrationSourceContext.cxx67
-rw-r--r--xmloff/source/text/XMLIndexIllustrationSourceContext.hxx55
-rw-r--r--xmloff/source/text/XMLIndexMarkExport.cxx228
-rw-r--r--xmloff/source/text/XMLIndexMarkExport.hxx92
-rw-r--r--xmloff/source/text/XMLIndexObjectSourceContext.cxx136
-rw-r--r--xmloff/source/text/XMLIndexObjectSourceContext.hxx63
-rw-r--r--xmloff/source/text/XMLIndexSimpleEntryContext.cxx123
-rw-r--r--xmloff/source/text/XMLIndexSimpleEntryContext.hxx79
-rw-r--r--xmloff/source/text/XMLIndexSourceBaseContext.cxx135
-rw-r--r--xmloff/source/text/XMLIndexSourceBaseContext.hxx84
-rw-r--r--xmloff/source/text/XMLIndexSpanEntryContext.cxx63
-rw-r--r--xmloff/source/text/XMLIndexSpanEntryContext.hxx57
-rw-r--r--xmloff/source/text/XMLIndexTOCContext.cxx343
-rw-r--r--xmloff/source/text/XMLIndexTOCContext.hxx82
-rw-r--r--xmloff/source/text/XMLIndexTOCSourceContext.cxx149
-rw-r--r--xmloff/source/text/XMLIndexTOCSourceContext.hxx62
-rw-r--r--xmloff/source/text/XMLIndexTOCStylesContext.cxx143
-rw-r--r--xmloff/source/text/XMLIndexTOCStylesContext.hxx73
-rw-r--r--xmloff/source/text/XMLIndexTabStopEntryContext.cxx155
-rw-r--r--xmloff/source/text/XMLIndexTabStopEntryContext.hxx66
-rw-r--r--xmloff/source/text/XMLIndexTableSourceContext.cxx146
-rw-r--r--xmloff/source/text/XMLIndexTableSourceContext.hxx63
-rw-r--r--xmloff/source/text/XMLIndexTemplateContext.cxx420
-rw-r--r--xmloff/source/text/XMLIndexTemplateContext.hxx125
-rw-r--r--xmloff/source/text/XMLIndexTitleTemplateContext.cxx95
-rw-r--r--xmloff/source/text/XMLIndexTitleTemplateContext.hxx71
-rw-r--r--xmloff/source/text/XMLIndexUserSourceContext.cxx157
-rw-r--r--xmloff/source/text/XMLIndexUserSourceContext.hxx65
-rw-r--r--xmloff/source/text/XMLLineNumberingExport.cxx185
-rw-r--r--xmloff/source/text/XMLLineNumberingExport.hxx35
-rw-r--r--xmloff/source/text/XMLLineNumberingImportContext.cxx233
-rw-r--r--xmloff/source/text/XMLLineNumberingSeparatorImportContext.cxx78
-rw-r--r--xmloff/source/text/XMLLineNumberingSeparatorImportContext.hxx59
-rw-r--r--xmloff/source/text/XMLPropertyBackpatcher.cxx208
-rw-r--r--xmloff/source/text/XMLPropertyBackpatcher.hxx97
-rw-r--r--xmloff/source/text/XMLRedlineExport.cxx656
-rw-r--r--xmloff/source/text/XMLRedlineExport.hxx163
-rw-r--r--xmloff/source/text/XMLSectionExport.cxx1836
-rw-r--r--xmloff/source/text/XMLSectionExport.hxx262
-rw-r--r--xmloff/source/text/XMLSectionFootnoteConfigExport.cxx179
-rw-r--r--xmloff/source/text/XMLSectionFootnoteConfigExport.hxx52
-rw-r--r--xmloff/source/text/XMLSectionFootnoteConfigImport.cxx170
-rw-r--r--xmloff/source/text/XMLSectionFootnoteConfigImport.hxx61
-rw-r--r--xmloff/source/text/XMLSectionImportContext.cxx324
-rw-r--r--xmloff/source/text/XMLSectionImportContext.hxx80
-rw-r--r--xmloff/source/text/XMLSectionSourceDDEImportContext.cxx108
-rw-r--r--xmloff/source/text/XMLSectionSourceDDEImportContext.hxx48
-rw-r--r--xmloff/source/text/XMLSectionSourceImportContext.cxx97
-rw-r--r--xmloff/source/text/XMLSectionSourceImportContext.hxx46
-rw-r--r--xmloff/source/text/XMLStringBufferImportContext.cxx60
-rw-r--r--xmloff/source/text/XMLTextCharStyleNamesElementExport.cxx75
-rw-r--r--xmloff/source/text/XMLTextCharStyleNamesElementExport.hxx46
-rw-r--r--xmloff/source/text/XMLTextColumnsContext.cxx369
-rw-r--r--xmloff/source/text/XMLTextColumnsExport.cxx196
-rw-r--r--xmloff/source/text/XMLTextFrameContext.cxx1751
-rw-r--r--xmloff/source/text/XMLTextFrameContext.hxx93
-rw-r--r--xmloff/source/text/XMLTextFrameHyperlinkContext.cxx183
-rw-r--r--xmloff/source/text/XMLTextFrameHyperlinkContext.hxx62
-rw-r--r--xmloff/source/text/XMLTextHeaderFooterContext.cxx190
-rw-r--r--xmloff/source/text/XMLTextListAutoStylePool.cxx294
-rw-r--r--xmloff/source/text/XMLTextListBlockContext.cxx277
-rw-r--r--xmloff/source/text/XMLTextListBlockContext.hxx78
-rw-r--r--xmloff/source/text/XMLTextListItemContext.cxx152
-rw-r--r--xmloff/source/text/XMLTextListItemContext.hxx69
-rw-r--r--xmloff/source/text/XMLTextMarkImportContext.cxx585
-rw-r--r--xmloff/source/text/XMLTextMarkImportContext.hxx106
-rw-r--r--xmloff/source/text/XMLTextMasterPageContext.cxx301
-rw-r--r--xmloff/source/text/XMLTextMasterPageExport.cxx237
-rw-r--r--xmloff/source/text/XMLTextMasterStylesContext.cxx66
-rw-r--r--xmloff/source/text/XMLTextNumRuleInfo.cxx222
-rw-r--r--xmloff/source/text/XMLTextNumRuleInfo.hxx158
-rw-r--r--xmloff/source/text/XMLTextPropertySetContext.cxx135
-rw-r--r--xmloff/source/text/XMLTextPropertySetContext.hxx51
-rw-r--r--xmloff/source/text/XMLTextShapeImportHelper.cxx149
-rw-r--r--xmloff/source/text/XMLTextShapeStyleContext.cxx219
-rw-r--r--xmloff/source/text/XMLTextTableContext.cxx35
-rw-r--r--xmloff/source/text/XMLTrackedChangesImportContext.cxx83
-rw-r--r--xmloff/source/text/XMLTrackedChangesImportContext.hxx48
-rw-r--r--xmloff/source/text/txtdrope.cxx87
-rw-r--r--xmloff/source/text/txtdrope.hxx41
-rw-r--r--xmloff/source/text/txtdropi.cxx122
-rw-r--r--xmloff/source/text/txtdropi.hxx46
-rw-r--r--xmloff/source/text/txtexppr.cxx1206
-rw-r--r--xmloff/source/text/txtexppr.hxx90
-rw-r--r--xmloff/source/text/txtflde.cxx3616
-rw-r--r--xmloff/source/text/txtfldi.cxx3661
-rw-r--r--xmloff/source/text/txtftne.cxx344
-rw-r--r--xmloff/source/text/txtimp.cxx2521
-rw-r--r--xmloff/source/text/txtimppr.cxx848
-rw-r--r--xmloff/source/text/txtlists.cxx499
-rw-r--r--xmloff/source/text/txtparae.cxx4351
-rw-r--r--xmloff/source/text/txtparai.cxx2147
-rw-r--r--xmloff/source/text/txtparai.hxx146
-rw-r--r--xmloff/source/text/txtparaimphint.hxx241
-rw-r--r--xmloff/source/text/txtprhdl.cxx1451
-rw-r--r--xmloff/source/text/txtprhdl.hxx31
-rw-r--r--xmloff/source/text/txtprmap.cxx1159
-rw-r--r--xmloff/source/text/txtsecte.cxx203
-rw-r--r--xmloff/source/text/txtstyle.cxx164
-rw-r--r--xmloff/source/text/txtstyli.cxx633
-rw-r--r--xmloff/source/text/txtvfldi.cxx1247
-rw-r--r--xmloff/source/text/xmlcontentcontrolcontext.cxx369
-rw-r--r--xmloff/source/text/xmlcontentcontrolcontext.hxx92
-rw-r--r--xmloff/source/text/xmllinebreakcontext.cxx60
-rw-r--r--xmloff/source/text/xmllinebreakcontext.hxx31
142 files changed, 43835 insertions, 0 deletions
diff --git a/xmloff/source/text/XMLAnchorTypePropHdl.hxx b/xmloff/source/text/XMLAnchorTypePropHdl.hxx
new file mode 100644
index 0000000000..64bddb078f
--- /dev/null
+++ b/xmloff/source/text/XMLAnchorTypePropHdl.hxx
@@ -0,0 +1,43 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/text/TextContentAnchorType.hpp>
+#include <xmloff/xmlprhdl.hxx>
+
+
+class XMLAnchorTypePropHdl : public XMLPropertyHandler
+{
+public:
+ virtual ~XMLAnchorTypePropHdl () override;
+
+ virtual bool importXML(
+ const OUString& rStrImpValue,
+ css::uno::Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter ) const override;
+ virtual bool exportXML(
+ OUString& rStrExpValue,
+ const css::uno::Any& rValue,
+ const SvXMLUnitConverter& rUnitConverter ) const override;
+ static bool convert( std::string_view rStrImpValue,
+ css::text::TextContentAnchorType& rType );
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLAutoMarkFileContext.cxx b/xmloff/source/text/XMLAutoMarkFileContext.cxx
new file mode 100644
index 0000000000..c7237aa783
--- /dev/null
+++ b/xmloff/source/text/XMLAutoMarkFileContext.cxx
@@ -0,0 +1,81 @@
+/* -*- 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 "XMLAutoMarkFileContext.hxx"
+#include <xmloff/xmlimp.hxx>
+#include <rtl/ustring.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/xml/sax/XAttributeList.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <sal/log.hxx>
+
+
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::UNO_QUERY;
+using ::com::sun::star::beans::XPropertySet;
+
+using ::xmloff::token::XML_HREF;
+
+
+XMLAutoMarkFileContext::XMLAutoMarkFileContext(
+ SvXMLImport& rImport) :
+ SvXMLImportContext(rImport)
+{
+}
+
+XMLAutoMarkFileContext::~XMLAutoMarkFileContext()
+{
+}
+
+
+void XMLAutoMarkFileContext::startFastElement(
+ sal_Int32 /*nElement*/,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ // scan for text:alphabetical-index-auto-mark-file attribute, and if
+ // found set value with the document
+
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ switch(aIter.getToken())
+ {
+ case XML_ELEMENT(XLINK, XML_HREF):
+ {
+ Any aAny;
+ aAny <<= GetImport().GetAbsoluteReference( aIter.toString() );
+ Reference<XPropertySet> xPropertySet(
+ GetImport().GetModel(), UNO_QUERY );
+ if (xPropertySet.is())
+ {
+ xPropertySet->setPropertyValue( "IndexAutoMarkFileURL", aAny );
+ }
+ break;
+ }
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLAutoMarkFileContext.hxx b/xmloff/source/text/XMLAutoMarkFileContext.hxx
new file mode 100644
index 0000000000..cf74dd596a
--- /dev/null
+++ b/xmloff/source/text/XMLAutoMarkFileContext.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+
+
+namespace com::sun::star {
+ namespace uno { template<class X> class Reference; }
+ namespace beans { class XPropertySet; }
+ namespace xml::sax { class XAttributeList; }
+}
+
+
+class XMLAutoMarkFileContext : public SvXMLImportContext
+{
+public:
+
+ XMLAutoMarkFileContext(
+ SvXMLImport& rImport);
+
+ virtual ~XMLAutoMarkFileContext() override;
+
+protected:
+
+ virtual void SAL_CALL startFastElement(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLAutoTextContainerEventImport.cxx b/xmloff/source/text/XMLAutoTextContainerEventImport.cxx
new file mode 100644
index 0000000000..9ac584865c
--- /dev/null
+++ b/xmloff/source/text/XMLAutoTextContainerEventImport.cxx
@@ -0,0 +1,63 @@
+/* -*- 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 "XMLAutoTextContainerEventImport.hxx"
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/xml/sax/XAttributeList.hpp>
+#include <com/sun/star/container/XNameReplace.hpp>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/XMLEventsImportContext.hxx>
+#include <sal/log.hxx>
+
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::container::XNameReplace;
+using ::xmloff::token::XML_EVENT_LISTENERS;
+
+
+XMLAutoTextContainerEventImport::XMLAutoTextContainerEventImport(
+ SvXMLImport& rImport,
+ const Reference<XNameReplace> & rEvnts ) :
+ SvXMLImportContext(rImport),
+ rEvents(rEvnts)
+{
+}
+
+XMLAutoTextContainerEventImport::~XMLAutoTextContainerEventImport()
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLAutoTextContainerEventImport::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
+{
+ if ( nElement == XML_ELEMENT(OFFICE, XML_EVENT_LISTENERS) )
+ {
+ return new XMLEventsImportContext(GetImport(), rEvents);
+ }
+ else
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ return nullptr;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLAutoTextContainerEventImport.hxx b/xmloff/source/text/XMLAutoTextContainerEventImport.hxx
new file mode 100644
index 0000000000..2640f27edf
--- /dev/null
+++ b/xmloff/source/text/XMLAutoTextContainerEventImport.hxx
@@ -0,0 +1,58 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+
+
+namespace com::sun::star {
+ namespace container { class XNameReplace; }
+ namespace xml::sax { class XAttributeList; }
+}
+
+
+/**
+ * Import the text:auto-text-container element.
+ * This only instantiates text:auto-text-group context.
+ */
+class XMLAutoTextContainerEventImport : public SvXMLImportContext
+{
+ /// the parent auto text container
+ const css::uno::Reference<css::container::XNameReplace> & rEvents;
+
+public:
+
+
+ XMLAutoTextContainerEventImport(
+ SvXMLImport& rImport,
+ const css::uno::Reference<css::container::XNameReplace > & rEvents );
+
+ virtual ~XMLAutoTextContainerEventImport() override;
+
+
+protected:
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLAutoTextEventExport.cxx b/xmloff/source/text/XMLAutoTextEventExport.cxx
new file mode 100644
index 0000000000..b6a089e8a0
--- /dev/null
+++ b/xmloff/source/text/XMLAutoTextEventExport.cxx
@@ -0,0 +1,216 @@
+/* -*- 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 "XMLAutoTextEventExport.hxx"
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+#include <com/sun/star/util/MeasureUnit.hpp>
+#include <com/sun/star/document/XEventsSupplier.hpp>
+#include <com/sun/star/container/XNameReplace.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/Exception.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <osl/diagnose.h>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/XMLEventExport.hxx>
+#include <tools/debug.hxx>
+#include <comphelper/processfactory.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+using ::com::sun::star::container::XNameReplace;
+using ::com::sun::star::document::XEventsSupplier;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Exception;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::XInterface;
+using ::com::sun::star::uno::UNO_QUERY;
+using ::com::sun::star::xml::sax::XDocumentHandler;
+
+
+XMLAutoTextEventExport::XMLAutoTextEventExport(
+ const css::uno::Reference< css::uno::XComponentContext >& xContext,
+ OUString const & implementationName, SvXMLExportFlags nFlags
+ )
+: SvXMLExport(xContext, implementationName, util::MeasureUnit::INCH, XML_AUTO_TEXT, nFlags)
+{
+}
+
+XMLAutoTextEventExport::~XMLAutoTextEventExport()
+{
+}
+
+void XMLAutoTextEventExport::initialize(
+ const Sequence<Any> & rArguments )
+{
+ if (rArguments.getLength() > 1)
+ {
+ Reference<XEventsSupplier> xSupplier;
+ rArguments[1] >>= xSupplier;
+ if (xSupplier.is())
+ {
+ xEvents = xSupplier->getEvents();
+ }
+ else
+ {
+ Reference<XNameReplace> xReplace;
+ rArguments[1] >>= xReplace;
+ if (xReplace.is())
+ {
+ xEvents = xReplace;
+ }
+ else
+ {
+ rArguments[1] >>= xEvents;
+ }
+ }
+ }
+
+ // call super class (for XHandler)
+ SvXMLExport::initialize(rArguments);
+}
+
+
+ErrCode XMLAutoTextEventExport::exportDoc( enum XMLTokenEnum )
+{
+ if( !(getExportFlags() & SvXMLExportFlags::OASIS) )
+ {
+ Reference< uno::XComponentContext> xContext = getComponentContext();
+ try
+ {
+
+ Sequence<Any> aArgs{ Any(GetDocHandler()) };
+
+ // get filter component
+ Reference< xml::sax::XDocumentHandler > xTmpDocHandler(
+ xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ "com.sun.star.comp.Oasis2OOoTransformer",
+ aArgs,
+ xContext),
+ UNO_QUERY);
+ OSL_ENSURE( xTmpDocHandler.is(),
+ "can't instantiate OASIS transformer component" );
+ if( xTmpDocHandler.is() )
+ {
+ SetDocHandler( xTmpDocHandler );
+ }
+ }
+ catch( css::uno::Exception& )
+ {
+ }
+ }
+ if (hasEvents())
+ {
+ GetDocHandler()->startDocument();
+
+ addChaffWhenEncryptedStorage();
+
+ addNamespaces();
+
+ {
+ // container element
+ SvXMLElementExport aContainerElement(
+ *this, XML_NAMESPACE_OOO, XML_AUTO_TEXT_EVENTS,
+ true, true);
+
+ exportEvents();
+ }
+
+ // and close document again
+ GetDocHandler()->endDocument();
+ }
+
+ return ERRCODE_NONE;
+}
+
+bool XMLAutoTextEventExport::hasEvents() const
+{
+ // TODO: provide full implementation that check for presence of events
+ return xEvents.is();
+}
+
+void XMLAutoTextEventExport::addNamespaces()
+{
+ // namespaces for office:, text: and script:
+ GetAttrList().AddAttribute(
+ GetNamespaceMap().GetAttrNameByIndex( XML_NAMESPACE_OFFICE ),
+ GetNamespaceMap().GetNameByIndex( XML_NAMESPACE_OFFICE ) );
+ GetAttrList().AddAttribute(
+ GetNamespaceMap().GetAttrNameByIndex( XML_NAMESPACE_TEXT ),
+ GetNamespaceMap().GetNameByIndex( XML_NAMESPACE_TEXT ) );
+ GetAttrList().AddAttribute(
+ GetNamespaceMap().GetAttrNameByIndex( XML_NAMESPACE_SCRIPT ),
+ GetNamespaceMap().GetNameByIndex( XML_NAMESPACE_SCRIPT ) );
+ GetAttrList().AddAttribute(
+ GetNamespaceMap().GetAttrNameByIndex( XML_NAMESPACE_DOM ),
+ GetNamespaceMap().GetNameByIndex( XML_NAMESPACE_DOM ) );
+ GetAttrList().AddAttribute(
+ GetNamespaceMap().GetAttrNameByIndex( XML_NAMESPACE_OOO ),
+ GetNamespaceMap().GetNameByIndex( XML_NAMESPACE_OOO ) );
+ GetAttrList().AddAttribute(
+ GetNamespaceMap().GetAttrNameByIndex( XML_NAMESPACE_XLINK ),
+ GetNamespaceMap().GetNameByIndex( XML_NAMESPACE_XLINK ) );
+}
+
+void XMLAutoTextEventExport::exportEvents()
+{
+ DBG_ASSERT(hasEvents(), "no events to export!");
+
+ GetEventExport().Export(xEvents);
+}
+
+
+// methods without content:
+
+void XMLAutoTextEventExport::ExportMeta_() {}
+void XMLAutoTextEventExport::ExportScripts_() {}
+void XMLAutoTextEventExport::ExportFontDecls_() {}
+void XMLAutoTextEventExport::ExportStyles_( bool ) {}
+void XMLAutoTextEventExport::ExportAutoStyles_() {}
+void XMLAutoTextEventExport::ExportMasterStyles_() {}
+void XMLAutoTextEventExport::ExportContent_() {}
+
+
+// methods to support the component registration
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_Writer_XMLOasisAutotextEventsExporter_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new XMLAutoTextEventExport(
+ context, "com.sun.star.comp.Writer.XMLOasisAutotextEventsExporter",
+ SvXMLExportFlags::ALL | SvXMLExportFlags::OASIS));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_Writer_XMLAutotextEventsExporter_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new XMLAutoTextEventExport(
+ context, "com.sun.star.comp.Writer.XMLAutotextEventsExporter",
+ SvXMLExportFlags::ALL));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLAutoTextEventExport.hxx b/xmloff/source/text/XMLAutoTextEventExport.hxx
new file mode 100644
index 0000000000..27e6de771c
--- /dev/null
+++ b/xmloff/source/text/XMLAutoTextEventExport.hxx
@@ -0,0 +1,88 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlexp.hxx>
+
+
+namespace com::sun::star {
+ namespace container { class XNameAccess; }
+ namespace frame { class XModel; }
+ namespace lang { class XMultiServiceFactory; }
+ namespace uno { template<class X> class Reference; }
+ namespace uno { template<class X> class Sequence; }
+ namespace uno { class XInterface; }
+ namespace uno { class Exception; }
+ namespace xml::sax { class XDocumentHandler; }
+}
+
+
+/**
+ * Component for the export of events attached to autotext blocks.
+ * Via the XInitialization interface it expects up to two strings, the
+ * first giving the file name (URL) of the autotext group, and the second
+ * identifying the autotext. If one of the strings is not given, it
+ * will export the whole group / all groups.
+ */
+class XMLAutoTextEventExport : public SvXMLExport
+{
+ css::uno::Reference<css::container::XNameAccess> xEvents;
+
+public:
+
+ XMLAutoTextEventExport(
+ const css::uno::Reference< css::uno::XComponentContext >& xContext, OUString const & implementationName, SvXMLExportFlags nFlags
+ );
+
+ virtual ~XMLAutoTextEventExport() override;
+
+ // XInitialization
+ virtual void SAL_CALL initialize(
+ const css::uno::Sequence<css::uno::Any> & rArguments ) override;
+
+private:
+
+ /// export the events off all autotexts
+ virtual ErrCode exportDoc(
+ enum ::xmloff::token::XMLTokenEnum eClass = xmloff::token::XML_TOKEN_INVALID ) override;
+
+ /// does the document have any events ?
+ bool hasEvents() const;
+
+ /// export the events element
+ void exportEvents();
+
+
+ /// add the namespaces used by events
+ /// (to be called for the document element)
+ void addNamespaces();
+
+
+ // methods without content:
+ virtual void ExportMeta_() override;
+ virtual void ExportScripts_() override;
+ virtual void ExportFontDecls_() override;
+ virtual void ExportStyles_( bool bUsed ) override ;
+ virtual void ExportAutoStyles_() override;
+ virtual void ExportMasterStyles_() override;
+ virtual void ExportContent_() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLAutoTextEventImport.cxx b/xmloff/source/text/XMLAutoTextEventImport.cxx
new file mode 100644
index 0000000000..cb76f062ba
--- /dev/null
+++ b/xmloff/source/text/XMLAutoTextEventImport.cxx
@@ -0,0 +1,93 @@
+/* -*- 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 "XMLAutoTextEventImport.hxx"
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/document/XEventsSupplier.hpp>
+#include <com/sun/star/uno/XInterface.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include "XMLAutoTextContainerEventImport.hxx"
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <tools/debug.hxx>
+#include <comphelper/processfactory.hxx>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Type;
+using ::com::sun::star::uno::XInterface;
+using ::com::sun::star::document::XEventsSupplier;
+using ::com::sun::star::container::XNameReplace;
+using ::xmloff::token::XML_AUTO_TEXT_EVENTS;
+
+XMLAutoTextEventImport::XMLAutoTextEventImport(
+ const css::uno::Reference<css::uno::XComponentContext>& xContext)
+ : SvXMLImport(xContext, "com.sun.star.comp.Writer.XMLOasisAutotextEventsImporter")
+{
+}
+
+XMLAutoTextEventImport::~XMLAutoTextEventImport() noexcept {}
+
+void XMLAutoTextEventImport::initialize(const Sequence<Any>& rArguments)
+{
+ // The events may come as either an XNameReplace or XEventsSupplier.
+
+ for (const auto& rArgument : rArguments)
+ {
+ const Type& rType = rArgument.getValueType();
+ if (rType == cppu::UnoType<XEventsSupplier>::get())
+ {
+ Reference<XEventsSupplier> xSupplier;
+ rArgument >>= xSupplier;
+ DBG_ASSERT(xSupplier.is(), "need XEventsSupplier or XNameReplace");
+
+ xEvents = xSupplier->getEvents();
+ }
+ else if (rType == cppu::UnoType<XNameReplace>::get())
+ {
+ rArgument >>= xEvents;
+ DBG_ASSERT(xEvents.is(), "need XEventsSupplier or XNameReplace");
+ }
+ }
+
+ // call parent
+ SvXMLImport::initialize(rArguments);
+}
+
+SvXMLImportContext* XMLAutoTextEventImport::CreateFastContext(
+ sal_Int32 nElement, const Reference<css::xml::sax::XFastAttributeList>& /*xAttrList*/)
+{
+ if (xEvents.is() && nElement == XML_ELEMENT(OOO, XML_AUTO_TEXT_EVENTS))
+ {
+ return new XMLAutoTextContainerEventImport(*this, xEvents);
+ }
+ return nullptr;
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_Writer_XMLOasisAutotextEventsImporter_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new XMLAutoTextEventImport(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLAutoTextEventImport.hxx b/xmloff/source/text/XMLAutoTextEventImport.hxx
new file mode 100644
index 0000000000..b79b231c53
--- /dev/null
+++ b/xmloff/source/text/XMLAutoTextEventImport.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/.
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlimp.hxx>
+#include <com/sun/star/container/XNameReplace.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+
+
+namespace com::sun::star {
+ namespace frame { class XModel; }
+ namespace text { class XAutoTextContainer; }
+ namespace text { class XAutoTextGroup; }
+ namespace text { class XAutoTextEntry; }
+ namespace uno { template<class X> class Reference; }
+ namespace uno { template<class X> class Sequence; }
+ namespace xml::sax { class XDocumentHandler; }
+}
+
+
+class XMLAutoTextEventImport : public SvXMLImport
+{
+ css::uno::Reference<css::container::XNameReplace> xEvents;
+
+public:
+ explicit XMLAutoTextEventImport(
+ const css::uno::Reference< css::uno::XComponentContext >& xContext);
+
+ virtual ~XMLAutoTextEventImport() noexcept override;
+
+ // XInitialization
+ virtual void SAL_CALL initialize(
+ const css::uno::Sequence<css::uno::Any> & rArguments ) override;
+
+protected:
+
+ virtual SvXMLImportContext *CreateFastContext( sal_Int32 Element,
+ const ::css::uno::Reference< ::css::xml::sax::XFastAttributeList >& xAttrList ) override;
+
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLCalculationSettingsContext.cxx b/xmloff/source/text/XMLCalculationSettingsContext.cxx
new file mode 100644
index 0000000000..fa7ff42365
--- /dev/null
+++ b/xmloff/source/text/XMLCalculationSettingsContext.cxx
@@ -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/.
+ *
+ * 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 "XMLCalculationSettingsContext.hxx"
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/text/XTextDocument.hpp>
+
+#include <sal/log.hxx>
+#include <sax/tools/converter.hxx>
+
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::text;
+using namespace ::xmloff::token;
+
+XMLCalculationSettingsContext::XMLCalculationSettingsContext( SvXMLImport& rImport,
+ sal_Int32 /*nElement*/,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+: SvXMLImportContext ( rImport )
+, nYear( 1930 )
+{
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ if (aIter.getToken() == XML_ELEMENT(TABLE, XML_NULL_YEAR) )
+ {
+ nYear = static_cast <sal_Int16> (aIter.toInt32());
+ }
+ else
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+}
+
+XMLCalculationSettingsContext::~XMLCalculationSettingsContext()
+{
+}
+void XMLCalculationSettingsContext::endFastElement(sal_Int32 )
+{
+ if (nYear != 1930 )
+ {
+ Reference < XTextDocument > xTextDoc ( GetImport().GetModel(), UNO_QUERY);
+ if (xTextDoc.is())
+ {
+ Reference < XPropertySet > xPropSet ( xTextDoc, UNO_QUERY );
+ xPropSet->setPropertyValue ( "TwoDigitYear", Any(nYear) );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLCalculationSettingsContext.hxx b/xmloff/source/text/XMLCalculationSettingsContext.hxx
new file mode 100644
index 0000000000..d0668b2e51
--- /dev/null
+++ b/xmloff/source/text/XMLCalculationSettingsContext.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/.
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+
+class XMLCalculationSettingsContext : public SvXMLImportContext
+{
+ sal_Int16 nYear;
+public:
+ XMLCalculationSettingsContext( SvXMLImport& rImport,
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList );
+
+ virtual ~XMLCalculationSettingsContext() override;
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLChangeElementImportContext.cxx b/xmloff/source/text/XMLChangeElementImportContext.cxx
new file mode 100644
index 0000000000..550bbcd965
--- /dev/null
+++ b/xmloff/source/text/XMLChangeElementImportContext.cxx
@@ -0,0 +1,93 @@
+/* -*- 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 "XMLChangeElementImportContext.hxx"
+#include "XMLChangedRegionImportContext.hxx"
+#include "XMLChangeInfoContext.hxx"
+#include <com/sun/star/uno/Reference.h>
+#include <utility>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+
+
+using ::com::sun::star::uno::Reference;
+using ::xmloff::token::XML_CHANGE_INFO;
+
+
+XMLChangeElementImportContext::XMLChangeElementImportContext(
+ SvXMLImport& rImport,
+ bool bAccContent,
+ XMLChangedRegionImportContext& rParent,
+ OUString aType) :
+ SvXMLImportContext(rImport),
+ bAcceptContent(bAccContent),
+ maType(std::move(aType)),
+ rChangedRegion(rParent)
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLChangeElementImportContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ SvXMLImportContextRef xContext;
+
+ if ( nElement == XML_ELEMENT(OFFICE, XML_CHANGE_INFO) )
+ {
+ xContext = new XMLChangeInfoContext(GetImport(),
+ rChangedRegion, maType);
+ }
+ else
+ {
+ // import into redline -> create XText
+ rChangedRegion.UseRedlineText();
+
+ xContext = GetImport().GetTextImport()->CreateTextChildContext(
+ GetImport(), nElement, xAttrList,
+ XMLTextType::ChangedRegion);
+
+ if (!xContext)
+ {
+ // no text element
+ // illegal element content! TODO: discard this redline!
+ // for the moment -> use default
+ }
+ }
+
+ return xContext;
+}
+
+void XMLChangeElementImportContext::startFastElement( sal_Int32, const Reference< css::xml::sax::XFastAttributeList >& )
+{
+ if(bAcceptContent)
+ {
+ GetImport().GetTextImport()->SetInsideDeleteContext(true);
+ }
+}
+
+void XMLChangeElementImportContext::endFastElement(sal_Int32 )
+{
+ if(bAcceptContent)
+ {
+ GetImport().GetTextImport()->SetInsideDeleteContext(false);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLChangeElementImportContext.hxx b/xmloff/source/text/XMLChangeElementImportContext.hxx
new file mode 100644
index 0000000000..7cd7c85975
--- /dev/null
+++ b/xmloff/source/text/XMLChangeElementImportContext.hxx
@@ -0,0 +1,80 @@
+/* -*- 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 .
+ */
+
+
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <com/sun/star/uno/Reference.h>
+
+
+namespace com::sun::star {
+ namespace xml::sax {
+ class XAttributeList;
+ }
+}
+class XMLChangedRegionImportContext;
+
+
+/**
+ * Import <text:deletion> and <text:insertion> elements contained in a
+ * <text:changed-region> element.
+ */
+ class XMLChangeElementImportContext : public SvXMLImportContext
+{
+ /**
+ * accept text content (paragraphs) in element as redline content?
+ *
+ * From the "5.5.4 <text:deletion>" section of the ODF 1.2 standard :
+ * The <text:deletion> element may also contain content that was
+ * deleted while change tracking was enabled.
+ *
+ * No other section in the "5.5 Change Tracking" chapter contain
+ * this sentence.
+ *
+ * So if bAcceptContent is true, we are importing a <text:deletion> element
+ */
+ bool bAcceptContent;
+
+ OUString maType;
+
+ /// context of enclosing <text:changed-region> element
+ XMLChangedRegionImportContext& rChangedRegion;
+
+public:
+
+ XMLChangeElementImportContext(
+ SvXMLImport& rImport,
+ /// accept text content (paragraphs) in element as redline content?
+ bool bAcceptContent,
+ /// context of enclosing <text:changed-region> element
+ XMLChangedRegionImportContext& rParent,
+ OUString aType);
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+
+ // Start- and EndElement are needed here to set the inside_deleted_section
+ // flag at the corresponding TextImportHelper
+ virtual void SAL_CALL startFastElement( sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLChangeImportContext.cxx b/xmloff/source/text/XMLChangeImportContext.cxx
new file mode 100644
index 0000000000..35e766e768
--- /dev/null
+++ b/xmloff/source/text/XMLChangeImportContext.cxx
@@ -0,0 +1,82 @@
+/* -*- 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 "XMLChangeImportContext.hxx"
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <sal/log.hxx>
+
+using ::com::sun::star::uno::Reference;
+using ::xmloff::token::XML_CHANGE_ID;
+
+
+XMLChangeImportContext::XMLChangeImportContext(
+ SvXMLImport& rImport,
+ Element const eElement,
+ bool bOutsideOfParagraph)
+ : SvXMLImportContext(rImport)
+ , m_Element(eElement)
+ , m_bIsOutsideOfParagraph(bOutsideOfParagraph)
+{
+}
+
+XMLChangeImportContext::~XMLChangeImportContext()
+{
+}
+
+void XMLChangeImportContext::startFastElement(
+ sal_Int32 /*nElement*/,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ switch(aIter.getToken())
+ {
+ case XML_ELEMENT(TEXT, XML_CHANGE_ID):
+ {
+ // Id found! Now call RedlineImportHelper
+
+ // prepare parameters
+ rtl::Reference<XMLTextImportHelper> rHelper =
+ GetImport().GetTextImport();
+ OUString sID = aIter.toString();
+
+ // <text:change> is both start and end
+ if (Element::START == m_Element || Element::POINT == m_Element)
+ rHelper->RedlineSetCursor(sID, true, m_bIsOutsideOfParagraph);
+ if (Element::END == m_Element || Element::POINT == m_Element)
+ rHelper->RedlineSetCursor(sID, false, m_bIsOutsideOfParagraph);
+
+ // outside of paragraph and still open? set open redline ID
+ if (m_bIsOutsideOfParagraph)
+ {
+ rHelper->SetOpenRedlineId(sID);
+ }
+ break;
+ }
+ // else: ignore
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLChangeImportContext.hxx b/xmloff/source/text/XMLChangeImportContext.hxx
new file mode 100644
index 0000000000..c2e128c552
--- /dev/null
+++ b/xmloff/source/text/XMLChangeImportContext.hxx
@@ -0,0 +1,67 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+
+#include <xmloff/xmlictxt.hxx>
+#include <com/sun/star/uno/Reference.h>
+
+
+namespace com::sun::star {
+ namespace xml::sax {
+ class XAttributeList;
+ }
+}
+
+
+/**
+ * import change tracking/redlining markers
+ * <text:change>, <text:change-start>, <text:change-end>
+ */
+class XMLChangeImportContext : public SvXMLImportContext
+{
+public:
+ enum class Element { START, END, POINT };
+
+ /**
+ * import a change mark
+ * (<text:change>, <text:change-start>, <text:change-end>)
+ * Note: a <text:change> mark denotes start and end of a change
+ * simultaneously, as in Element::POINT.
+ */
+ XMLChangeImportContext(
+ SvXMLImport& rImport,
+ Element eElement,
+ /// true if change mark is encountered outside of a paragraph
+ /// (usually before a section or table)
+ bool bIsOutsideOfParagraph);
+
+ virtual ~XMLChangeImportContext() override;
+
+ virtual void SAL_CALL startFastElement(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+
+private:
+ Element m_Element;
+ bool m_bIsOutsideOfParagraph;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLChangeInfoContext.cxx b/xmloff/source/text/XMLChangeInfoContext.cxx
new file mode 100644
index 0000000000..8782013966
--- /dev/null
+++ b/xmloff/source/text/XMLChangeInfoContext.cxx
@@ -0,0 +1,86 @@
+/* -*- 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 "XMLChangeInfoContext.hxx"
+#include "XMLChangedRegionImportContext.hxx"
+#include <XMLStringBufferImportContext.hxx>
+#include <com/sun/star/uno/Reference.h>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <sal/log.hxx>
+
+
+using namespace ::xmloff::token;
+
+using ::com::sun::star::uno::Reference;
+
+
+XMLChangeInfoContext::XMLChangeInfoContext(
+ SvXMLImport& rImport,
+ XMLChangedRegionImportContext& rPParent,
+ const OUString& rChangeType)
+: SvXMLImportContext(rImport)
+, rType(rChangeType)
+, rChangedRegion(rPParent)
+{
+}
+
+XMLChangeInfoContext::~XMLChangeInfoContext()
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLChangeInfoContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
+{
+ SvXMLImportContextRef xContext;
+
+ switch (nElement)
+ {
+ case XML_ELEMENT(DC, XML_CREATOR):
+ xContext = new XMLStringBufferImportContext(GetImport(), sAuthorBuffer);
+ break;
+ case XML_ELEMENT(DC, XML_DATE):
+ xContext = new XMLStringBufferImportContext(GetImport(), sDateTimeBuffer);
+ break;
+ case XML_ELEMENT(LO_EXT, XML_MOVE_ID):
+ xContext = new XMLStringBufferImportContext(GetImport(), sMovedIDBuffer);
+ break;
+ case XML_ELEMENT(TEXT, XML_P):
+ case XML_ELEMENT(LO_EXT, XML_P):
+ xContext = new XMLStringBufferImportContext(GetImport(), sCommentBuffer);
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ }
+
+ return xContext;
+}
+
+void XMLChangeInfoContext::endFastElement(sal_Int32 )
+{
+ // set values at changed region context
+ rChangedRegion.SetChangeInfo(rType, sAuthorBuffer.makeStringAndClear(),
+ sCommentBuffer.makeStringAndClear(), sDateTimeBuffer,
+ sMovedIDBuffer.makeStringAndClear());
+ sDateTimeBuffer.setLength(0);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLChangeInfoContext.hxx b/xmloff/source/text/XMLChangeInfoContext.hxx
new file mode 100644
index 0000000000..994e285d04
--- /dev/null
+++ b/xmloff/source/text/XMLChangeInfoContext.hxx
@@ -0,0 +1,69 @@
+/* -*- 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 .
+ */
+
+
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <com/sun/star/uno/Reference.h>
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+
+namespace com::sun::star {
+ namespace xml::sax { class XAttributeList; }
+}
+class XMLChangedRegionImportContext;
+
+
+/**
+ * Import <office:change-info> elements as children of <text:changed-region>
+ * elements. The attribute values will be passed to the enclosing
+ * XMLChangedRegionImportContext (which has to be passed down in the
+ * constructor).
+ */
+class XMLChangeInfoContext : public SvXMLImportContext
+{
+ const OUString& rType;
+
+ OUStringBuffer sAuthorBuffer;
+ OUStringBuffer sDateTimeBuffer;
+ OUStringBuffer sMovedIDBuffer;
+ OUStringBuffer sCommentBuffer;
+
+ XMLChangedRegionImportContext& rChangedRegion;
+
+public:
+
+
+ XMLChangeInfoContext(
+ SvXMLImport& rImport,
+ XMLChangedRegionImportContext& rChangedRegion,
+ const OUString& rChangeType);
+
+ virtual ~XMLChangeInfoContext() override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLChangedRegionImportContext.cxx b/xmloff/source/text/XMLChangedRegionImportContext.cxx
new file mode 100644
index 0000000000..7143ee4d08
--- /dev/null
+++ b/xmloff/source/text/XMLChangedRegionImportContext.cxx
@@ -0,0 +1,176 @@
+/* -*- 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 "XMLChangedRegionImportContext.hxx"
+#include "XMLChangeElementImportContext.hxx"
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/text/XTextCursor.hpp>
+
+#include <sal/log.hxx>
+#include <sax/tools/converter.hxx>
+
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmltoken.hxx>
+
+
+using namespace ::xmloff::token;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::text::XTextCursor;
+using namespace ::com::sun::star;
+
+
+XMLChangedRegionImportContext::XMLChangedRegionImportContext(SvXMLImport& rImport) :
+ SvXMLImportContext(rImport),
+ bMergeLastPara(true)
+{
+}
+
+XMLChangedRegionImportContext::~XMLChangedRegionImportContext()
+{
+}
+
+void XMLChangedRegionImportContext::startFastElement(
+ sal_Int32 /*nElement*/,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ // process attributes: id
+ bool bHaveXmlId( false );
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ switch(aIter.getToken())
+ {
+ case XML_ELEMENT(XML, XML_ID):
+ {
+ sID = aIter.toString();
+ bHaveXmlId = true;
+ break;
+ }
+ case XML_ELEMENT(TEXT, XML_ID):
+ {
+ if (!bHaveXmlId) { sID = aIter.toString(); }
+ break;
+ }
+ case XML_ELEMENT(TEXT, XML_MERGE_LAST_PARAGRAPH):
+ {
+ bool bTmp(false);
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bMergeLastPara = bTmp;
+ }
+ break;
+ }
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLChangedRegionImportContext::createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
+{
+ SvXMLImportContextRef xContext;
+
+ // from the ODF 1.2 standard :
+ // The <text:changed-region> element has the following child elements:
+ // <text:deletion>, <text:format-change> and <text:insertion>.
+ if (nElement == XML_ELEMENT(TEXT, XML_INSERTION) ||
+ nElement == XML_ELEMENT(TEXT, XML_DELETION) ||
+ nElement == XML_ELEMENT(TEXT, XML_FORMAT_CHANGE) )
+ {
+ // create XMLChangeElementImportContext for all kinds of changes
+ xContext = new XMLChangeElementImportContext(
+ GetImport(),
+ nElement == XML_ELEMENT(TEXT, XML_DELETION),
+ *this,
+ SvXMLImport::getNameFromToken(nElement));
+ }
+ else
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+
+ // illegal element content! TODO: discard the redlines
+ // for the moment -> use text
+ // or default if text fail
+
+ return xContext;
+}
+
+void XMLChangedRegionImportContext::endFastElement(sal_Int32 )
+{
+ // restore old XCursor (if necessary)
+ if (xOldCursor.is())
+ {
+ // delete last paragraph
+ // (one extra paragraph was inserted in the beginning)
+ try
+ {
+ GetImport().GetTextImport()->DeleteParagraph();
+ }
+ catch (uno::Exception const&)
+ { // cursor may be disposed - must reset to old cursor!
+ SAL_INFO("xmloff.text", "XMLChangedRegionImportContext: delete paragraph failed");
+ }
+
+ GetImport().GetTextImport()->SetCursor(xOldCursor);
+ xOldCursor = nullptr;
+ }
+}
+
+void XMLChangedRegionImportContext::SetChangeInfo(
+ const OUString& rType,
+ const OUString& rAuthor,
+ const OUString& rComment,
+ std::u16string_view rDate,
+ const OUString& rMovedID)
+{
+ util::DateTime aDateTime;
+ if (::sax::Converter::parseDateTime(aDateTime, rDate))
+ {
+ GetImport().GetTextImport()->RedlineAdd(
+ rType, sID, rAuthor, rComment, aDateTime, rMovedID, bMergeLastPara);
+ }
+}
+
+void XMLChangedRegionImportContext::UseRedlineText()
+{
+ // if we haven't already installed the redline cursor, do it now
+ if ( xOldCursor.is())
+ return;
+
+ // get TextImportHelper and old Cursor
+ rtl::Reference<XMLTextImportHelper> rHelper(GetImport().GetTextImport());
+ Reference<XTextCursor> xCursor( rHelper->GetCursor() );
+
+ // create Redline and new Cursor
+ Reference<XTextCursor> xNewCursor =
+ rHelper->RedlineCreateText(xCursor, sID);
+
+ if (xNewCursor.is())
+ {
+ // save old cursor and install new one
+ xOldCursor = xCursor;
+ rHelper->SetCursor( xNewCursor );
+ }
+ // else: leave as is
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLChangedRegionImportContext.hxx b/xmloff/source/text/XMLChangedRegionImportContext.hxx
new file mode 100644
index 0000000000..e05e97c932
--- /dev/null
+++ b/xmloff/source/text/XMLChangedRegionImportContext.hxx
@@ -0,0 +1,82 @@
+/* -*- 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 .
+ */
+
+
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <com/sun/star/uno/Reference.h>
+
+
+namespace com::sun::star {
+ namespace text {
+ class XTextCursor;
+ }
+ namespace xml::sax {
+ class XAttributeList;
+ }
+}
+
+/**
+ * Import <text:changed-region> elements contained in a
+ * <text:tracked-changes> element.
+ */
+class XMLChangedRegionImportContext : public SvXMLImportContext
+{
+ /// if we replace the current XTextCursor/XText by the ones for
+ /// the redline, we remember the old cursor here.
+ css::uno::Reference<css::text::XTextCursor> xOldCursor;
+
+ /// redline-ID
+ OUString sID;
+
+ /// merge-last-paragraph flag
+ bool bMergeLastPara;
+
+public:
+
+
+ XMLChangedRegionImportContext(SvXMLImport& rImport);
+
+ virtual ~XMLChangedRegionImportContext() override;
+
+ virtual void SAL_CALL startFastElement(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+
+ /// change info: To be called from change-info context
+ void SetChangeInfo(const OUString& rType,
+ const OUString& rAuthor,
+ const OUString& rComment,
+ std::u16string_view rDate,
+ const OUString& rMovedId);
+
+ /// create redline XText/XTextCursor on demand and register with
+ /// XMLTextImportHelper
+ void UseRedlineText();
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLComplexColorContext.cxx b/xmloff/source/text/XMLComplexColorContext.cxx
new file mode 100644
index 0000000000..c580b02225
--- /dev/null
+++ b/xmloff/source/text/XMLComplexColorContext.cxx
@@ -0,0 +1,172 @@
+/* -*- 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 <sal/log.hxx>
+#include <sax/tools/converter.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlement.hxx>
+#include <xmloff/xmlprhdl.hxx>
+#include <xmloff/XMLComplexColorContext.hxx>
+#include <docmodel/uno/UnoComplexColor.hxx>
+
+using namespace css;
+using namespace xmloff::token;
+
+SvXMLEnumMapEntry<sal_Int16> const pXML_ThemeColor_Enum[] = { { XML_NONE, -1 },
+ { XML_DARK1, 0 },
+ { XML_LIGHT1, 1 },
+ { XML_DARK2, 2 },
+ { XML_LIGHT2, 3 },
+ { XML_ACCENT1, 4 },
+ { XML_ACCENT2, 5 },
+ { XML_ACCENT3, 6 },
+ { XML_ACCENT4, 7 },
+ { XML_ACCENT5, 8 },
+ { XML_ACCENT6, 9 },
+ { XML_HYPERLINK, 10 },
+ { XML_FOLLOWED_HYPERLINK, 11 },
+ { XML_TOKEN_INVALID, 0 } };
+
+XMLComplexColorImport::XMLComplexColorImport(model::ComplexColor& rComplexColor)
+ : mrComplexColor(rComplexColor)
+{
+}
+
+void XMLComplexColorImport::fillAttributes(
+ const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
+{
+ for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
+ {
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(LO_EXT, XML_THEME_TYPE):
+ {
+ sal_Int16 nValue = -1;
+ if (SvXMLUnitConverter::convertEnum(nValue, aIter.toView(), pXML_ThemeColor_Enum))
+ {
+ mrComplexColor.setThemeColor(model::convertToThemeColorType(nValue));
+ }
+ break;
+ }
+ case XML_ELEMENT(LO_EXT, XML_COLOR_TYPE):
+ {
+ const OUString aValue = aIter.toString();
+ if (aValue == u"theme")
+ mrComplexColor.setType(model::ColorType::Theme);
+ // TODO - handle other color types
+ break;
+ }
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ break;
+ }
+ }
+}
+
+bool XMLComplexColorImport::handleTransformContext(
+ sal_Int32 nElement, const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList)
+{
+ if (nElement == XML_ELEMENT(LO_EXT, XML_TRANSFORMATION))
+ {
+ auto eTransformationType = model::TransformationType::Undefined;
+ sal_Int16 nTransformationValue = 0;
+ for (auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList))
+ {
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(LO_EXT, XML_TYPE):
+ {
+ const OUString aValue = aIter.toString();
+ if (aValue == u"tint")
+ eTransformationType = model::TransformationType::Tint;
+ else if (aValue == u"shade")
+ eTransformationType = model::TransformationType::Shade;
+ else if (aValue == u"lumoff")
+ eTransformationType = model::TransformationType::LumOff;
+ else if (aValue == u"lummod")
+ eTransformationType = model::TransformationType::LumMod;
+ break;
+ }
+ case XML_ELEMENT(LO_EXT, XML_VALUE):
+ {
+ sal_Int32 nValue;
+ if (::sax::Converter::convertNumber(nValue, aIter.toView(), SHRT_MIN, SHRT_MAX))
+ nTransformationValue = static_cast<sal_Int16>(nValue);
+ break;
+ }
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ break;
+ }
+ }
+ mrComplexColor.addTransformation({ eTransformationType, nTransformationValue });
+ return true;
+ }
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ return false;
+}
+
+XMLPropertyComplexColorContext::XMLPropertyComplexColorContext(
+ SvXMLImport& rImport, sal_Int32 nElement,
+ const uno::Reference<xml::sax::XFastAttributeList>& xAttrList, const XMLPropertyState& rProp,
+ std::vector<XMLPropertyState>& rProps)
+ : XMLElementPropertyContext(rImport, nElement, rProp, rProps)
+ , mnRootElement(nElement)
+ , maComplexColorImport(maComplexColor)
+{
+ maComplexColorImport.fillAttributes(xAttrList);
+}
+
+css::uno::Reference<css::xml::sax::XFastContextHandler>
+XMLPropertyComplexColorContext::createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList)
+{
+ if (maComplexColorImport.handleTransformContext(nElement, xAttrList))
+ return this;
+ return nullptr;
+}
+
+void XMLPropertyComplexColorContext::endFastElement(sal_Int32 nElement)
+{
+ if (nElement == mnRootElement)
+ {
+ if (getComplexColor().getThemeColorType() != model::ThemeColorType::Unknown)
+ {
+ aProp.maValue <<= model::color::createXComplexColor(getComplexColor());
+ SetInsert(true);
+ }
+ }
+ XMLElementPropertyContext::endFastElement(nElement);
+}
+
+XMLComplexColorContext::XMLComplexColorContext(
+ SvXMLImport& rImport, model::ComplexColor& rComplexColor,
+ const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
+ : SvXMLImportContext(rImport)
+ , maComplexColorImport(rComplexColor)
+{
+ maComplexColorImport.fillAttributes(xAttrList);
+}
+
+css::uno::Reference<css::xml::sax::XFastContextHandler>
+XMLComplexColorContext::createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList)
+{
+ if (maComplexColorImport.handleTransformContext(nElement, xAttrList))
+ return this;
+ return nullptr;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLComplexColorExport.cxx b/xmloff/source/text/XMLComplexColorExport.cxx
new file mode 100644
index 0000000000..feac9d0d6e
--- /dev/null
+++ b/xmloff/source/text/XMLComplexColorExport.cxx
@@ -0,0 +1,97 @@
+/* -*- 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 <xmloff/XMLComplexColorExport.hxx>
+
+#include <sal/config.h>
+
+#include <docmodel/uno/UnoComplexColor.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <array>
+
+using namespace css;
+using namespace ::xmloff::token;
+
+XMLComplexColorExport::XMLComplexColorExport(SvXMLExport& rExport)
+ : mrExport(rExport)
+{
+}
+
+namespace
+{
+constexpr const std::array<XMLTokenEnum, 12> constThemeColorTypeToToken{
+ XML_DARK1, XML_LIGHT1, XML_DARK2, XML_LIGHT2, XML_ACCENT1, XML_ACCENT2,
+ XML_ACCENT3, XML_ACCENT4, XML_ACCENT5, XML_ACCENT6, XML_HYPERLINK, XML_FOLLOWED_HYPERLINK
+};
+}
+
+void XMLComplexColorExport::doExport(model::ComplexColor const& rComplexColor, sal_uInt16 nPrefix,
+ const OUString& rLocalName)
+{
+ auto eThemeType = rComplexColor.getThemeColorType();
+ if (eThemeType == model::ThemeColorType::Unknown)
+ return;
+
+ XMLTokenEnum nToken = constThemeColorTypeToToken[sal_Int16(eThemeType)];
+ mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_THEME_TYPE, nToken);
+ mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_COLOR_TYPE, "theme");
+ SvXMLElementExport aComplexColorElement(mrExport, nPrefix, rLocalName, true, true);
+
+ for (auto const& rTransform : rComplexColor.getTransformations())
+ {
+ OUString aType;
+ switch (rTransform.meType)
+ {
+ case model::TransformationType::Tint:
+ aType = "tint";
+ break;
+ case model::TransformationType::Shade:
+ aType = "shade";
+ break;
+ case model::TransformationType::LumMod:
+ aType = "lummod";
+ break;
+ case model::TransformationType::LumOff:
+ aType = "lumoff";
+ break;
+ default:
+ break;
+ }
+ if (!aType.isEmpty())
+ {
+ mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_TYPE, aType);
+ mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_VALUE,
+ OUString::number(rTransform.mnValue));
+ SvXMLElementExport aTransformElement(mrExport, XML_NAMESPACE_LO_EXT, XML_TRANSFORMATION,
+ true, true);
+ }
+ }
+}
+
+void XMLComplexColorExport::exportComplexColor(model::ComplexColor const& rComplexColor,
+ sal_uInt16 nPrefix, XMLTokenEnum nToken)
+{
+ doExport(rComplexColor, nPrefix, GetXMLToken(nToken));
+}
+
+void XMLComplexColorExport::exportXML(const uno::Any& rAny, sal_uInt16 nPrefix,
+ const OUString& rLocalName)
+{
+ uno::Reference<util::XComplexColor> xComplexColor;
+ rAny >>= xComplexColor;
+ if (!xComplexColor.is())
+ return;
+
+ model::ComplexColor aComplexColor = model::color::getFromXComplexColor(xComplexColor);
+ doExport(aComplexColor, nPrefix, rLocalName);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLFootnoteBodyImportContext.cxx b/xmloff/source/text/XMLFootnoteBodyImportContext.cxx
new file mode 100644
index 0000000000..2e9b76ccaa
--- /dev/null
+++ b/xmloff/source/text/XMLFootnoteBodyImportContext.cxx
@@ -0,0 +1,47 @@
+/* -*- 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 "XMLFootnoteBodyImportContext.hxx"
+
+#include <rtl/ustring.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/txtimp.hxx>
+#include <com/sun/star/xml/sax/XAttributeList.hpp>
+
+using ::com::sun::star::uno::Reference;
+
+
+XMLFootnoteBodyImportContext::XMLFootnoteBodyImportContext( SvXMLImport& rImport ) :
+ SvXMLImportContext(rImport)
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLFootnoteBodyImportContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ // return text context
+ return
+ GetImport().GetTextImport()->CreateTextChildContext(GetImport(),
+ nElement,
+ xAttrList,
+ XMLTextType::Footnote);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLFootnoteBodyImportContext.hxx b/xmloff/source/text/XMLFootnoteBodyImportContext.hxx
new file mode 100644
index 0000000000..d52557797e
--- /dev/null
+++ b/xmloff/source/text/XMLFootnoteBodyImportContext.hxx
@@ -0,0 +1,49 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <com/sun/star/uno/Reference.h>
+
+
+namespace com::sun::star {
+ namespace xml::sax {
+ class XAttributeList;
+ }
+}
+
+
+/// import foot- and endnote body elements (<text:footnote-body>)
+class XMLFootnoteBodyImportContext : public SvXMLImportContext
+{
+
+public:
+
+ XMLFootnoteBodyImportContext( SvXMLImport& rImport );
+
+protected:
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLFootnoteConfigurationImportContext.cxx b/xmloff/source/text/XMLFootnoteConfigurationImportContext.cxx
new file mode 100644
index 0000000000..8e67b2d909
--- /dev/null
+++ b/xmloff/source/text/XMLFootnoteConfigurationImportContext.cxx
@@ -0,0 +1,335 @@
+/* -*- 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 <XMLFootnoteConfigurationImportContext.hxx>
+
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+
+#include <sax/tools/converter.hxx>
+
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlement.hxx>
+
+#include <xmloff/families.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/xml/sax/XAttributeList.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/text/XFootnotesSupplier.hpp>
+#include <com/sun/star/text/XEndnotesSupplier.hpp>
+#include <com/sun/star/text/FootnoteNumbering.hpp>
+#include <com/sun/star/style/NumberingType.hpp>
+
+
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::style;
+using namespace ::com::sun::star::xml::sax;
+using namespace ::xmloff::token;
+
+
+// XMLFootnoteConfigHelper
+
+namespace {
+
+/// local helper class for import of quo-vadis and ergo-sum elements
+class XMLFootnoteConfigHelper : public SvXMLImportContext
+{
+ OUStringBuffer sBuffer;
+ XMLFootnoteConfigurationImportContext& rConfig;
+ bool bIsBegin;
+
+public:
+
+ XMLFootnoteConfigHelper(
+ SvXMLImport& rImport,
+ XMLFootnoteConfigurationImportContext& rConfigImport,
+ bool bBegin);
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual void SAL_CALL characters( const OUString& rChars ) override;
+};
+
+}
+
+XMLFootnoteConfigHelper::XMLFootnoteConfigHelper(
+ SvXMLImport& rImport,
+ XMLFootnoteConfigurationImportContext& rConfigImport,
+ bool bBegin)
+: SvXMLImportContext(rImport)
+, rConfig(rConfigImport)
+, bIsBegin(bBegin)
+{
+}
+
+void XMLFootnoteConfigHelper::endFastElement(sal_Int32 )
+{
+ if (bIsBegin)
+ {
+ rConfig.SetBeginNotice(sBuffer.makeStringAndClear());
+ }
+ else
+ {
+ rConfig.SetEndNotice(sBuffer.makeStringAndClear());
+ }
+// rConfig = NULL; // import contexts are ref-counted
+}
+
+void XMLFootnoteConfigHelper::characters( const OUString& rChars )
+{
+ sBuffer.append(rChars);
+}
+
+
+// XMLFootnoteConfigurationImportContext
+
+constexpr OUStringLiteral gsPropertyAnchorCharStyleName(u"AnchorCharStyleName");
+constexpr OUStringLiteral gsPropertyCharStyleName(u"CharStyleName");
+constexpr OUStringLiteral gsPropertyNumberingType(u"NumberingType");
+constexpr OUStringLiteral gsPropertyPageStyleName(u"PageStyleName");
+constexpr OUStringLiteral gsPropertyParagraphStyleName(u"ParaStyleName");
+constexpr OUStringLiteral gsPropertyPrefix(u"Prefix");
+constexpr OUStringLiteral gsPropertyStartAt(u"StartAt");
+constexpr OUStringLiteral gsPropertySuffix(u"Suffix");
+constexpr OUStringLiteral gsPropertyPositionEndOfDoc(u"PositionEndOfDoc");
+constexpr OUStringLiteral gsPropertyFootnoteCounting(u"FootnoteCounting");
+constexpr OUStringLiteral gsPropertyEndNotice(u"EndNotice");
+constexpr OUStringLiteral gsPropertyBeginNotice(u"BeginNotice");
+
+XMLFootnoteConfigurationImportContext::XMLFootnoteConfigurationImportContext(
+ SvXMLImport& rImport,
+ sal_Int32 /*nElement*/,
+ const Reference<XFastAttributeList> & xAttrList)
+: SvXMLStyleContext(rImport, XmlStyleFamily::TEXT_FOOTNOTECONFIG)
+, sNumFormat("1")
+, sNumSync("false")
+, nOffset(0)
+, nNumbering(FootnoteNumbering::PER_PAGE)
+, bPosition(false)
+, bIsEndnote(false)
+{
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
+ {
+ if( aIter.getToken() == XML_ELEMENT(TEXT, XML_NOTE_CLASS) )
+ {
+ if( IsXMLToken(aIter, XML_ENDNOTE ) )
+ {
+ bIsEndnote = true;
+ SetFamily( XmlStyleFamily::TEXT_FOOTNOTECONFIG );
+ }
+ break;
+ }
+ }
+
+}
+XMLFootnoteConfigurationImportContext::~XMLFootnoteConfigurationImportContext()
+{
+}
+
+SvXMLEnumMapEntry<sal_Int16> const aFootnoteNumberingMap[] =
+{
+ { XML_PAGE, FootnoteNumbering::PER_PAGE },
+ { XML_CHAPTER, FootnoteNumbering::PER_CHAPTER },
+ { XML_DOCUMENT, FootnoteNumbering::PER_DOCUMENT },
+ { XML_TOKEN_INVALID, 0 },
+};
+
+void XMLFootnoteConfigurationImportContext::SetAttribute( sal_Int32 nElement,
+ const OUString& rValue )
+{
+ switch (nElement)
+ {
+ case XML_ELEMENT(TEXT, XML_CITATION_STYLE_NAME):
+ sCitationStyle = rValue;
+ break;
+ case XML_ELEMENT(TEXT, XML_CITATION_BODY_STYLE_NAME):
+ sAnchorStyle = rValue;
+ break;
+ case XML_ELEMENT(TEXT, XML_DEFAULT_STYLE_NAME):
+ sDefaultStyle = rValue;
+ break;
+ case XML_ELEMENT(TEXT, XML_MASTER_PAGE_NAME):
+ sPageStyle = rValue;
+ break;
+ case XML_ELEMENT(TEXT, XML_START_VALUE):
+ case XML_ELEMENT(TEXT, XML_OFFSET): // for backwards compatibility with SRC630 & earlier
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertNumber(nTmp, rValue))
+ {
+ nOffset = static_cast<sal_uInt16>(nTmp);
+ }
+ break;
+ }
+ case XML_ELEMENT(STYLE, XML_NUM_PREFIX):
+ case XML_ELEMENT(TEXT, XML_NUM_PREFIX): // for backwards compatibility with SRC630 & earlier
+ sPrefix = rValue;
+ break;
+ case XML_ELEMENT(STYLE, XML_NUM_SUFFIX):
+ case XML_ELEMENT(TEXT, XML_NUM_SUFFIX): // for backwards compatibility with SRC630 & earlier
+ sSuffix = rValue;
+ break;
+ case XML_ELEMENT(STYLE, XML_NUM_FORMAT):
+ sNumFormat = rValue;
+ break;
+ case XML_ELEMENT(STYLE, XML_NUM_LETTER_SYNC):
+ sNumSync = rValue;
+ break;
+ case XML_ELEMENT(TEXT, XML_START_NUMBERING_AT):
+ {
+ (void)SvXMLUnitConverter::convertEnum(nNumbering, rValue,
+ aFootnoteNumberingMap);
+ break;
+ }
+ case XML_ELEMENT(TEXT, XML_FOOTNOTES_POSITION):
+ bPosition = IsXMLToken( rValue, XML_DOCUMENT );
+ break;
+ default:
+ ; // ignore
+ }
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLFootnoteConfigurationImportContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
+{
+ css::uno::Reference< css::xml::sax::XFastContextHandler > xContext;
+
+ if (bIsEndnote)
+ return nullptr;
+
+ switch (nElement)
+ {
+ case XML_ELEMENT(TEXT, XML_FOOTNOTE_CONTINUATION_NOTICE_FORWARD):
+ xContext = new XMLFootnoteConfigHelper(GetImport(), *this, false);
+ break;
+ case XML_ELEMENT(TEXT, XML_FOOTNOTE_CONTINUATION_NOTICE_BACKWARD):
+ xContext = new XMLFootnoteConfigHelper(GetImport(), *this, true);
+ break;
+ }
+
+ return xContext;
+}
+
+// Rename method <CreateAndInsertLate(..)> to <Finish(..)> (#i40597#)
+void XMLFootnoteConfigurationImportContext::Finish( bool bOverwrite )
+{
+
+ if (!bOverwrite)
+ return;
+
+ if (bIsEndnote)
+ {
+ Reference<XEndnotesSupplier> xSupplier(
+ GetImport().GetModel(), UNO_QUERY);
+ if (xSupplier.is())
+ {
+ ProcessSettings(xSupplier->getEndnoteSettings());
+ }
+ }
+ else
+ {
+ Reference<XFootnotesSupplier> xSupplier(
+ GetImport().GetModel(), UNO_QUERY);
+ if (xSupplier.is())
+ {
+ ProcessSettings(xSupplier->getFootnoteSettings());
+ }
+ }
+ // else: ignore (there's only one configuration, so we can only overwrite)
+}
+
+void XMLFootnoteConfigurationImportContext::ProcessSettings(
+ const Reference<XPropertySet> & rConfig)
+{
+ Any aAny;
+
+ if (!sCitationStyle.isEmpty())
+ {
+ aAny <<= GetImport().GetStyleDisplayName(
+ XmlStyleFamily::TEXT_TEXT, sCitationStyle );
+ rConfig->setPropertyValue(gsPropertyCharStyleName, aAny);
+ }
+
+ if (!sAnchorStyle.isEmpty())
+ {
+ aAny <<= GetImport().GetStyleDisplayName(
+ XmlStyleFamily::TEXT_TEXT, sAnchorStyle );
+ rConfig->setPropertyValue(gsPropertyAnchorCharStyleName, aAny);
+ }
+
+ if (!sPageStyle.isEmpty())
+ {
+ aAny <<= GetImport().GetStyleDisplayName(
+ XmlStyleFamily::MASTER_PAGE, sPageStyle );
+ rConfig->setPropertyValue(gsPropertyPageStyleName, aAny);
+ }
+
+ if (!sDefaultStyle.isEmpty())
+ {
+ aAny <<= GetImport().GetStyleDisplayName(
+ XmlStyleFamily::TEXT_PARAGRAPH, sDefaultStyle );
+ rConfig->setPropertyValue(gsPropertyParagraphStyleName, aAny);
+ }
+
+ rConfig->setPropertyValue(gsPropertyPrefix, Any(sPrefix));
+
+ rConfig->setPropertyValue(gsPropertySuffix, Any(sSuffix));
+
+ sal_Int16 nNumType = NumberingType::ARABIC;
+ GetImport().GetMM100UnitConverter().convertNumFormat( nNumType, sNumFormat,
+ sNumSync );
+ // #i61399: Corrupt file? It contains "Bullet" as numbering style for footnotes.
+ // Okay, even it seems to be corrupt, we will oversee this and set the style to ARABIC
+ if( NumberingType::CHAR_SPECIAL == nNumType )
+ nNumType = NumberingType::ARABIC;
+
+ rConfig->setPropertyValue(gsPropertyNumberingType, Any(nNumType));
+
+ rConfig->setPropertyValue(gsPropertyStartAt, Any(nOffset));
+
+ if (!bIsEndnote)
+ {
+ rConfig->setPropertyValue(gsPropertyPositionEndOfDoc, Any(bPosition));
+ rConfig->setPropertyValue(gsPropertyFootnoteCounting, Any(nNumbering));
+ rConfig->setPropertyValue(gsPropertyEndNotice, Any(sEndNotice));
+ rConfig->setPropertyValue(gsPropertyBeginNotice, Any(sBeginNotice));
+ }
+}
+
+void XMLFootnoteConfigurationImportContext::SetBeginNotice(
+ const OUString& sText)
+{
+ sBeginNotice = sText;
+}
+
+void XMLFootnoteConfigurationImportContext::SetEndNotice(
+ const OUString& sText)
+{
+ sEndNotice = sText;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLFootnoteImportContext.cxx b/xmloff/source/text/XMLFootnoteImportContext.cxx
new file mode 100644
index 0000000000..cf206e5d6e
--- /dev/null
+++ b/xmloff/source/text/XMLFootnoteImportContext.cxx
@@ -0,0 +1,168 @@
+/* -*- 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 "XMLFootnoteImportContext.hxx"
+
+#include <rtl/ustring.hxx>
+#include <sal/log.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/txtimp.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+
+#include "XMLFootnoteBodyImportContext.hxx"
+
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/xml/sax/XAttributeList.hpp>
+#include <com/sun/star/text/XTextContent.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/text/XFootnote.hpp>
+
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::xml::sax;
+using namespace ::xmloff::token;
+
+XMLFootnoteImportContext::XMLFootnoteImportContext(
+ SvXMLImport& rImport,
+ XMLTextImportHelper& rHlp )
+: SvXMLImportContext(rImport)
+, mbListContextPushed(false)
+, rHelper(rHlp)
+{
+}
+
+void XMLFootnoteImportContext::startFastElement(
+ sal_Int32 /*nElement*/,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ // create footnote
+ Reference<XMultiServiceFactory> xFactory(GetImport().GetModel(),
+ UNO_QUERY);
+ if( !xFactory.is() )
+ return;
+
+ // create endnote or footnote
+ bool bIsEndnote = false;
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ if( aIter.getToken() == XML_ELEMENT(TEXT, XML_NOTE_CLASS) )
+ {
+ if( IsXMLToken( aIter, XML_ENDNOTE ) )
+ bIsEndnote = true;
+ break;
+ }
+ }
+
+ Reference<XInterface> xIfc = xFactory->createInstance(
+ bIsEndnote ?
+ OUString("com.sun.star.text.Endnote") :
+ OUString("com.sun.star.text.Footnote") );
+
+ // attach footnote to document
+ Reference<XTextContent> xTextContent(xIfc, UNO_QUERY);
+ rHelper.InsertTextContent(xTextContent);
+
+ // process id attribute
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ if( aIter.getToken() == XML_ELEMENT(TEXT, XML_ID) )
+ {
+ // get ID ...
+ Reference<XPropertySet> xPropertySet(xTextContent, UNO_QUERY);
+ Any aAny =xPropertySet->getPropertyValue("ReferenceId");
+ sal_Int16 nID = 0;
+ aAny >>= nID;
+
+ // ... and insert into map
+ rHelper.InsertFootnoteID( aIter.toString(), nID);
+ break;
+ }
+ }
+
+ // save old cursor and install new one
+ xOldCursor = rHelper.GetCursor();
+ Reference<XText> xText(xTextContent, UNO_QUERY);
+ rHelper.SetCursor(xText->createTextCursor());
+
+ // remember old list item and block (#89891#) and reset them
+ // for the footnote
+ rHelper.PushListContext();
+ mbListContextPushed = true;
+
+ // remember footnote (for CreateChildContext)
+ xFootnote.set(xTextContent, UNO_QUERY);
+
+ // else: ignore footnote! Content will be merged into document.
+}
+
+void XMLFootnoteImportContext::endFastElement(sal_Int32 )
+{
+ // get rid of last dummy paragraph
+ rHelper.DeleteParagraph();
+
+ // reinstall old cursor
+ rHelper.SetCursor(xOldCursor);
+
+ // reinstall old list item
+ if (mbListContextPushed) {
+ rHelper.PopListContext();
+ }
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLFootnoteImportContext::createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ SvXMLImportContextRef xContext;
+
+ switch(nElement)
+ {
+ case XML_ELEMENT(TEXT, XML_NOTE_CITATION):
+ {
+ // little hack: we only care for one attribute of the citation
+ // element. We handle that here, and then return a
+ // default context.
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ if ( aIter.getToken() == XML_ELEMENT(TEXT, XML_LABEL) )
+ xFootnote->setLabel(aIter.toString());
+ }
+
+ // ignore content: return default context
+ break;
+ }
+
+ case XML_ELEMENT(TEXT, XML_NOTE_BODY):
+ // return footnote body
+ xContext = new XMLFootnoteBodyImportContext(GetImport());
+ break;
+
+ default:
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ }
+
+ return xContext;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLFootnoteImportContext.hxx b/xmloff/source/text/XMLFootnoteImportContext.hxx
new file mode 100644
index 0000000000..d05b7b631c
--- /dev/null
+++ b/xmloff/source/text/XMLFootnoteImportContext.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/.
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <com/sun/star/uno/Reference.h>
+
+
+namespace com::sun::star {
+ namespace text {
+ class XTextCursor;
+ class XFootnote;
+ }
+ namespace xml::sax {
+ class XAttributeList;
+ }
+}
+class XMLTextImportHelper;
+
+/// import footnote elements (<text:footnote>)
+class XMLFootnoteImportContext : public SvXMLImportContext
+{
+ /// old document cursor
+ css::uno::Reference<css::text::XTextCursor> xOldCursor;
+
+ /// old list item and block (#89891#)
+ bool mbListContextPushed;
+
+ /// text import helper; holds current XTextCursor (and XText)
+ XMLTextImportHelper& rHelper;
+
+ /// the footnote
+ css::uno::Reference<css::text::XFootnote> xFootnote;
+
+public:
+
+
+ XMLFootnoteImportContext(
+ SvXMLImport& rImport,
+ XMLTextImportHelper& rHlp );
+
+protected:
+
+ virtual void SAL_CALL startFastElement(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexAlphabeticalSourceContext.cxx b/xmloff/source/text/XMLIndexAlphabeticalSourceContext.cxx
new file mode 100644
index 0000000000..fe6013619d
--- /dev/null
+++ b/xmloff/source/text/XMLIndexAlphabeticalSourceContext.cxx
@@ -0,0 +1,212 @@
+/* -*- 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 "XMLIndexAlphabeticalSourceContext.hxx"
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+
+#include <sax/tools/converter.hxx>
+
+#include "XMLIndexTemplateContext.hxx"
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/txtimp.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <rtl/ustring.hxx>
+
+
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Any;
+using namespace ::xmloff::token;
+
+XMLIndexAlphabeticalSourceContext::XMLIndexAlphabeticalSourceContext(
+ SvXMLImport& rImport,
+ Reference<XPropertySet> & rPropSet)
+: XMLIndexSourceBaseContext(rImport, rPropSet, UseStyles::None)
+, bMainEntryStyleNameOK(false)
+, bSeparators(false)
+, bCombineEntries(true)
+, bCaseSensitive(true)
+, bEntry(false)
+, bUpperCase(false)
+, bCombineDash(false)
+, bCombinePP(true)
+, bCommaSeparated(false)
+{
+}
+
+XMLIndexAlphabeticalSourceContext::~XMLIndexAlphabeticalSourceContext()
+{
+}
+
+void XMLIndexAlphabeticalSourceContext::ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)
+{
+ bool bTmp(false);
+
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(TEXT, XML_MAIN_ENTRY_STYLE_NAME):
+ {
+ sMainEntryStyleName = aIter.toString();
+ OUString sDisplayStyleName = GetImport().GetStyleDisplayName(
+ XmlStyleFamily::TEXT_TEXT, sMainEntryStyleName );
+ const Reference < css::container::XNameContainer >&
+ rStyles = GetImport().GetTextImport()->GetTextStyles();
+ bMainEntryStyleNameOK = rStyles.is() && rStyles->hasByName( sDisplayStyleName );
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_IGNORE_CASE):
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bCaseSensitive = !bTmp;
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_ALPHABETICAL_SEPARATORS):
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bSeparators = bTmp;
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_COMBINE_ENTRIES):
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bCombineEntries = bTmp;
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_COMBINE_ENTRIES_WITH_DASH):
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bCombineDash = bTmp;
+ }
+ break;
+ case XML_ELEMENT(TEXT, XML_USE_KEYS_AS_ENTRIES):
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bEntry = bTmp;
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_COMBINE_ENTRIES_WITH_PP):
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bCombinePP = bTmp;
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_CAPITALIZE_ENTRIES):
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bUpperCase = bTmp;
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_COMMA_SEPARATED):
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bCommaSeparated = bTmp;
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_SORT_ALGORITHM):
+ sAlgorithm = aIter.toString();
+ break;
+ case XML_ELEMENT(STYLE, XML_RFC_LANGUAGE_TAG):
+ maLanguageTagODF.maRfcLanguageTag = aIter.toString();
+ break;
+ case XML_ELEMENT(FO, XML_LANGUAGE):
+ maLanguageTagODF.maLanguage = aIter.toString();
+ break;
+ case XML_ELEMENT(FO, XML_SCRIPT):
+ maLanguageTagODF.maScript = aIter.toString();
+ break;
+ case XML_ELEMENT(FO, XML_COUNTRY):
+ maLanguageTagODF.maCountry = aIter.toString();
+ break;
+
+ default:
+ XMLIndexSourceBaseContext::ProcessAttribute(aIter);
+ break;
+ }
+}
+
+void XMLIndexAlphabeticalSourceContext::endFastElement(sal_Int32 nElement)
+{
+
+ Any aAny;
+
+ if (bMainEntryStyleNameOK)
+ {
+ aAny <<= GetImport().GetStyleDisplayName(
+ XmlStyleFamily::TEXT_TEXT, sMainEntryStyleName );
+ rIndexPropertySet->setPropertyValue("MainEntryCharacterStyleName",aAny);
+ }
+
+ rIndexPropertySet->setPropertyValue("UseAlphabeticalSeparators", css::uno::Any(bSeparators));
+ rIndexPropertySet->setPropertyValue("UseCombinedEntries", css::uno::Any(bCombineEntries));
+ rIndexPropertySet->setPropertyValue("IsCaseSensitive", css::uno::Any(bCaseSensitive));
+ rIndexPropertySet->setPropertyValue("UseKeyAsEntry", css::uno::Any(bEntry));
+ rIndexPropertySet->setPropertyValue("UseUpperCase", css::uno::Any(bUpperCase));
+ rIndexPropertySet->setPropertyValue("UseDash", css::uno::Any(bCombineDash));
+ rIndexPropertySet->setPropertyValue("UsePP", css::uno::Any(bCombinePP));
+ rIndexPropertySet->setPropertyValue("IsCommaSeparated", css::uno::Any(bCommaSeparated));
+
+
+ if (!sAlgorithm.isEmpty())
+ {
+ rIndexPropertySet->setPropertyValue("SortAlgorithm", css::uno::Any(sAlgorithm));
+ }
+
+ if ( !maLanguageTagODF.isEmpty() )
+ {
+ aAny <<= maLanguageTagODF.getLanguageTag().getLocale( false);
+ rIndexPropertySet->setPropertyValue("Locale", aAny);
+ }
+
+ XMLIndexSourceBaseContext::endFastElement(nElement);
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLIndexAlphabeticalSourceContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ if ( nElement == XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_ENTRY_TEMPLATE) )
+ {
+ return new XMLIndexTemplateContext(GetImport(), rIndexPropertySet,
+ aLevelNameAlphaMap,
+ XML_OUTLINE_LEVEL,
+ aLevelStylePropNameAlphaMap,
+ aAllowedTokenTypesAlpha);
+ }
+ else
+ {
+ return XMLIndexSourceBaseContext::createFastChildContext(nElement,
+ xAttrList);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexAlphabeticalSourceContext.hxx b/xmloff/source/text/XMLIndexAlphabeticalSourceContext.hxx
new file mode 100644
index 0000000000..45fcea4ba0
--- /dev/null
+++ b/xmloff/source/text/XMLIndexAlphabeticalSourceContext.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/.
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include "XMLIndexSourceBaseContext.hxx"
+#include <xmloff/languagetagodf.hxx>
+#include <com/sun/star/uno/Reference.h>
+
+
+namespace com::sun::star {
+ namespace xml::sax { class XAttributeList; }
+ namespace beans { class XPropertySet; }
+}
+
+
+/**
+ * Import alphabetical (keyword) index source element
+ */
+class XMLIndexAlphabeticalSourceContext : public XMLIndexSourceBaseContext
+{
+ LanguageTagODF maLanguageTagODF;
+ OUString sAlgorithm;
+
+ OUString sMainEntryStyleName;
+ bool bMainEntryStyleNameOK;
+
+ bool bSeparators;
+ bool bCombineEntries;
+ bool bCaseSensitive;
+ bool bEntry;
+ bool bUpperCase;
+ bool bCombineDash;
+ bool bCombinePP;
+ bool bCommaSeparated;
+
+public:
+
+
+ XMLIndexAlphabeticalSourceContext(
+ SvXMLImport& rImport,
+ css::uno::Reference<css::beans::XPropertySet> & rPropSet);
+
+ virtual ~XMLIndexAlphabeticalSourceContext() override;
+
+protected:
+
+ virtual void ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter) override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexBibliographyConfigurationContext.cxx b/xmloff/source/text/XMLIndexBibliographyConfigurationContext.cxx
new file mode 100644
index 0000000000..e7ba5e6bae
--- /dev/null
+++ b/xmloff/source/text/XMLIndexBibliographyConfigurationContext.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/.
+ *
+ * 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 <comphelper/propertyvalue.hxx>
+#include <XMLIndexBibliographyConfigurationContext.hxx>
+#include "XMLIndexBibliographyEntryContext.hxx"
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/txtimp.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <sal/log.hxx>
+#include <sax/tools/converter.hxx>
+#include <rtl/ustring.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <comphelper/sequence.hxx>
+
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::uno;
+using namespace ::xmloff::token;
+
+using ::com::sun::star::xml::sax::XFastAttributeList;
+using ::com::sun::star::beans::PropertyValue;
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::lang::XMultiServiceFactory;
+
+
+constexpr OUString gsFieldMaster_Bibliography(u"com.sun.star.text.FieldMaster.Bibliography"_ustr);
+constexpr OUStringLiteral gsBracketBefore(u"BracketBefore");
+constexpr OUStringLiteral gsBracketAfter(u"BracketAfter");
+constexpr OUStringLiteral gsIsNumberEntries(u"IsNumberEntries");
+constexpr OUStringLiteral gsIsSortByPosition(u"IsSortByPosition");
+constexpr OUStringLiteral gsSortKeys(u"SortKeys");
+constexpr OUString gsSortKey(u"SortKey"_ustr);
+constexpr OUString gsIsSortAscending(u"IsSortAscending"_ustr);
+constexpr OUStringLiteral gsSortAlgorithm(u"SortAlgorithm");
+constexpr OUStringLiteral gsLocale(u"Locale");
+
+XMLIndexBibliographyConfigurationContext::XMLIndexBibliographyConfigurationContext(
+ SvXMLImport& rImport) :
+ SvXMLStyleContext(rImport, XmlStyleFamily::TEXT_BIBLIOGRAPHYCONFIG),
+ maLanguageTagODF(),
+ bNumberedEntries(false),
+ bSortByPosition(true)
+{
+}
+
+XMLIndexBibliographyConfigurationContext::~XMLIndexBibliographyConfigurationContext()
+{
+}
+
+void XMLIndexBibliographyConfigurationContext::SetAttribute(
+ sal_Int32 nElement,
+ const OUString& sValue)
+{
+ switch (nElement)
+ {
+ case XML_ELEMENT(TEXT, XML_PREFIX):
+ sPrefix = sValue;
+ break;
+ case XML_ELEMENT(TEXT, XML_SUFFIX):
+ sSuffix = sValue;
+ break;
+ case XML_ELEMENT(TEXT, XML_NUMBERED_ENTRIES):
+ {
+ bool bTmp(false);
+ if (::sax::Converter::convertBool(bTmp, sValue))
+ {
+ bNumberedEntries = bTmp;
+ }
+ break;
+ }
+ case XML_ELEMENT(TEXT, XML_SORT_BY_POSITION):
+ {
+ bool bTmp(false);
+ if (::sax::Converter::convertBool(bTmp, sValue))
+ {
+ bSortByPosition = bTmp;
+ }
+ break;
+ }
+ case XML_ELEMENT(TEXT, XML_SORT_ALGORITHM):
+ sAlgorithm = sValue;
+ break;
+ case XML_ELEMENT(FO, XML_LANGUAGE):
+ maLanguageTagODF.maLanguage = sValue;
+ break;
+ case XML_ELEMENT(FO, XML_SCRIPT):
+ maLanguageTagODF.maScript = sValue;
+ break;
+ case XML_ELEMENT(FO, XML_COUNTRY):
+ maLanguageTagODF.maCountry = sValue;
+ break;
+ case XML_ELEMENT(STYLE, XML_RFC_LANGUAGE_TAG):
+ maLanguageTagODF.maRfcLanguageTag = sValue;
+ break;
+ }
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLIndexBibliographyConfigurationContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ // process children here and use default context!
+ if ( nElement == XML_ELEMENT(TEXT, XML_SORT_KEY) )
+ {
+ std::string_view sKey;
+ bool bSort(true);
+
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
+ {
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(TEXT, XML_KEY):
+ sKey = aIter.toView();
+ break;
+ case XML_ELEMENT(TEXT, XML_SORT_ASCENDING):
+ {
+ bool bTmp(false);
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ bSort = bTmp;
+ break;
+ }
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ break;
+ }
+ }
+
+ // valid data?
+ sal_uInt16 nKey;
+ if (SvXMLUnitConverter::convertEnum(nKey, sKey,
+ aBibliographyDataFieldMap))
+ {
+ Sequence<PropertyValue> aKey
+ {
+ comphelper::makePropertyValue(gsSortKey, static_cast<sal_Int16>(nKey)),
+ comphelper::makePropertyValue(gsIsSortAscending, bSort)
+ };
+
+ aSortKeys.push_back(aKey);
+ }
+ }
+
+ return nullptr;
+}
+
+void XMLIndexBibliographyConfigurationContext::CreateAndInsert(bool)
+{
+ // (code almost the same as export...)
+
+ // insert and block mode is handled in insertStyleFamily
+
+ // first: get field master
+ // (we'll create one, and get the only master for this type)
+ Reference<XMultiServiceFactory> xFactory(GetImport().GetModel(),UNO_QUERY);
+ if( !xFactory.is() )
+ return;
+
+ Sequence<OUString> aServices = xFactory->getAvailableServiceNames();
+ // here we should use a method which compares in reverse order if available
+ if (comphelper::findValue(aServices, gsFieldMaster_Bibliography) == -1)
+ return;
+
+ Reference<XInterface> xIfc =
+ xFactory->createInstance(gsFieldMaster_Bibliography);
+ if( !xIfc.is() )
+ return;
+
+ Reference<XPropertySet> xPropSet( xIfc, UNO_QUERY );
+ Any aAny;
+
+ xPropSet->setPropertyValue(gsBracketAfter, Any(sSuffix));
+ xPropSet->setPropertyValue(gsBracketBefore, Any(sPrefix));
+ xPropSet->setPropertyValue(gsIsNumberEntries, Any(bNumberedEntries));
+ xPropSet->setPropertyValue(gsIsSortByPosition, Any(bSortByPosition));
+
+ if( !maLanguageTagODF.isEmpty() )
+ {
+ aAny <<= maLanguageTagODF.getLanguageTag().getLocale( false);
+ xPropSet->setPropertyValue(gsLocale, aAny);
+ }
+
+ if( !sAlgorithm.isEmpty() )
+ {
+ xPropSet->setPropertyValue(gsSortAlgorithm, Any(sAlgorithm));
+ }
+
+ Sequence<Sequence<PropertyValue> > aKeysSeq = comphelper::containerToSequence(aSortKeys);
+ xPropSet->setPropertyValue(gsSortKeys, Any(aKeysSeq));
+ // else: can't get FieldMaster -> ignore
+ // else: can't even get Factory -> ignore
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexBibliographyEntryContext.cxx b/xmloff/source/text/XMLIndexBibliographyEntryContext.cxx
new file mode 100644
index 0000000000..8ae78e9902
--- /dev/null
+++ b/xmloff/source/text/XMLIndexBibliographyEntryContext.cxx
@@ -0,0 +1,156 @@
+/* -*- 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 "XMLIndexBibliographyEntryContext.hxx"
+#include "XMLIndexTemplateContext.hxx"
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/txtimp.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlement.hxx>
+#include <com/sun/star/text/BibliographyDataField.hpp>
+#include <sal/log.hxx>
+
+
+using namespace ::com::sun::star::text;
+using namespace ::xmloff::token;
+
+using ::com::sun::star::beans::PropertyValue;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+
+XMLIndexBibliographyEntryContext::XMLIndexBibliographyEntryContext(
+ SvXMLImport& rImport,
+ XMLIndexTemplateContext& rTemplate ) :
+ XMLIndexSimpleEntryContext(rImport,
+ "TokenBibliographyDataField",
+ rTemplate),
+ nBibliographyInfo(BibliographyDataField::IDENTIFIER),
+ bBibliographyInfoOK(false)
+{
+}
+
+XMLIndexBibliographyEntryContext::~XMLIndexBibliographyEntryContext()
+{
+}
+
+const SvXMLEnumMapEntry<sal_uInt16> aBibliographyDataFieldMap[] =
+{
+ { XML_ADDRESS, BibliographyDataField::ADDRESS },
+ { XML_ANNOTE, BibliographyDataField::ANNOTE },
+ { XML_AUTHOR, BibliographyDataField::AUTHOR },
+ { XML_BIBLIOGRAPHY_TYPE, BibliographyDataField::BIBILIOGRAPHIC_TYPE },
+ // #96658#: also read old documents (bib*i*liographic...)
+ { XML_BIBILIOGRAPHIC_TYPE, BibliographyDataField::BIBILIOGRAPHIC_TYPE },
+ { XML_BOOKTITLE, BibliographyDataField::BOOKTITLE },
+ { XML_CHAPTER, BibliographyDataField::CHAPTER },
+ { XML_CUSTOM1, BibliographyDataField::CUSTOM1 },
+ { XML_CUSTOM2, BibliographyDataField::CUSTOM2 },
+ { XML_CUSTOM3, BibliographyDataField::CUSTOM3 },
+ { XML_CUSTOM4, BibliographyDataField::CUSTOM4 },
+ { XML_CUSTOM5, BibliographyDataField::CUSTOM5 },
+ { XML_EDITION, BibliographyDataField::EDITION },
+ { XML_EDITOR, BibliographyDataField::EDITOR },
+ { XML_HOWPUBLISHED, BibliographyDataField::HOWPUBLISHED },
+ { XML_IDENTIFIER, BibliographyDataField::IDENTIFIER },
+ { XML_INSTITUTION, BibliographyDataField::INSTITUTION },
+ { XML_ISBN, BibliographyDataField::ISBN },
+ { XML_JOURNAL, BibliographyDataField::JOURNAL },
+ { XML_MONTH, BibliographyDataField::MONTH },
+ { XML_NOTE, BibliographyDataField::NOTE },
+ { XML_NUMBER, BibliographyDataField::NUMBER },
+ { XML_ORGANIZATIONS, BibliographyDataField::ORGANIZATIONS },
+ { XML_PAGES, BibliographyDataField::PAGES },
+ { XML_PUBLISHER, BibliographyDataField::PUBLISHER },
+ { XML_REPORT_TYPE, BibliographyDataField::REPORT_TYPE },
+ { XML_SCHOOL, BibliographyDataField::SCHOOL },
+ { XML_SERIES, BibliographyDataField::SERIES },
+ { XML_TITLE, BibliographyDataField::TITLE },
+ { XML_URL, BibliographyDataField::URL },
+ { XML_VOLUME, BibliographyDataField::VOLUME },
+ { XML_YEAR, BibliographyDataField::YEAR },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+void XMLIndexBibliographyEntryContext::startFastElement(
+ sal_Int32 /*nElement*/,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ // handle both, style name and bibliography info
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ switch(aIter.getToken())
+ {
+ case XML_ELEMENT(TEXT, XML_STYLE_NAME):
+ {
+ m_sCharStyleName = aIter.toString();
+ m_bCharStyleNameOK = true;
+ break;
+ }
+ case XML_ELEMENT(TEXT, XML_BIBLIOGRAPHY_DATA_FIELD):
+ {
+ sal_uInt16 nTmp;
+ if (SvXMLUnitConverter::convertEnum(nTmp, aIter.toView(), aBibliographyDataFieldMap))
+ {
+ nBibliographyInfo = nTmp;
+ bBibliographyInfoOK = true;
+ }
+ break;
+ }
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+
+ // if we have a style name, set it!
+ if (m_bCharStyleNameOK)
+ {
+ m_nValues++;
+ }
+
+ // always bibliography; else element is not valid
+ m_nValues++;
+}
+
+void XMLIndexBibliographyEntryContext::endFastElement(sal_Int32 nElement)
+{
+ // only valid, if we have bibliography info
+ if (bBibliographyInfoOK)
+ {
+ XMLIndexSimpleEntryContext::endFastElement(nElement);
+ }
+}
+
+void XMLIndexBibliographyEntryContext::FillPropertyValues(
+ css::uno::Sequence<css::beans::PropertyValue> & rValues)
+{
+ // entry name and (optionally) style name in parent class
+ XMLIndexSimpleEntryContext::FillPropertyValues(rValues);
+
+ // bibliography data field
+ sal_Int32 nIndex = m_bCharStyleNameOK ? 2 : 1;
+ auto pValues = rValues.getArray();
+ pValues[nIndex].Name = "BibliographyDataField";
+ pValues[nIndex].Value <<= nBibliographyInfo;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexBibliographyEntryContext.hxx b/xmloff/source/text/XMLIndexBibliographyEntryContext.hxx
new file mode 100644
index 0000000000..4c586a5a85
--- /dev/null
+++ b/xmloff/source/text/XMLIndexBibliographyEntryContext.hxx
@@ -0,0 +1,70 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include "XMLIndexSimpleEntryContext.hxx"
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/Sequence.h>
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+
+namespace com::sun::star {
+ namespace xml::sax { class XAttributeList; }
+}
+class XMLIndexTemplateContext;
+template<typename EnumT> struct SvXMLEnumMapEntry;
+
+extern const SvXMLEnumMapEntry<sal_uInt16> aBibliographyDataFieldMap[];
+
+/**
+ * Import bibliography index entry templates
+ */
+class XMLIndexBibliographyEntryContext : public XMLIndexSimpleEntryContext
+{
+ // bibliography info
+ sal_Int16 nBibliographyInfo;
+ bool bBibliographyInfoOK;
+
+public:
+
+
+ XMLIndexBibliographyEntryContext(
+ SvXMLImport& rImport,
+ XMLIndexTemplateContext& rTemplate );
+
+ virtual ~XMLIndexBibliographyEntryContext() override;
+
+protected:
+
+ /** process parameters */
+ virtual void SAL_CALL startFastElement(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+
+ /** call FillPropertyValues and insert into template */
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ /** fill property values for this template entry */
+ virtual void FillPropertyValues(
+ css::uno::Sequence<css::beans::PropertyValue> & rValues) override;
+
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexBibliographySourceContext.cxx b/xmloff/source/text/XMLIndexBibliographySourceContext.cxx
new file mode 100644
index 0000000000..426505fc27
--- /dev/null
+++ b/xmloff/source/text/XMLIndexBibliographySourceContext.cxx
@@ -0,0 +1,80 @@
+/* -*- 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 "XMLIndexBibliographySourceContext.hxx"
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include "XMLIndexTemplateContext.hxx"
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/log.hxx>
+
+
+using namespace ::xmloff::token;
+
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::uno::Reference;
+
+
+XMLIndexBibliographySourceContext::XMLIndexBibliographySourceContext(
+ SvXMLImport& rImport,
+ Reference<XPropertySet> & rPropSet)
+ : XMLIndexSourceBaseContext(rImport, rPropSet, UseStyles::None)
+{
+}
+
+XMLIndexBibliographySourceContext::~XMLIndexBibliographySourceContext()
+{
+}
+
+void XMLIndexBibliographySourceContext::ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)
+{
+ // We have no attributes. Who wants attributes, anyway?
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+}
+
+void XMLIndexBibliographySourceContext::endFastElement(sal_Int32 )
+{
+ // No attributes, no properties.
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLIndexBibliographySourceContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ if ( nElement == XML_ELEMENT(TEXT, XML_BIBLIOGRAPHY_ENTRY_TEMPLATE) )
+ {
+ return new XMLIndexTemplateContext(GetImport(), rIndexPropertySet,
+ aLevelNameBibliographyMap,
+ XML_BIBLIOGRAPHY_TYPE,
+ aLevelStylePropNameBibliographyMap,
+ aAllowedTokenTypesBibliography);
+ }
+ else
+ {
+ return XMLIndexSourceBaseContext::createFastChildContext(nElement,
+ xAttrList);
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexBibliographySourceContext.hxx b/xmloff/source/text/XMLIndexBibliographySourceContext.hxx
new file mode 100644
index 0000000000..497c33d1cf
--- /dev/null
+++ b/xmloff/source/text/XMLIndexBibliographySourceContext.hxx
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include "XMLIndexSourceBaseContext.hxx"
+#include <com/sun/star/uno/Reference.h>
+
+
+namespace com::sun::star {
+ namespace xml::sax { class XAttributeList; }
+ namespace beans { class XPropertySet; }
+}
+
+
+/**
+ * Import bibliography source element
+ */
+class XMLIndexBibliographySourceContext : public XMLIndexSourceBaseContext
+{
+
+public:
+
+ XMLIndexBibliographySourceContext(
+ SvXMLImport& rImport,
+ css::uno::Reference<css::beans::XPropertySet> & rPropSet);
+
+ virtual ~XMLIndexBibliographySourceContext() override;
+
+protected:
+
+ virtual void ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter) override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexBodyContext.cxx b/xmloff/source/text/XMLIndexBodyContext.cxx
new file mode 100644
index 0000000000..53a7def1d2
--- /dev/null
+++ b/xmloff/source/text/XMLIndexBodyContext.cxx
@@ -0,0 +1,52 @@
+/* -*- 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 "XMLIndexBodyContext.hxx"
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/txtimp.hxx>
+#include <rtl/ustring.hxx>
+
+using ::com::sun::star::uno::Reference;
+
+
+XMLIndexBodyContext::XMLIndexBodyContext( SvXMLImport& rImport ) :
+ SvXMLImportContext(rImport),
+ bHasContent(false)
+{
+}
+
+XMLIndexBodyContext::~XMLIndexBodyContext()
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLIndexBodyContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ // return text content (if possible)
+ SvXMLImportContext* pContext = GetImport().GetTextImport()->CreateTextChildContext(
+ GetImport(), nElement, xAttrList, XMLTextType::Section );
+ if (pContext)
+ bHasContent = true;
+
+ return pContext;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexBodyContext.hxx b/xmloff/source/text/XMLIndexBodyContext.hxx
new file mode 100644
index 0000000000..5962bacf34
--- /dev/null
+++ b/xmloff/source/text/XMLIndexBodyContext.hxx
@@ -0,0 +1,63 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <com/sun/star/uno/Reference.h>
+
+
+namespace com::sun::star {
+ namespace xml::sax { class XAttributeList; }
+ namespace beans { class XPropertySet; }
+}
+
+/**
+ * Import index body.
+ *
+ * This class basically delegates all CreateChildContext() calls to
+ * the text import and doesn't do much else.
+ */
+class XMLIndexBodyContext : public SvXMLImportContext
+{
+ bool bHasContent;
+
+public:
+
+
+ XMLIndexBodyContext( SvXMLImport& rImport );
+
+ virtual ~XMLIndexBodyContext() override;
+
+ /// return whether any content elements were encountered
+ inline bool HasContent() const;
+
+protected:
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+};
+
+inline bool XMLIndexBodyContext::HasContent() const
+{
+ return bHasContent;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexChapterInfoEntryContext.cxx b/xmloff/source/text/XMLIndexChapterInfoEntryContext.cxx
new file mode 100644
index 0000000000..b17d05739c
--- /dev/null
+++ b/xmloff/source/text/XMLIndexChapterInfoEntryContext.cxx
@@ -0,0 +1,185 @@
+/* -*- 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 "XMLIndexChapterInfoEntryContext.hxx"
+
+#include <com/sun/star/text/ChapterFormat.hpp>
+
+#include <sax/tools/converter.hxx>
+#include <sal/log.hxx>
+
+#include "XMLIndexTemplateContext.hxx"
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlement.hxx>
+
+
+using namespace ::com::sun::star::text;
+using namespace ::xmloff::token;
+
+using ::com::sun::star::beans::PropertyValue;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+
+XMLIndexChapterInfoEntryContext::XMLIndexChapterInfoEntryContext(
+ SvXMLImport& rImport,
+ XMLIndexTemplateContext& rTemplate,
+ bool bT ) :
+ XMLIndexSimpleEntryContext(rImport,
+ (bT ? OUString("TokenEntryNumber")
+ : OUString("TokenChapterInfo")),
+ rTemplate),
+ nChapterInfo(ChapterFormat::NAME_NUMBER),
+ bChapterInfoOK(false),
+ bTOC( bT ),
+ nOutlineLevel( 0 ),
+ bOutlineLevelOK(false)
+{
+}
+
+XMLIndexChapterInfoEntryContext::~XMLIndexChapterInfoEntryContext()
+{
+}
+
+const SvXMLEnumMapEntry<sal_uInt16> aChapterDisplayMap[] =
+{
+ { XML_NAME, ChapterFormat::NAME },
+ { XML_NUMBER, ChapterFormat::NUMBER },
+ { XML_NUMBER_AND_NAME, ChapterFormat::NAME_NUMBER },
+ //---> i89791
+ // enabled for ODF 1.2, full index support in 3.0
+ { XML_PLAIN_NUMBER_AND_NAME, ChapterFormat::NO_PREFIX_SUFFIX },
+ { XML_PLAIN_NUMBER, ChapterFormat::DIGIT },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+void XMLIndexChapterInfoEntryContext::startFastElement(
+ sal_Int32 /*nElement*/,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ // handle both, style name and bibliography info
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ switch(aIter.getToken())
+ {
+ case XML_ELEMENT(TEXT, XML_STYLE_NAME):
+ {
+ m_sCharStyleName = aIter.toString();
+ m_bCharStyleNameOK = true;
+ break;
+ }
+ case XML_ELEMENT(TEXT, XML_DISPLAY): //i53420, always true, in TOC as well
+ {
+ sal_uInt16 nTmp;
+ if (SvXMLUnitConverter::convertEnum(nTmp, aIter.toView(), aChapterDisplayMap))
+ {
+ nChapterInfo = nTmp;
+ bChapterInfoOK = true;
+ }
+ break;
+ }
+ case XML_ELEMENT(TEXT, XML_OUTLINE_LEVEL):
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertNumber(nTmp, aIter.toView()))
+ {
+//control on range is carried out in the UNO level
+ nOutlineLevel = static_cast<sal_uInt16>(nTmp);
+ bOutlineLevelOK = true;
+ }
+ break;
+ }
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+
+ // if we have a style name, set it!
+ if (m_bCharStyleNameOK)
+ {
+ m_nValues++;
+ }
+
+ // if we have chapter info, set it!
+ if (bChapterInfoOK)
+ {
+ m_nValues++;
+ /* Some of the index chapter information attributes written to ODF 1.1
+ and 1.2 don't reflect the displaying (#i89791#)
+ */
+ if ( !bTOC )
+ {
+ bool bConvert( false );
+ {
+ sal_Int32 nUPD( 0 );
+ sal_Int32 nBuild( 0 );
+ const bool bBuildIdFound = GetImport().getBuildIds( nUPD, nBuild );
+ if ( GetImport().IsTextDocInOOoFileFormat() ||
+ ( bBuildIdFound &&
+ ( nUPD== 680 || nUPD == 645 || nUPD == 641 ) ) )
+ {
+ bConvert = true;
+ }
+ }
+ if ( bConvert )
+ {
+ if ( nChapterInfo == ChapterFormat::NUMBER )
+ {
+ nChapterInfo = ChapterFormat::DIGIT;
+ }
+ else if ( nChapterInfo == ChapterFormat::NAME_NUMBER )
+ {
+ nChapterInfo = ChapterFormat::NO_PREFIX_SUFFIX;
+ }
+ }
+ }
+ }
+ if (bOutlineLevelOK)
+ m_nValues++;
+}
+
+void XMLIndexChapterInfoEntryContext::FillPropertyValues(
+ css::uno::Sequence<css::beans::PropertyValue> & rValues)
+{
+ // entry name and (optionally) style name in parent class
+ XMLIndexSimpleEntryContext::FillPropertyValues(rValues);
+
+ sal_Int32 nIndex = m_bCharStyleNameOK ? 2 : 1;
+ auto pValues = rValues.getArray();
+
+ if( bChapterInfoOK )
+ {
+ // chapter info field
+ pValues[nIndex].Name = "ChapterFormat";
+ pValues[nIndex].Value <<= nChapterInfo;
+ nIndex++;
+ }
+ if( bOutlineLevelOK )
+ {
+ pValues[nIndex].Name = "ChapterLevel";
+ pValues[nIndex].Value <<= nOutlineLevel;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexChapterInfoEntryContext.hxx b/xmloff/source/text/XMLIndexChapterInfoEntryContext.hxx
new file mode 100644
index 0000000000..f1cc400e5e
--- /dev/null
+++ b/xmloff/source/text/XMLIndexChapterInfoEntryContext.hxx
@@ -0,0 +1,67 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include "XMLIndexSimpleEntryContext.hxx"
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/Sequence.h>
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+
+namespace com::sun::star {
+ namespace xml::sax { class XAttributeList; }
+}
+class XMLIndexTemplateContext;
+
+/**
+ * Import chapter info index entry templates
+ */
+class XMLIndexChapterInfoEntryContext : public XMLIndexSimpleEntryContext
+{
+ // chapter format
+ sal_Int16 nChapterInfo;
+ bool bChapterInfoOK;
+ bool bTOC;
+ sal_Int16 nOutlineLevel;
+ bool bOutlineLevelOK;
+
+public:
+
+
+ XMLIndexChapterInfoEntryContext(
+ SvXMLImport& rImport,
+ XMLIndexTemplateContext& rTemplate,
+ bool bTOC );
+
+ virtual ~XMLIndexChapterInfoEntryContext() override;
+
+protected:
+
+ /** process parameters */
+ virtual void SAL_CALL startFastElement(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+
+ /** fill property values for this template entry */
+ virtual void FillPropertyValues(
+ css::uno::Sequence<css::beans::PropertyValue> & rValues) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexIllustrationSourceContext.cxx b/xmloff/source/text/XMLIndexIllustrationSourceContext.cxx
new file mode 100644
index 0000000000..3148bc71ec
--- /dev/null
+++ b/xmloff/source/text/XMLIndexIllustrationSourceContext.cxx
@@ -0,0 +1,67 @@
+/* -*- 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 "XMLIndexIllustrationSourceContext.hxx"
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include "XMLIndexTemplateContext.hxx"
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <rtl/ustring.hxx>
+
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::uno::Reference;
+using ::xmloff::token::XML_ILLUSTRATION_INDEX_ENTRY_TEMPLATE;
+using ::xmloff::token::XML_TOKEN_INVALID;
+
+
+XMLIndexIllustrationSourceContext::XMLIndexIllustrationSourceContext(
+ SvXMLImport& rImport,
+ Reference<XPropertySet> & rPropSet)
+ : XMLIndexTableSourceContext(rImport, rPropSet)
+{
+}
+
+XMLIndexIllustrationSourceContext::~XMLIndexIllustrationSourceContext()
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLIndexIllustrationSourceContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ if ( nElement == XML_ELEMENT(TEXT, XML_ILLUSTRATION_INDEX_ENTRY_TEMPLATE) )
+ {
+ return new XMLIndexTemplateContext(GetImport(), rIndexPropertySet,
+ aLevelNameTableMap,
+ XML_TOKEN_INVALID, // no outline-level attr
+ aLevelStylePropNameTableMap,
+ aAllowedTokenTypesTable);
+ }
+ else
+ {
+ return XMLIndexSourceBaseContext::createFastChildContext(nElement,
+ xAttrList);
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexIllustrationSourceContext.hxx b/xmloff/source/text/XMLIndexIllustrationSourceContext.hxx
new file mode 100644
index 0000000000..b482c63fff
--- /dev/null
+++ b/xmloff/source/text/XMLIndexIllustrationSourceContext.hxx
@@ -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/.
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include "XMLIndexTableSourceContext.hxx"
+#include <com/sun/star/uno/Reference.h>
+
+
+namespace com::sun::star {
+ namespace xml::sax { class XAttributeList; }
+ namespace beans { class XPropertySet; }
+}
+
+
+/**
+ * Import illustration index source element;
+ *
+ * All logic is inherited from table source context. The only difference is
+ * the different child context (illustration entry template).
+ */
+class XMLIndexIllustrationSourceContext : public XMLIndexTableSourceContext
+{
+public:
+
+ XMLIndexIllustrationSourceContext(
+ SvXMLImport& rImport,
+ css::uno::Reference<css::beans::XPropertySet> & rPropSet);
+
+ virtual ~XMLIndexIllustrationSourceContext() override;
+
+protected:
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexMarkExport.cxx b/xmloff/source/text/XMLIndexMarkExport.cxx
new file mode 100644
index 0000000000..f27c87d9ea
--- /dev/null
+++ b/xmloff/source/text/XMLIndexMarkExport.cxx
@@ -0,0 +1,228 @@
+/* -*- 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 "XMLIndexMarkExport.hxx"
+#include <o3tl/any.hxx>
+#include <tools/debug.hxx>
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <sax/tools/converter.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmlexp.hxx>
+
+
+using namespace ::xmloff::token;
+
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::beans::XPropertySetInfo;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Any;
+
+XMLIndexMarkExport::XMLIndexMarkExport(
+ SvXMLExport& rExp)
+: rExport(rExp)
+{
+}
+
+const enum XMLTokenEnum lcl_pTocMarkNames[] =
+ { XML_TOC_MARK, XML_TOC_MARK_START, XML_TOC_MARK_END };
+const enum XMLTokenEnum lcl_pUserIndexMarkName[] =
+ { XML_USER_INDEX_MARK,
+ XML_USER_INDEX_MARK_START, XML_USER_INDEX_MARK_END };
+const enum XMLTokenEnum lcl_pAlphaIndexMarkName[] =
+ { XML_ALPHABETICAL_INDEX_MARK,
+ XML_ALPHABETICAL_INDEX_MARK_START,
+ XML_ALPHABETICAL_INDEX_MARK_END };
+
+
+void XMLIndexMarkExport::ExportIndexMark(
+ const Reference<XPropertySet> & rPropSet,
+ bool bAutoStyles)
+{
+ /// index marks have no styles!
+ if (bAutoStyles)
+ return;
+
+ const enum XMLTokenEnum * pElements = nullptr;
+ sal_Int8 nElementNo = -1;
+
+ // get index mark
+ Any aAny = rPropSet->getPropertyValue(gsDocumentIndexMark);
+ Reference<XPropertySet> xIndexMarkPropSet;
+ aAny >>= xIndexMarkPropSet;
+
+ // common: handling of start, end, collapsed entries and
+ // alternative text
+
+ // collapsed/alternative text entry?
+ aAny = rPropSet->getPropertyValue(gsIsCollapsed);
+ if (*o3tl::doAccess<bool>(aAny))
+ {
+ // collapsed entry: needs alternative text
+ nElementNo = 0;
+
+ aAny = xIndexMarkPropSet->getPropertyValue(gsAlternativeText);
+ OUString sTmp;
+ aAny >>= sTmp;
+ DBG_ASSERT(!sTmp.isEmpty(),
+ "collapsed index mark without alternative text");
+ rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_STRING_VALUE, sTmp);
+ }
+ else
+ {
+ // start and end entries: has ID
+ aAny = rPropSet->getPropertyValue(gsIsStart);
+ nElementNo = *o3tl::doAccess<bool>(aAny) ? 1 : 2;
+
+ // generate ID
+ OUStringBuffer sBuf;
+ GetID(sBuf, xIndexMarkPropSet);
+ rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_ID,
+ sBuf.makeStringAndClear());
+ }
+
+ // distinguish between TOC, user, alphab. index marks by
+ // asking for specific properties
+ // Export attributes for -mark-start and -mark elements,
+ // but not for -mark-end
+ Reference<XPropertySetInfo> xPropertySetInfo =
+ xIndexMarkPropSet->getPropertySetInfo();
+ if (xPropertySetInfo->hasPropertyByName(gsUserIndexName))
+ {
+ // user index mark
+ pElements = lcl_pUserIndexMarkName;
+ if (nElementNo != 2)
+ {
+ ExportUserIndexMarkAttributes(xIndexMarkPropSet);
+ }
+ }
+ else if (xPropertySetInfo->hasPropertyByName(gsPrimaryKey))
+ {
+ // alphabetical index mark
+ pElements = lcl_pAlphaIndexMarkName;
+ if (nElementNo != 2)
+ {
+ ExportAlphabeticalIndexMarkAttributes(xIndexMarkPropSet);
+ }
+ }
+ else
+ {
+ // table of content:
+ pElements = lcl_pTocMarkNames;
+ if (nElementNo != 2)
+ {
+ ExportTOCMarkAttributes(xIndexMarkPropSet);
+ }
+ }
+
+ // export element
+ DBG_ASSERT(pElements != nullptr, "illegal element array");
+ DBG_ASSERT(nElementNo >= 0, "illegal name array index");
+ DBG_ASSERT(nElementNo <= 2, "illegal name array index");
+
+ if ((pElements != nullptr) && (nElementNo != -1))
+ {
+ SvXMLElementExport aElem(rExport,
+ XML_NAMESPACE_TEXT,
+ pElements[nElementNo],
+ false, false);
+ }
+
+}
+
+void XMLIndexMarkExport::ExportTOCMarkAttributes(
+ const Reference<XPropertySet> & rPropSet)
+{
+ // outline level
+ sal_Int16 nLevel = 0;
+ Any aAny = rPropSet->getPropertyValue(gsLevel);
+ aAny >>= nLevel;
+ rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_OUTLINE_LEVEL,
+ OUString::number(nLevel + 1));
+}
+
+static void lcl_ExportPropertyString( SvXMLExport& rExport,
+ const Reference<XPropertySet> & rPropSet,
+ const OUString & sProperty,
+ XMLTokenEnum eToken,
+ Any& rAny )
+{
+ rAny = rPropSet->getPropertyValue( sProperty );
+
+ OUString sValue;
+ if( (rAny >>= sValue) && !sValue.isEmpty() )
+ {
+ rExport.AddAttribute( XML_NAMESPACE_TEXT, eToken, sValue );
+ }
+}
+
+static void lcl_ExportPropertyBool( SvXMLExport& rExport,
+ const Reference<XPropertySet> & rPropSet,
+ const OUString & sProperty,
+ XMLTokenEnum eToken,
+ Any& rAny )
+{
+ rAny = rPropSet->getPropertyValue( sProperty );
+
+ bool bValue;
+ if( (rAny >>= bValue) && bValue )
+ {
+ rExport.AddAttribute( XML_NAMESPACE_TEXT, eToken, XML_TRUE );
+ }
+}
+
+void XMLIndexMarkExport::ExportUserIndexMarkAttributes(
+ const Reference<XPropertySet> & rPropSet)
+{
+ // name of user index
+ // (unless it's the default index; then it has no name)
+ Any aAny;
+ lcl_ExportPropertyString( rExport, rPropSet, gsUserIndexName, XML_INDEX_NAME, aAny );
+
+ // additionally export outline level; just reuse ExportTOCMarkAttributes
+ ExportTOCMarkAttributes( rPropSet );
+}
+
+void XMLIndexMarkExport::ExportAlphabeticalIndexMarkAttributes(
+ const Reference<XPropertySet> & rPropSet)
+{
+ // primary and secondary keys (if available)
+ Any aAny;
+ lcl_ExportPropertyString( rExport, rPropSet, gsTextReading, XML_STRING_VALUE_PHONETIC, aAny );
+ lcl_ExportPropertyString( rExport, rPropSet, gsPrimaryKey, XML_KEY1, aAny );
+ lcl_ExportPropertyString( rExport, rPropSet, gsPrimaryKeyReading, XML_KEY1_PHONETIC, aAny );
+ lcl_ExportPropertyString( rExport, rPropSet, gsSecondaryKey, XML_KEY2, aAny );
+ lcl_ExportPropertyString( rExport, rPropSet, gsSecondaryKeyReading, XML_KEY2_PHONETIC, aAny );
+ lcl_ExportPropertyBool( rExport, rPropSet, gsMainEntry, XML_MAIN_ENTRY, aAny );
+}
+
+void XMLIndexMarkExport::GetID(
+ OUStringBuffer& sBuf,
+ const Reference<XPropertySet> & rPropSet)
+{
+ // HACK: use address of object to form identifier
+ sal_Int64 nId = sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_uIntPtr>(rPropSet.get()));
+ sBuf.append("IMark");
+ sBuf.append(nId);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexMarkExport.hxx b/xmloff/source/text/XMLIndexMarkExport.hxx
new file mode 100644
index 0000000000..a62ce9b503
--- /dev/null
+++ b/xmloff/source/text/XMLIndexMarkExport.hxx
@@ -0,0 +1,92 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/uno/Reference.h>
+
+class SvXMLExport;
+namespace com::sun::star {
+ namespace beans { class XPropertySet; }
+}
+
+
+/**
+ * This class handles the export of index marks for table of content,
+ * alphabetical and user index.
+ *
+ * Marks for bibliography indices are internally modelled as text
+ * fields and thus handled in txtparae.cxx
+ */
+class XMLIndexMarkExport
+{
+ static constexpr OUString gsLevel = u"Level"_ustr;
+ static constexpr OUString gsUserIndexName = u"UserIndexName"_ustr;
+ static constexpr OUString gsPrimaryKey = u"PrimaryKey"_ustr;
+ static constexpr OUString gsSecondaryKey = u"SecondaryKey"_ustr;
+ static constexpr OUString gsDocumentIndexMark = u"DocumentIndexMark"_ustr;
+ static constexpr OUString gsIsStart = u"IsStart"_ustr;
+ static constexpr OUString gsIsCollapsed = u"IsCollapsed"_ustr;
+ static constexpr OUString gsAlternativeText = u"AlternativeText"_ustr;
+ static constexpr OUString gsTextReading = u"TextReading"_ustr;
+ static constexpr OUString gsPrimaryKeyReading = u"PrimaryKeyReading"_ustr;
+ static constexpr OUString gsSecondaryKeyReading = u"SecondaryKeyReading"_ustr;
+ static constexpr OUString gsMainEntry = u"IsMainEntry"_ustr;
+
+ SvXMLExport& rExport;
+
+public:
+ explicit XMLIndexMarkExport(SvXMLExport& rExp);
+
+ /**
+ * export by the property set of its *text* *portion*.
+ *
+ * The text portion supplies us with the properties of the index
+ * mark itself, as well as the information whether we are at the
+ * start or end of an index mark, or whether the index mark is
+ * collapsed.
+ */
+ void ExportIndexMark(
+ const css::uno::Reference<css::beans::XPropertySet> & rPropSet,
+ bool bAutoStyles);
+
+private:
+
+ /// export attributes of table-of-content index marks
+ void ExportTOCMarkAttributes(
+ const css::uno::Reference<css::beans::XPropertySet> & rPropSet);
+
+ /// export attributes of user index marks
+ void ExportUserIndexMarkAttributes(
+ const css::uno::Reference<css::beans::XPropertySet> & rPropSet);
+
+ /// export attributes of alphabetical index marks
+ void ExportAlphabeticalIndexMarkAttributes(
+ const css::uno::Reference<css::beans::XPropertySet> & rPropSet);
+
+ /// create a numerical ID for this index mark
+ /// (represented by its properties)
+ static void GetID(
+ OUStringBuffer& sBuffer,
+ const css::uno::Reference<css::beans::XPropertySet> & rPropSet);
+
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexObjectSourceContext.cxx b/xmloff/source/text/XMLIndexObjectSourceContext.cxx
new file mode 100644
index 0000000000..805ce796aa
--- /dev/null
+++ b/xmloff/source/text/XMLIndexObjectSourceContext.cxx
@@ -0,0 +1,136 @@
+/* -*- 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 "XMLIndexObjectSourceContext.hxx"
+
+#include <rtl/ustring.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include <sax/tools/converter.hxx>
+
+#include "XMLIndexTemplateContext.hxx"
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+
+
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Any;
+using namespace ::xmloff::token;
+
+
+XMLIndexObjectSourceContext::XMLIndexObjectSourceContext(
+ SvXMLImport& rImport,
+ Reference<XPropertySet> & rPropSet)
+ : XMLIndexSourceBaseContext(rImport, rPropSet, UseStyles::Single),
+ bUseCalc(false),
+ bUseChart(false),
+ bUseDraw(false),
+ bUseMath(false),
+ bUseOtherObjects(false)
+{
+}
+
+XMLIndexObjectSourceContext::~XMLIndexObjectSourceContext()
+{
+}
+
+void XMLIndexObjectSourceContext::ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)
+{
+ bool bTmp(false);
+
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(TEXT, XML_USE_OTHER_OBJECTS):
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bUseOtherObjects = bTmp;
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_USE_SPREADSHEET_OBJECTS):
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bUseCalc = bTmp;
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_USE_CHART_OBJECTS):
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bUseChart = bTmp;
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_USE_DRAW_OBJECTS):
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bUseDraw = bTmp;
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_USE_MATH_OBJECTS):
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bUseMath = bTmp;
+ }
+ break;
+
+ default:
+ XMLIndexSourceBaseContext::ProcessAttribute(aIter);
+ break;
+ }
+}
+
+void XMLIndexObjectSourceContext::endFastElement(sal_Int32 nElement)
+{
+ rIndexPropertySet->setPropertyValue("CreateFromStarCalc", css::uno::Any(bUseCalc));
+ rIndexPropertySet->setPropertyValue("CreateFromStarChart", css::uno::Any(bUseChart));
+ rIndexPropertySet->setPropertyValue("CreateFromStarDraw", css::uno::Any(bUseDraw));
+ rIndexPropertySet->setPropertyValue("CreateFromStarMath", css::uno::Any(bUseMath));
+ rIndexPropertySet->setPropertyValue("CreateFromOtherEmbeddedObjects", css::uno::Any(bUseOtherObjects));
+
+ XMLIndexSourceBaseContext::endFastElement(nElement);
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLIndexObjectSourceContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ if ( nElement == XML_ELEMENT(TEXT, XML_OBJECT_INDEX_ENTRY_TEMPLATE) )
+ {
+ return new XMLIndexTemplateContext(GetImport(), rIndexPropertySet,
+ aLevelNameTableMap,
+ XML_TOKEN_INVALID, // no outline-level attr
+ aLevelStylePropNameTableMap,
+ aAllowedTokenTypesTable);
+ }
+ else
+ {
+ return XMLIndexSourceBaseContext::createFastChildContext(nElement,
+ xAttrList);
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexObjectSourceContext.hxx b/xmloff/source/text/XMLIndexObjectSourceContext.hxx
new file mode 100644
index 0000000000..6240a5c28a
--- /dev/null
+++ b/xmloff/source/text/XMLIndexObjectSourceContext.hxx
@@ -0,0 +1,63 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include "XMLIndexSourceBaseContext.hxx"
+#include <com/sun/star/uno/Reference.h>
+
+
+namespace com::sun::star {
+ namespace xml::sax { class XAttributeList; }
+ namespace beans { class XPropertySet; }
+}
+
+
+/**
+ * Import object index source element
+ */
+class XMLIndexObjectSourceContext : public XMLIndexSourceBaseContext
+{
+ bool bUseCalc;
+ bool bUseChart;
+ bool bUseDraw;
+ bool bUseMath;
+ bool bUseOtherObjects;
+
+public:
+
+
+ XMLIndexObjectSourceContext(
+ SvXMLImport& rImport,
+ css::uno::Reference<css::beans::XPropertySet> & rPropSet);
+
+ virtual ~XMLIndexObjectSourceContext() override;
+
+protected:
+
+ virtual void ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter) override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexSimpleEntryContext.cxx b/xmloff/source/text/XMLIndexSimpleEntryContext.cxx
new file mode 100644
index 0000000000..6c59f13380
--- /dev/null
+++ b/xmloff/source/text/XMLIndexSimpleEntryContext.cxx
@@ -0,0 +1,123 @@
+/* -*- 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 "XMLIndexSimpleEntryContext.hxx"
+#include "XMLIndexTemplateContext.hxx"
+#include <utility>
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/txtimp.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <sal/log.hxx>
+
+#include <com/sun/star/container/XNameContainer.hpp>
+
+using ::com::sun::star::beans::PropertyValue;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Any;
+using ::xmloff::token::XML_STYLE_NAME;
+
+
+XMLIndexSimpleEntryContext::XMLIndexSimpleEntryContext(
+ SvXMLImport& rImport,
+ OUString aEntry,
+ XMLIndexTemplateContext& rTemplate )
+: SvXMLImportContext(rImport)
+, m_rEntryType(std::move(aEntry))
+, m_bCharStyleNameOK(false)
+, m_rTemplateContext(rTemplate)
+, m_nValues(1)
+{
+}
+
+XMLIndexSimpleEntryContext::~XMLIndexSimpleEntryContext()
+{
+}
+
+void XMLIndexSimpleEntryContext::startFastElement(
+ sal_Int32 /*nElement*/,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ // we know only one attribute: style-name
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ if(aIter.getToken() == XML_ELEMENT(TEXT, XML_STYLE_NAME))
+ {
+ m_sCharStyleName = aIter.toString();
+ OUString sDisplayStyleName = GetImport().GetStyleDisplayName(
+ XmlStyleFamily::TEXT_TEXT, m_sCharStyleName );
+ // #142494#: Check if style exists
+ const Reference < css::container::XNameContainer > & rStyles =
+ GetImport().GetTextImport()->GetTextStyles();
+ if( rStyles.is() && rStyles->hasByName( sDisplayStyleName ) )
+ m_bCharStyleNameOK = true;
+ else
+ m_bCharStyleNameOK = false;
+ }
+ else
+ XMLOFF_INFO_UNKNOWN("xmloff", aIter);
+ }
+
+ // if we have a style name, set it!
+ if (m_bCharStyleNameOK)
+ {
+ m_nValues++;
+ }
+
+}
+
+void XMLIndexSimpleEntryContext::endFastElement(sal_Int32 )
+{
+ Sequence<PropertyValue> aValues(m_nValues);
+
+ FillPropertyValues(aValues);
+ m_rTemplateContext.addTemplateEntry(aValues);
+}
+
+void XMLIndexSimpleEntryContext::FillPropertyValues(
+ css::uno::Sequence<css::beans::PropertyValue> & rValues)
+{
+ // due to the limited number of subclasses, we fill the values
+ // directly into the slots. Subclasses will have to know they can
+ // only use slot so-and-so.
+
+ Any aAny;
+ auto pValues = rValues.getArray();
+
+ // token type
+ pValues[0].Name = "TokenType";
+ pValues[0].Value <<= m_rEntryType;
+
+ // char style
+ if (m_bCharStyleNameOK)
+ {
+ pValues[1].Name = "CharacterStyleName";
+ aAny <<= GetImport().GetStyleDisplayName(
+ XmlStyleFamily::TEXT_TEXT,
+ m_sCharStyleName );
+ pValues[1].Value = aAny;
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexSimpleEntryContext.hxx b/xmloff/source/text/XMLIndexSimpleEntryContext.hxx
new file mode 100644
index 0000000000..684245184e
--- /dev/null
+++ b/xmloff/source/text/XMLIndexSimpleEntryContext.hxx
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/Sequence.h>
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+
+namespace com::sun::star {
+ namespace xml::sax { class XAttributeList; }
+}
+class XMLIndexTemplateContext;
+
+/**
+ * Import index entry templates
+ */
+class XMLIndexSimpleEntryContext : public SvXMLImportContext
+{
+
+ // entry type
+ const OUString m_rEntryType;
+
+protected:
+ // character style
+ OUString m_sCharStyleName;
+ bool m_bCharStyleNameOK;
+
+ // surrounding template
+ XMLIndexTemplateContext& m_rTemplateContext;
+
+ // number of values for PropertyValues
+ sal_Int32 m_nValues;
+
+public:
+
+
+ XMLIndexSimpleEntryContext(
+ SvXMLImport& rImport,
+ OUString aEntry,
+ XMLIndexTemplateContext& rTemplate );
+
+ virtual ~XMLIndexSimpleEntryContext() override;
+
+protected:
+
+ /** process parameters */
+ virtual void SAL_CALL startFastElement(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+
+ /** call FillPropertyValues and insert into template */
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ /** fill property values for this template entry */
+ virtual void FillPropertyValues(
+ css::uno::Sequence<css::beans::PropertyValue> & rValues);
+
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexSourceBaseContext.cxx b/xmloff/source/text/XMLIndexSourceBaseContext.cxx
new file mode 100644
index 0000000000..366daed58f
--- /dev/null
+++ b/xmloff/source/text/XMLIndexSourceBaseContext.cxx
@@ -0,0 +1,135 @@
+/* -*- 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 "XMLIndexSourceBaseContext.hxx"
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include "XMLIndexTitleTemplateContext.hxx"
+#include "XMLIndexTOCStylesContext.hxx"
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <sax/tools/converter.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/log.hxx>
+
+
+using namespace ::xmloff::token;
+
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Any;
+
+
+XMLIndexSourceBaseContext::XMLIndexSourceBaseContext(
+ SvXMLImport& rImport,
+ Reference<XPropertySet> & rPropSet,
+ UseStyles const eUseStyles)
+: SvXMLImportContext(rImport)
+, m_UseStyles(eUseStyles)
+, bChapterIndex(false)
+, bRelativeTabs(true)
+, rIndexPropertySet(rPropSet)
+{
+}
+
+XMLIndexSourceBaseContext::~XMLIndexSourceBaseContext()
+{
+}
+
+void XMLIndexSourceBaseContext::startFastElement(
+ sal_Int32 /*nElement*/,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ // process attributes
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ ProcessAttribute(aIter);
+}
+
+void XMLIndexSourceBaseContext::ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)
+{
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(TEXT, XML_INDEX_SCOPE):
+ if ( IsXMLToken( aIter, XML_CHAPTER ) )
+ {
+ bChapterIndex = true;
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_RELATIVE_TAB_STOP_POSITION):
+ {
+ bool bTmp(false);
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bRelativeTabs = bTmp;
+ }
+ break;
+ }
+
+ default:
+ // unknown attribute -> ignore
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ break;
+ }
+}
+
+void XMLIndexSourceBaseContext::endFastElement(sal_Int32 )
+{
+ rIndexPropertySet->setPropertyValue("IsRelativeTabstops", css::uno::Any(bRelativeTabs));
+ rIndexPropertySet->setPropertyValue("CreateFromChapter", css::uno::Any(bChapterIndex));
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLIndexSourceBaseContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList)
+{
+ SvXMLImportContextRef xContext;
+
+ if (nElement == XML_ELEMENT(TEXT, XML_INDEX_TITLE_TEMPLATE) )
+ {
+ xContext = new XMLIndexTitleTemplateContext(GetImport(),
+ rIndexPropertySet);
+ }
+ else if (m_UseStyles == UseStyles::Level
+ && nElement == XML_ELEMENT(TEXT, XML_INDEX_SOURCE_STYLES))
+ {
+ xContext = new XMLIndexTOCStylesContext(GetImport(),
+ rIndexPropertySet);
+ }
+ else if (m_UseStyles == UseStyles::Single
+ && (nElement == XML_ELEMENT(LO_EXT, XML_INDEX_SOURCE_STYLE)
+ || nElement == XML_ELEMENT(TEXT, XML_INDEX_SOURCE_STYLE)))
+ {
+ OUString const styleName(xmloff::GetIndexSourceStyleName(xAttrList));
+ if (!styleName.isEmpty())
+ {
+ OUString const convertedStyleName(GetImport().GetStyleDisplayName(
+ XmlStyleFamily::TEXT_PARAGRAPH, styleName));
+ rIndexPropertySet->setPropertyValue("CreateFromParagraphStyle", css::uno::Any(convertedStyleName));
+ }
+ }
+
+ // else: unknown namespace -> ignore
+
+ return xContext;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexSourceBaseContext.hxx b/xmloff/source/text/XMLIndexSourceBaseContext.hxx
new file mode 100644
index 0000000000..b927954e5f
--- /dev/null
+++ b/xmloff/source/text/XMLIndexSourceBaseContext.hxx
@@ -0,0 +1,84 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <com/sun/star/uno/Reference.h>
+#include <rtl/ustring.hxx>
+#include <sax/fastattribs.hxx>
+
+
+namespace com::sun::star {
+ namespace xml::sax { class XAttributeList; }
+ namespace beans { class XPropertySet; }
+}
+
+/**
+ * Superclass for index source elements
+ */
+class XMLIndexSourceBaseContext : public SvXMLImportContext
+{
+protected:
+ enum class UseStyles { None, Level, Single };
+
+private:
+ UseStyles m_UseStyles;
+ bool bChapterIndex; /// chapter-wise or document index?
+ bool bRelativeTabs; /// tab stops relative to margin or indent?
+
+protected:
+
+ /// property set of index; must be accessible to subclasses
+ css::uno::Reference<css::beans::XPropertySet> & rIndexPropertySet;
+
+public:
+
+
+ XMLIndexSourceBaseContext(
+ SvXMLImport& rImport,
+ css::uno::Reference<css::beans::XPropertySet> & rPropSet,
+ UseStyles eUseStyles);
+
+ virtual ~XMLIndexSourceBaseContext() override;
+
+protected:
+
+ virtual void SAL_CALL startFastElement(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+
+ virtual void ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter);
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+};
+
+
+namespace xmloff {
+
+OUString GetIndexSourceStyleName(
+ css::uno::Reference<css::xml::sax::XFastAttributeList> const& xAttrList);
+
+} // namespace xmloff
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexSpanEntryContext.cxx b/xmloff/source/text/XMLIndexSpanEntryContext.cxx
new file mode 100644
index 0000000000..ba0c976cfc
--- /dev/null
+++ b/xmloff/source/text/XMLIndexSpanEntryContext.cxx
@@ -0,0 +1,63 @@
+/* -*- 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 "XMLIndexSpanEntryContext.hxx"
+#include <rtl/ustring.hxx>
+#include "XMLIndexTemplateContext.hxx"
+#include <xmloff/xmlictxt.hxx>
+
+
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::beans::PropertyValue;
+
+
+XMLIndexSpanEntryContext::XMLIndexSpanEntryContext(
+ SvXMLImport& rImport,
+ XMLIndexTemplateContext& rTemplate ) :
+ XMLIndexSimpleEntryContext(rImport, "TokenText",
+ rTemplate)
+{
+ m_nValues++; // one more for the text string
+}
+
+XMLIndexSpanEntryContext::~XMLIndexSpanEntryContext()
+{
+}
+
+void XMLIndexSpanEntryContext::characters(const OUString& sString)
+{
+ sContent.append(sString);
+}
+
+void XMLIndexSpanEntryContext::FillPropertyValues(
+ Sequence<PropertyValue> & rValues)
+{
+ // call superclass for token type, stylename,
+ XMLIndexSimpleEntryContext::FillPropertyValues(rValues);
+
+ // content
+ auto pValues = rValues.getArray();
+ Any aAny;
+ aAny <<= sContent.makeStringAndClear();
+ pValues[m_nValues-1].Name = "Text";
+ pValues[m_nValues-1].Value = aAny;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexSpanEntryContext.hxx b/xmloff/source/text/XMLIndexSpanEntryContext.hxx
new file mode 100644
index 0000000000..8b4711c1f8
--- /dev/null
+++ b/xmloff/source/text/XMLIndexSpanEntryContext.hxx
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include "XMLIndexSimpleEntryContext.hxx"
+#include <com/sun/star/uno/Sequence.h>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <rtl/ustrbuf.hxx>
+
+namespace com::sun::star {
+ namespace xml::sax { class XAttributeList; }
+}
+
+/**
+ * Import index entry templates
+ */
+class XMLIndexSpanEntryContext : public XMLIndexSimpleEntryContext
+{
+ OUStringBuffer sContent;
+
+public:
+
+
+ XMLIndexSpanEntryContext(
+ SvXMLImport& rImport,
+ XMLIndexTemplateContext& rTemplate );
+
+ virtual ~XMLIndexSpanEntryContext() override;
+
+protected:
+
+ /// Collect element contents
+ virtual void SAL_CALL characters(const OUString& sString) override;
+
+ /// add Text PropertyValue
+ virtual void FillPropertyValues(
+ css::uno::Sequence<css::beans::PropertyValue> & rValues) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexTOCContext.cxx b/xmloff/source/text/XMLIndexTOCContext.cxx
new file mode 100644
index 0000000000..2e3f1e3a47
--- /dev/null
+++ b/xmloff/source/text/XMLIndexTOCContext.cxx
@@ -0,0 +1,343 @@
+/* -*- 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 "XMLIndexTOCContext.hxx"
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/uno/XInterface.hpp>
+#include <com/sun/star/text/XTextContent.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <sax/tools/converter.hxx>
+#include <sal/log.hxx>
+#include "XMLIndexTOCSourceContext.hxx"
+#include "XMLIndexObjectSourceContext.hxx"
+#include "XMLIndexAlphabeticalSourceContext.hxx"
+#include "XMLIndexUserSourceContext.hxx"
+#include "XMLIndexBibliographySourceContext.hxx"
+#include "XMLIndexTableSourceContext.hxx"
+#include "XMLIndexIllustrationSourceContext.hxx"
+#include "XMLIndexBodyContext.hxx"
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/txtimp.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/prstylei.hxx>
+#include <xmloff/xmlerror.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlement.hxx>
+#include <rtl/ustring.hxx>
+#include <osl/diagnose.h>
+
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::text;
+using namespace ::xmloff::token;
+
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::lang::XMultiServiceFactory;
+using ::com::sun::star::lang::IllegalArgumentException;
+
+
+static const char* aIndexServiceMap[] =
+{
+ "com.sun.star.text.ContentIndex",
+ "com.sun.star.text.DocumentIndex",
+ "com.sun.star.text.TableIndex",
+ "com.sun.star.text.ObjectIndex",
+ "com.sun.star.text.Bibliography",
+ "com.sun.star.text.UserIndex",
+ "com.sun.star.text.IllustrationsIndex"
+};
+
+const XMLTokenEnum aIndexSourceElementMap[] =
+{
+ XML_TABLE_OF_CONTENT_SOURCE,
+ XML_ALPHABETICAL_INDEX_SOURCE,
+ XML_TABLE_INDEX_SOURCE,
+ XML_OBJECT_INDEX_SOURCE,
+ XML_BIBLIOGRAPHY_SOURCE,
+ XML_USER_INDEX_SOURCE,
+ XML_ILLUSTRATION_INDEX_SOURCE
+};
+
+SvXMLEnumMapEntry<IndexTypeEnum> const aIndexTypeMap[] =
+{
+ { XML_TABLE_OF_CONTENT, TEXT_INDEX_TOC },
+ { XML_ALPHABETICAL_INDEX, TEXT_INDEX_ALPHABETICAL },
+ { XML_TABLE_INDEX, TEXT_INDEX_TABLE },
+ { XML_OBJECT_INDEX, TEXT_INDEX_OBJECT },
+ { XML_BIBLIOGRAPHY, TEXT_INDEX_BIBLIOGRAPHY },
+ { XML_USER_INDEX, TEXT_INDEX_USER },
+ { XML_ILLUSTRATION_INDEX, TEXT_INDEX_ILLUSTRATION },
+ { XML_TOKEN_INVALID, IndexTypeEnum(0) }
+};
+
+
+XMLIndexTOCContext::XMLIndexTOCContext(SvXMLImport& rImport,
+ sal_Int32 nElement)
+ : SvXMLImportContext(rImport)
+ , eIndexType(TEXT_INDEX_UNKNOWN)
+ , bValid(false)
+{
+ if (IsTokenInNamespace(nElement, XML_NAMESPACE_TEXT))
+ {
+ if (SvXMLUnitConverter::convertEnum(eIndexType, SvXMLImport::getNameFromToken(nElement), aIndexTypeMap))
+ {
+ // check for array index:
+ OSL_ENSURE(unsigned(eIndexType) < (SAL_N_ELEMENTS(aIndexServiceMap)), "index out of range");
+ OSL_ENSURE(SAL_N_ELEMENTS(aIndexServiceMap) ==
+ SAL_N_ELEMENTS(aIndexSourceElementMap),
+ "service and source element maps must be same size");
+ bValid = true;
+ }
+ }
+}
+
+XMLIndexTOCContext::~XMLIndexTOCContext()
+{
+}
+
+void XMLIndexTOCContext::startFastElement(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ if (!bValid)
+ return;
+
+ // find text:style-name attribute and set section style
+ // find text:protected and set value
+ // find text:name and set value (if not empty)
+ bool bProtected = false;
+ OUString sIndexName;
+ OUString sXmlId;
+ XMLPropStyleContext* pStyle(nullptr);
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ switch(aIter.getToken())
+ {
+ case XML_ELEMENT(TEXT, XML_STYLE_NAME):
+ {
+ pStyle = GetImport().GetTextImport()->FindSectionStyle(
+ aIter.toString());
+ break;
+ }
+ case XML_ELEMENT(TEXT, XML_PROTECTED):
+ {
+ bool bTmp(false);
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bProtected = bTmp;
+ }
+ break;
+ }
+ case XML_ELEMENT(TEXT, XML_NAME):
+ {
+ sIndexName = aIter.toString();
+ break;
+ }
+ case XML_ELEMENT(XML, XML_ID):
+ {
+ sXmlId = aIter.toString();
+ break;
+ }
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+
+ // create table of content (via MultiServiceFactory)
+ Reference<XMultiServiceFactory> xFactory(GetImport().GetModel(),
+ UNO_QUERY);
+ if( xFactory.is() )
+ {
+ Reference<XInterface> xIfc =
+ xFactory->createInstance(
+ OUString::createFromAscii(aIndexServiceMap[eIndexType]));
+ if( xIfc.is() )
+ {
+ // get Property set
+ Reference<XPropertySet> xPropSet(xIfc, UNO_QUERY);
+ xTOCPropertySet = xPropSet;
+
+ // insert section
+ // a) insert section
+ // The inserted index consists of an empty paragraph
+ // only, as well as an empty paragraph *after* the index
+ // b) insert marker after index, and put Cursor inside of the
+ // index
+
+ // preliminaries
+#ifndef DBG_UTIL
+ static constexpr OUStringLiteral sMarker(u" ");
+#else
+ static constexpr OUStringLiteral sMarker(u"Y");
+#endif
+ rtl::Reference<XMLTextImportHelper> rImport =
+ GetImport().GetTextImport();
+
+ // a) insert index
+ Reference<XTextContent> xTextContent(xIfc, UNO_QUERY);
+ try
+ {
+ GetImport().GetTextImport()->InsertTextContent(
+ xTextContent);
+ }
+ catch(const IllegalArgumentException& e)
+ {
+ // illegal argument? Then we can't accept indices here!
+ Sequence<OUString> aSeq { SvXMLImport::getNameFromToken(nElement) };
+ GetImport().SetError(
+ XMLERROR_FLAG_ERROR | XMLERROR_NO_INDEX_ALLOWED_HERE,
+ aSeq, e.Message, nullptr );
+
+ // set bValid to false, and return prematurely
+ bValid = false;
+ return;
+ }
+
+ // xml:id for RDF metadata
+ GetImport().SetXmlId(xIfc, sXmlId);
+
+ // b) insert marker and move cursor
+ rImport->InsertString(sMarker);
+ rImport->GetCursor()->goLeft(2, false);
+ }
+ }
+
+ // finally, check for redlines that should start at
+ // the section start node
+ if( bValid )
+ GetImport().GetTextImport()->RedlineAdjustStartNodeCursor();
+
+ if (pStyle != nullptr)
+ {
+ pStyle->FillPropertySet( xTOCPropertySet );
+ }
+
+ xTOCPropertySet->setPropertyValue( "IsProtected", Any(bProtected) );
+
+ if (!sIndexName.isEmpty())
+ {
+ xTOCPropertySet->setPropertyValue( "Name", Any(sIndexName) );
+ }
+
+}
+
+void XMLIndexTOCContext::endFastElement(sal_Int32 )
+{
+ // complete import of index by removing the markers (if the index
+ // was actually inserted, that is)
+ if( !bValid )
+ return;
+
+ // preliminaries
+ rtl::Reference<XMLTextImportHelper> rHelper= GetImport().GetTextImport();
+
+ // get rid of last paragraph (unless it's the only paragraph)
+ rHelper->GetCursor()->goRight(1, false);
+ if( xBodyContextRef.is() && xBodyContextRef->HasContent() )
+ {
+ rHelper->GetCursor()->goLeft(1, true);
+ rHelper->GetText()->insertString(rHelper->GetCursorAsRange(),
+ "", true);
+ }
+
+ // and delete second marker
+ rHelper->GetCursor()->goRight(1, true);
+ rHelper->GetText()->insertString(rHelper->GetCursorAsRange(),
+ "", true);
+
+ // check for Redlines on our end node
+ GetImport().GetTextImport()->RedlineAdjustStartNodeCursor();
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLIndexTOCContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
+{
+ SvXMLImportContextRef xContext;
+
+ // not valid -> ignore
+ if (!bValid)
+ return nullptr;
+
+ if (nElement == XML_ELEMENT(TEXT, XML_INDEX_BODY) )
+ {
+ rtl::Reference<XMLIndexBodyContext> xNewBodyContext = new XMLIndexBodyContext(GetImport());
+ xContext = xNewBodyContext;
+ if ( !xBodyContextRef.is() || !xBodyContextRef->HasContent() )
+ {
+ xBodyContextRef = xNewBodyContext;
+ }
+ }
+ else if (nElement == XML_ELEMENT(TEXT, aIndexSourceElementMap[eIndexType]))
+ {
+ // instantiate source context for the appropriate index type
+ switch (eIndexType)
+ {
+ case TEXT_INDEX_TOC:
+ xContext = new XMLIndexTOCSourceContext(
+ GetImport(), xTOCPropertySet);
+ break;
+
+ case TEXT_INDEX_OBJECT:
+ xContext = new XMLIndexObjectSourceContext(
+ GetImport(), xTOCPropertySet);
+ break;
+
+ case TEXT_INDEX_ALPHABETICAL:
+ xContext = new XMLIndexAlphabeticalSourceContext(
+ GetImport(), xTOCPropertySet);
+ break;
+
+ case TEXT_INDEX_USER:
+ xContext = new XMLIndexUserSourceContext(
+ GetImport(), xTOCPropertySet);
+ break;
+
+ case TEXT_INDEX_BIBLIOGRAPHY:
+ xContext = new XMLIndexBibliographySourceContext(
+ GetImport(), xTOCPropertySet);
+ break;
+
+ case TEXT_INDEX_TABLE:
+ xContext = new XMLIndexTableSourceContext(
+ GetImport(), xTOCPropertySet);
+ break;
+
+ case TEXT_INDEX_ILLUSTRATION:
+ xContext = new XMLIndexIllustrationSourceContext(
+ GetImport(), xTOCPropertySet);
+ break;
+
+ default:
+ OSL_FAIL("index type not implemented");
+ break;
+ }
+ }
+ // else: ignore
+
+ return xContext;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexTOCContext.hxx b/xmloff/source/text/XMLIndexTOCContext.hxx
new file mode 100644
index 0000000000..47cd8ad2c2
--- /dev/null
+++ b/xmloff/source/text/XMLIndexTOCContext.hxx
@@ -0,0 +1,82 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <com/sun/star/uno/Reference.h>
+
+
+namespace com::sun::star {
+ namespace xml::sax { class XAttributeList; }
+ namespace beans { class XPropertySet; }
+}
+
+
+enum IndexTypeEnum
+{
+ TEXT_INDEX_TOC,
+ TEXT_INDEX_ALPHABETICAL,
+ TEXT_INDEX_TABLE,
+ TEXT_INDEX_OBJECT,
+ TEXT_INDEX_BIBLIOGRAPHY,
+ TEXT_INDEX_USER,
+ TEXT_INDEX_ILLUSTRATION,
+
+ TEXT_INDEX_UNKNOWN
+};
+
+class XMLIndexBodyContext;
+/**
+ * Import all indices.
+ *
+ * Originally, this class would import only the TOC (table of
+ * content), but now it's role has been expanded to handle all
+ * indices, and hence is named inappropriately. Depending on the
+ * element name it decides which index source element context to create.
+ */
+class XMLIndexTOCContext final : public SvXMLImportContext
+{
+ /** XPropertySet of the index */
+ css::uno::Reference<css::beans::XPropertySet> xTOCPropertySet;
+
+ enum IndexTypeEnum eIndexType;
+
+ bool bValid;
+
+ rtl::Reference<XMLIndexBodyContext> xBodyContextRef;
+
+public:
+
+ XMLIndexTOCContext( SvXMLImport& rImport, sal_Int32 nElement );
+
+ virtual ~XMLIndexTOCContext() override;
+
+ virtual void SAL_CALL startFastElement(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexTOCSourceContext.cxx b/xmloff/source/text/XMLIndexTOCSourceContext.cxx
new file mode 100644
index 0000000000..8850493b86
--- /dev/null
+++ b/xmloff/source/text/XMLIndexTOCSourceContext.cxx
@@ -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/.
+ *
+ * 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 "XMLIndexTOCSourceContext.hxx"
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XIndexReplace.hpp>
+#include <sax/tools/converter.hxx>
+#include "XMLIndexTemplateContext.hxx"
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/txtimp.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <rtl/ustring.hxx>
+
+
+using namespace ::xmloff::token;
+
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Any;
+
+XMLIndexTOCSourceContext::XMLIndexTOCSourceContext(
+ SvXMLImport& rImport,
+ Reference<XPropertySet> & rPropSet)
+: XMLIndexSourceBaseContext(rImport, rPropSet, UseStyles::Level)
+ // use all chapters by default
+, nOutlineLevel(rImport.GetTextImport()->GetChapterNumbering()->getCount())
+, bUseOutline(true)
+, bUseMarks(true)
+, bUseParagraphStyles(false)
+{
+}
+
+XMLIndexTOCSourceContext::~XMLIndexTOCSourceContext()
+{
+}
+
+void XMLIndexTOCSourceContext::ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)
+{
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(TEXT, XML_OUTLINE_LEVEL):
+ if ( IsXMLToken( aIter, XML_NONE ) )
+ {
+ // #104651# use OUTLINE_LEVEL and USE_OUTLINE_LEVEL instead of
+ // OUTLINE_LEVEL with values none|1..10. For backwards
+ // compatibility, 'none' must still be read.
+ bUseOutline = false;
+ }
+ else
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertNumber(
+ nTmp, aIter.toView(), 1, GetImport().GetTextImport()->
+ GetChapterNumbering()->getCount()))
+ {
+ bUseOutline = true;
+ nOutlineLevel = nTmp;
+ }
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_USE_OUTLINE_LEVEL):
+ {
+ bool bTmp(false);
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bUseOutline = bTmp;
+ }
+ break;
+ }
+
+
+ case XML_ELEMENT(TEXT, XML_USE_INDEX_MARKS):
+ {
+ bool bTmp(false);
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bUseMarks = bTmp;
+ }
+ break;
+ }
+
+ case XML_ELEMENT(TEXT, XML_USE_INDEX_SOURCE_STYLES):
+ {
+ bool bTmp(false);
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bUseParagraphStyles = bTmp;
+ }
+ break;
+ }
+
+ default:
+ // default: ask superclass
+ XMLIndexSourceBaseContext::ProcessAttribute(aIter);
+ break;
+ }
+}
+
+void XMLIndexTOCSourceContext::endFastElement(sal_Int32 nElement)
+{
+ rIndexPropertySet->setPropertyValue("CreateFromMarks", css::uno::Any(bUseMarks));
+ rIndexPropertySet->setPropertyValue("CreateFromOutline", css::uno::Any(bUseOutline));
+ rIndexPropertySet->setPropertyValue("CreateFromLevelParagraphStyles", css::uno::Any(bUseParagraphStyles));
+
+ rIndexPropertySet->setPropertyValue("Level", css::uno::Any(static_cast<sal_Int16>(nOutlineLevel)));
+
+ // process common attributes
+ XMLIndexSourceBaseContext::endFastElement(nElement);
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLIndexTOCSourceContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ if ( nElement == XML_ELEMENT(TEXT, XML_TABLE_OF_CONTENT_ENTRY_TEMPLATE) )
+ {
+ return new XMLIndexTemplateContext(GetImport(), rIndexPropertySet,
+ aSvLevelNameTOCMap,
+ XML_OUTLINE_LEVEL,
+ aLevelStylePropNameTOCMap,
+ aAllowedTokenTypesTOC, true );
+ }
+ else
+ {
+ return XMLIndexSourceBaseContext::createFastChildContext(nElement,
+ xAttrList);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexTOCSourceContext.hxx b/xmloff/source/text/XMLIndexTOCSourceContext.hxx
new file mode 100644
index 0000000000..f8129fc149
--- /dev/null
+++ b/xmloff/source/text/XMLIndexTOCSourceContext.hxx
@@ -0,0 +1,62 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include "XMLIndexSourceBaseContext.hxx"
+#include <com/sun/star/uno/Reference.h>
+
+
+namespace com::sun::star {
+ namespace xml::sax { class XAttributeList; }
+ namespace beans { class XPropertySet; }
+}
+
+
+/**
+ * Import table of context source element
+ */
+class XMLIndexTOCSourceContext : public XMLIndexSourceBaseContext
+{
+ sal_Int32 nOutlineLevel;
+ bool bUseOutline;
+ bool bUseMarks;
+ bool bUseParagraphStyles;
+
+public:
+
+
+ XMLIndexTOCSourceContext(
+ SvXMLImport& rImport,
+ css::uno::Reference<css::beans::XPropertySet> & rPropSet);
+
+ virtual ~XMLIndexTOCSourceContext() override;
+
+protected:
+
+ virtual void ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter) override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexTOCStylesContext.cxx b/xmloff/source/text/XMLIndexTOCStylesContext.cxx
new file mode 100644
index 0000000000..ff9cfaa4cb
--- /dev/null
+++ b/xmloff/source/text/XMLIndexTOCStylesContext.cxx
@@ -0,0 +1,143 @@
+/* -*- 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 "XMLIndexTOCStylesContext.hxx"
+
+#include "XMLIndexSourceBaseContext.hxx"
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XIndexReplace.hpp>
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/txtimp.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <sax/tools/converter.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <rtl/ustring.hxx>
+
+
+using namespace ::xmloff::token;
+
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::container::XIndexReplace;
+
+
+
+XMLIndexTOCStylesContext::XMLIndexTOCStylesContext(
+ SvXMLImport& rImport, Reference<XPropertySet> & rPropSet)
+ : SvXMLImportContext(rImport)
+ , rTOCPropertySet(rPropSet)
+ , nOutlineLevel(0)
+{
+}
+
+XMLIndexTOCStylesContext::~XMLIndexTOCStylesContext()
+{
+}
+
+void XMLIndexTOCStylesContext::startFastElement(
+ sal_Int32 /*nElement*/,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ // find text:outline-level attribute
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ if ( aIter.getToken() == XML_ELEMENT(TEXT, XML_OUTLINE_LEVEL) )
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertNumber(
+ nTmp, aIter.toView(), 1,
+ GetImport().GetTextImport()->GetChapterNumbering()->
+ getCount()))
+ {
+ // API numbers 0..9, we number 1..10
+ nOutlineLevel = nTmp-1;
+ }
+ break;
+ }
+ }
+}
+
+void XMLIndexTOCStylesContext::endFastElement(sal_Int32 )
+{
+ // if valid...
+ if (nOutlineLevel < 0)
+ return;
+
+ // copy vector into sequence
+ const sal_Int32 nCount = aStyleNames.size();
+ Sequence<OUString> aStyleNamesSequence(nCount);
+ auto aStyleNamesSequenceRange = asNonConstRange(aStyleNamesSequence);
+ for(sal_Int32 i = 0; i < nCount; i++)
+ {
+ aStyleNamesSequenceRange[i] = GetImport().GetStyleDisplayName(
+ XmlStyleFamily::TEXT_PARAGRAPH,
+ aStyleNames[i] );
+ }
+
+ // get index replace
+ Any aAny = rTOCPropertySet->getPropertyValue("LevelParagraphStyles");
+ Reference<XIndexReplace> xIndexReplace;
+ aAny >>= xIndexReplace;
+
+ // set style names
+ xIndexReplace->replaceByIndex(nOutlineLevel, Any(aStyleNamesSequence));
+}
+
+namespace xmloff {
+
+OUString GetIndexSourceStyleName(
+ css::uno::Reference<css::xml::sax::XFastAttributeList> const& xAttrList)
+{
+ for (auto& rIter : sax_fastparser::castToFastAttributeList(xAttrList))
+ {
+ if (rIter.getToken() == XML_ELEMENT(TEXT, XML_STYLE_NAME))
+ {
+ return rIter.toString();
+ }
+ }
+ return OUString();
+}
+
+} // namespace xmloff
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLIndexTOCStylesContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ // check for index-source-style
+ if ( nElement == XML_ELEMENT(TEXT, XML_INDEX_SOURCE_STYLE) )
+ {
+ // find text:style-name attribute and record in aStyleNames
+ OUString const styleName(xmloff::GetIndexSourceStyleName(xAttrList));
+ if (!styleName.isEmpty())
+ {
+ aStyleNames.emplace_back(styleName);
+ }
+ }
+
+ // always return default context; we already got the interesting info
+ return new SvXMLImportContext(GetImport());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexTOCStylesContext.hxx b/xmloff/source/text/XMLIndexTOCStylesContext.hxx
new file mode 100644
index 0000000000..a34cf604f1
--- /dev/null
+++ b/xmloff/source/text/XMLIndexTOCStylesContext.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/.
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <com/sun/star/uno/Reference.h>
+
+#include <vector>
+
+namespace com::sun::star {
+ namespace xml::sax { class XAttributeList; }
+ namespace beans { class XPropertySet; }
+}
+
+
+/**
+ * Import <test:index-source-styles> elements and their children
+ *
+ * (Small hackery here: Because there's only one type of child
+ * elements with only one interesting attribute, we completely handle
+ * them inside the CreateChildContext method, rather than creating a
+ * new import class for them. This must be changed if children become
+ * more complex in future versions.)
+ */
+class XMLIndexTOCStylesContext : public SvXMLImportContext
+{
+ /// XPropertySet of the index
+ css::uno::Reference<css::beans::XPropertySet> & rTOCPropertySet;
+
+ /// style names for this level
+ ::std::vector< OUString > aStyleNames;
+
+ /// outline level
+ sal_Int32 nOutlineLevel;
+
+public:
+ XMLIndexTOCStylesContext(
+ SvXMLImport& rImport,
+ css::uno::Reference<css::beans::XPropertySet> & rPropSet );
+
+ virtual ~XMLIndexTOCStylesContext() override;
+
+protected:
+
+ virtual void SAL_CALL startFastElement(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexTabStopEntryContext.cxx b/xmloff/source/text/XMLIndexTabStopEntryContext.cxx
new file mode 100644
index 0000000000..cf7b339a04
--- /dev/null
+++ b/xmloff/source/text/XMLIndexTabStopEntryContext.cxx
@@ -0,0 +1,155 @@
+/* -*- 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 "XMLIndexTabStopEntryContext.hxx"
+
+#include <sax/tools/converter.hxx>
+
+#include "XMLIndexTemplateContext.hxx"
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/log.hxx>
+
+using namespace ::xmloff::token;
+
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::beans::PropertyValue;
+
+
+XMLIndexTabStopEntryContext::XMLIndexTabStopEntryContext(
+ SvXMLImport& rImport,
+ XMLIndexTemplateContext& rTemplate ) :
+ XMLIndexSimpleEntryContext(rImport, "TokenTabStop",
+ rTemplate),
+ nTabPosition(0),
+ bTabPositionOK(false),
+ bTabRightAligned(false),
+ bLeaderCharOK(false),
+ bWithTab(true) // #i21237#
+{
+}
+
+XMLIndexTabStopEntryContext::~XMLIndexTabStopEntryContext()
+{
+}
+
+void XMLIndexTabStopEntryContext::startFastElement(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ // process three attributes: type, position, leader char
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ switch(aIter.getToken())
+ {
+ case XML_ELEMENT(STYLE, XML_TYPE):
+ {
+ // if it's neither left nor right, value is
+ // ignored. Since left is default, we only need to
+ // check for right
+ bTabRightAligned = IsXMLToken( aIter, XML_RIGHT );
+ break;
+ }
+ case XML_ELEMENT(STYLE, XML_POSITION):
+ {
+ sal_Int32 nTmp;
+ if (GetImport().GetMM100UnitConverter().
+ convertMeasureToCore(nTmp, aIter.toView()))
+ {
+ nTabPosition = nTmp;
+ bTabPositionOK = true;
+ }
+ break;
+ }
+ case XML_ELEMENT(STYLE, XML_LEADER_CHAR):
+ {
+ sLeaderChar = aIter.toString();
+ // valid only, if we have a char!
+ bLeaderCharOK = !sLeaderChar.isEmpty();
+ break;
+ }
+ case XML_ELEMENT(STYLE, XML_WITH_TAB):
+ {
+ // #i21237#
+ bool bTmp(false);
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ bWithTab = bTmp;
+ break;
+ }
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ // else: unknown style: attribute -> ignore
+ }
+ }
+
+ // how many entries? #i21237#
+ m_nValues += 2 + (bTabPositionOK ? 1 : 0) + (bLeaderCharOK ? 1 : 0);
+
+ // now try parent class (for character style)
+ XMLIndexSimpleEntryContext::startFastElement( nElement, xAttrList );
+}
+
+void XMLIndexTabStopEntryContext::FillPropertyValues(
+ Sequence<PropertyValue> & rValues)
+{
+ // fill values from parent class (type + style name)
+ XMLIndexSimpleEntryContext::FillPropertyValues(rValues);
+
+ // get values array and next entry to be written;
+ sal_Int32 nNextEntry = m_bCharStyleNameOK ? 2 : 1;
+ PropertyValue* pValues = rValues.getArray();
+
+ // right aligned?
+ pValues[nNextEntry].Name = "TabStopRightAligned";
+ pValues[nNextEntry].Value <<= bTabRightAligned;
+ nNextEntry++;
+
+ // position
+ if (bTabPositionOK)
+ {
+ pValues[nNextEntry].Name = "TabStopPosition";
+ pValues[nNextEntry].Value <<= nTabPosition;
+ nNextEntry++;
+ }
+
+ // leader char
+ if (bLeaderCharOK)
+ {
+ pValues[nNextEntry].Name = "TabStopFillCharacter";
+ pValues[nNextEntry].Value <<= sLeaderChar;
+ nNextEntry++;
+ }
+
+ // tab character #i21237#
+ pValues[nNextEntry].Name = "WithTab";
+ pValues[nNextEntry].Value <<= bWithTab;
+ nNextEntry++;
+
+ // check whether we really filled all elements of the sequence
+ SAL_WARN_IF( nNextEntry != rValues.getLength(), "xmloff",
+ "length incorrectly precomputed!" );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexTabStopEntryContext.hxx b/xmloff/source/text/XMLIndexTabStopEntryContext.hxx
new file mode 100644
index 0000000000..5c208f6385
--- /dev/null
+++ b/xmloff/source/text/XMLIndexTabStopEntryContext.hxx
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include "XMLIndexSimpleEntryContext.hxx"
+#include <rtl/ustring.hxx>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/Sequence.h>
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+
+namespace com::sun::star {
+ namespace xml::sax { class XAttributeList; }
+}
+class XMLIndexTemplateContext;
+
+/**
+ * Import index entry templates
+ */
+class XMLIndexTabStopEntryContext : public XMLIndexSimpleEntryContext
+{
+ OUString sLeaderChar; /// fill ("leader") character
+ sal_Int32 nTabPosition; /// tab position
+ bool bTabPositionOK; /// is tab right aligned?
+ bool bTabRightAligned; /// is nTabPosition valid?
+ bool bLeaderCharOK; /// is sLeaderChar valid?
+ bool bWithTab; /// is tab char present? #i21237#
+
+public:
+
+
+ XMLIndexTabStopEntryContext(
+ SvXMLImport& rImport,
+ XMLIndexTemplateContext& rTemplate );
+
+ virtual ~XMLIndexTabStopEntryContext() override;
+
+protected:
+
+ virtual void SAL_CALL startFastElement(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+
+ /** fill property values for this template entry */
+ virtual void FillPropertyValues(
+ css::uno::Sequence<css::beans::PropertyValue> & rValues) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexTableSourceContext.cxx b/xmloff/source/text/XMLIndexTableSourceContext.cxx
new file mode 100644
index 0000000000..48855b6ac0
--- /dev/null
+++ b/xmloff/source/text/XMLIndexTableSourceContext.cxx
@@ -0,0 +1,146 @@
+/* -*- 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 "XMLIndexTableSourceContext.hxx"
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/text/ReferenceFieldPart.hpp>
+
+#include <sax/tools/converter.hxx>
+
+#include "XMLIndexTemplateContext.hxx"
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlement.hxx>
+#include <rtl/ustring.hxx>
+
+
+using namespace ::com::sun::star::text;
+using namespace ::xmloff::token;
+
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Any;
+
+XMLIndexTableSourceContext::XMLIndexTableSourceContext(
+ SvXMLImport& rImport, Reference<XPropertySet> & rPropSet)
+ : XMLIndexSourceBaseContext(rImport, rPropSet, UseStyles::Single)
+ , nDisplayFormat(0)
+ , bSequenceOK(false)
+ , bDisplayFormatOK(false)
+ , bUseCaption(true)
+{
+}
+
+XMLIndexTableSourceContext::~XMLIndexTableSourceContext()
+{
+}
+
+SvXMLEnumMapEntry<sal_uInt16> const lcl_aReferenceTypeTokenMap[] =
+{
+
+ { XML_TEXT, ReferenceFieldPart::TEXT },
+ { XML_CATEGORY_AND_VALUE, ReferenceFieldPart::CATEGORY_AND_NUMBER },
+ { XML_CAPTION, ReferenceFieldPart::ONLY_CAPTION },
+
+ // wrong values that previous versions wrote:
+ { XML_CHAPTER, ReferenceFieldPart::CATEGORY_AND_NUMBER },
+ { XML_PAGE, ReferenceFieldPart::ONLY_CAPTION },
+
+ { XML_TOKEN_INVALID, 0 }
+};
+
+void XMLIndexTableSourceContext::ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)
+{
+ bool bTmp(false);
+
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(TEXT, XML_USE_CAPTION):
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bUseCaption = bTmp;
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_CAPTION_SEQUENCE_NAME):
+ sSequence = aIter.toString();
+ bSequenceOK = true;
+ break;
+
+ case XML_ELEMENT(TEXT, XML_CAPTION_SEQUENCE_FORMAT):
+ {
+ sal_uInt16 nTmp;
+ if (SvXMLUnitConverter::convertEnum(nTmp, aIter.toView(),
+ lcl_aReferenceTypeTokenMap))
+ {
+ nDisplayFormat = nTmp;
+ bDisplayFormatOK = true;
+ }
+ break;
+ }
+
+ default:
+ XMLIndexSourceBaseContext::ProcessAttribute(aIter);
+ break;
+ }
+}
+
+void XMLIndexTableSourceContext::endFastElement(sal_Int32 nElement)
+{
+ rIndexPropertySet->setPropertyValue("CreateFromLabels", css::uno::Any(bUseCaption));
+
+ if (bSequenceOK)
+ {
+ rIndexPropertySet->setPropertyValue("LabelCategory", css::uno::Any(sSequence));
+ }
+
+ if (bDisplayFormatOK)
+ {
+ rIndexPropertySet->setPropertyValue("LabelDisplayType", css::uno::Any(nDisplayFormat));
+ }
+
+ XMLIndexSourceBaseContext::endFastElement(nElement);
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLIndexTableSourceContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ if ( nElement == XML_ELEMENT(TEXT, XML_TABLE_INDEX_ENTRY_TEMPLATE) )
+ {
+ return new XMLIndexTemplateContext(GetImport(), rIndexPropertySet,
+ aLevelNameTableMap,
+ XML_TOKEN_INVALID, // no outline-level attr
+ aLevelStylePropNameTableMap,
+ aAllowedTokenTypesTable);
+ }
+ else
+ {
+ return XMLIndexSourceBaseContext::createFastChildContext(nElement,
+ xAttrList);
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexTableSourceContext.hxx b/xmloff/source/text/XMLIndexTableSourceContext.hxx
new file mode 100644
index 0000000000..1a0a7b0bfb
--- /dev/null
+++ b/xmloff/source/text/XMLIndexTableSourceContext.hxx
@@ -0,0 +1,63 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include "XMLIndexSourceBaseContext.hxx"
+#include <com/sun/star/uno/Reference.h>
+
+
+namespace com::sun::star {
+ namespace xml::sax { class XAttributeList; }
+ namespace beans { class XPropertySet; }
+}
+
+
+/**
+ * Import table index source element
+ */
+class XMLIndexTableSourceContext : public XMLIndexSourceBaseContext
+{
+ OUString sSequence;
+ sal_Int16 nDisplayFormat;
+
+ bool bSequenceOK;
+ bool bDisplayFormatOK;
+ bool bUseCaption;
+
+public:
+
+ XMLIndexTableSourceContext(
+ SvXMLImport& rImport,
+ css::uno::Reference<css::beans::XPropertySet> & rPropSet);
+
+ virtual ~XMLIndexTableSourceContext() override;
+
+protected:
+
+ virtual void ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter) override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexTemplateContext.cxx b/xmloff/source/text/XMLIndexTemplateContext.cxx
new file mode 100644
index 0000000000..411e4c6b94
--- /dev/null
+++ b/xmloff/source/text/XMLIndexTemplateContext.cxx
@@ -0,0 +1,420 @@
+/* -*- 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 "XMLIndexTemplateContext.hxx"
+#include "XMLIndexSimpleEntryContext.hxx"
+#include "XMLIndexSpanEntryContext.hxx"
+#include "XMLIndexTabStopEntryContext.hxx"
+#include "XMLIndexBibliographyEntryContext.hxx"
+#include "XMLIndexChapterInfoEntryContext.hxx"
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/txtimp.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlement.hxx>
+#include <tools/debug.hxx>
+#include <rtl/ustring.hxx>
+#include <sal/log.hxx>
+#include <com/sun/star/container/XIndexReplace.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include <algorithm>
+
+using namespace ::xmloff::token;
+
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::beans::PropertyValues;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::container::XIndexReplace;
+
+XMLIndexTemplateContext::XMLIndexTemplateContext(
+ SvXMLImport& rImport,
+ Reference<XPropertySet> & rPropSet,
+ const SvXMLEnumMapEntry<sal_uInt16>* pLevelNameMap,
+ enum XMLTokenEnum eLevelAttrName,
+ const char** pLevelStylePropMap,
+ const bool* pAllowedTokenTypes,
+ bool bT )
+: SvXMLImportContext(rImport)
+, pOutlineLevelNameMap(pLevelNameMap)
+, eOutlineLevelAttrName(eLevelAttrName)
+, pOutlineLevelStylePropMap(pLevelStylePropMap)
+, pAllowedTokenTypesMap(pAllowedTokenTypes)
+, nOutlineLevel(1) // all indices have level 1 (0 is for header)
+, bStyleNameOK(false)
+, bOutlineLevelOK(false)
+, bTOC( bT )
+, rPropertySet(rPropSet)
+{
+ DBG_ASSERT( ((XML_TOKEN_INVALID != eLevelAttrName) && (nullptr != pLevelNameMap))
+ || ((XML_TOKEN_INVALID == eLevelAttrName) && (nullptr == pLevelNameMap)),
+ "need both, attribute name and value map, or neither" );
+ SAL_WARN_IF( nullptr == pOutlineLevelStylePropMap, "xmloff", "need property name map" );
+ SAL_WARN_IF( nullptr == pAllowedTokenTypes, "xmloff", "need allowed tokens map" );
+
+ // no map for outline-level? then use 1
+ if (nullptr == pLevelNameMap)
+ {
+ nOutlineLevel = 1;
+ bOutlineLevelOK = true;
+ }
+}
+
+XMLIndexTemplateContext::~XMLIndexTemplateContext()
+{
+}
+
+
+void XMLIndexTemplateContext::addTemplateEntry(
+ const PropertyValues& aValues)
+{
+ aValueVector.push_back(aValues);
+}
+
+
+void XMLIndexTemplateContext::startFastElement(
+ sal_Int32 /*nElement*/,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ // process two attributes: style-name, outline-level
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ if(aIter.getToken() == XML_ELEMENT(TEXT, XML_STYLE_NAME))
+ {
+ // style name
+ sStyleName = aIter.toString();
+ bStyleNameOK = true;
+ }
+ else if (aIter.getToken() == XML_ELEMENT(TEXT, eOutlineLevelAttrName))
+ {
+ // we have an attr name! Then see if we have the attr, too.
+ // outline level
+ sal_uInt16 nTmp;
+ if (SvXMLUnitConverter::convertEnum(nTmp, aIter.toView(), pOutlineLevelNameMap))
+ {
+ nOutlineLevel = nTmp;
+ bOutlineLevelOK = true;
+ }
+ // else: illegal value -> ignore
+ }
+ // else: attribute not in text namespace -> ignore
+ }
+}
+
+void XMLIndexTemplateContext::endFastElement(sal_Int32 )
+{
+ if (!bOutlineLevelOK)
+ return;
+
+ const sal_Int32 nCount = aValueVector.size();
+ Sequence<PropertyValues> aValueSequence(nCount);
+ std::copy(aValueVector.begin(), aValueVector.end(), aValueSequence.getArray());
+
+ // get LevelFormat IndexReplace ...
+ Any aAny = rPropertySet->getPropertyValue("LevelFormat");
+ Reference<XIndexReplace> xIndexReplace;
+ aAny >>= xIndexReplace;
+
+ // ... and insert
+ xIndexReplace->replaceByIndex(nOutlineLevel, Any(aValueSequence));
+
+ if (!bStyleNameOK)
+ return;
+
+ const char* pStyleProperty =
+ pOutlineLevelStylePropMap[nOutlineLevel];
+
+ DBG_ASSERT(nullptr != pStyleProperty, "need property name");
+ if (nullptr == pStyleProperty)
+ return;
+
+ OUString sDisplayStyleName =
+ GetImport().GetStyleDisplayName(
+ XmlStyleFamily::TEXT_PARAGRAPH,
+ sStyleName );
+ // #i50288#: Check if style exists
+ const Reference < css::container::XNameContainer > & rStyles =
+ GetImport().GetTextImport()->GetParaStyles();
+ if( rStyles.is() &&
+ rStyles->hasByName( sDisplayStyleName ) )
+ {
+ rPropertySet->setPropertyValue(
+ OUString::createFromAscii(pStyleProperty), css::uno::Any(sDisplayStyleName));
+ }
+}
+
+namespace {
+/// template token types; used for aTokenTypeMap parameter
+enum TemplateTokenType
+{
+ XML_TOK_INDEX_TYPE_ENTRY_TEXT = 0,
+ XML_TOK_INDEX_TYPE_TAB_STOP,
+ XML_TOK_INDEX_TYPE_TEXT,
+ XML_TOK_INDEX_TYPE_PAGE_NUMBER,
+ XML_TOK_INDEX_TYPE_CHAPTER,
+ XML_TOK_INDEX_TYPE_LINK_START,
+ XML_TOK_INDEX_TYPE_LINK_END,
+ XML_TOK_INDEX_TYPE_BIBLIOGRAPHY
+};
+
+}
+
+SvXMLEnumMapEntry<TemplateTokenType> const aTemplateTokenTypeMap[] =
+{
+ { XML_INDEX_ENTRY_TEXT, XML_TOK_INDEX_TYPE_ENTRY_TEXT },
+ { XML_INDEX_ENTRY_TAB_STOP, XML_TOK_INDEX_TYPE_TAB_STOP },
+ { XML_INDEX_ENTRY_SPAN, XML_TOK_INDEX_TYPE_TEXT },
+ { XML_INDEX_ENTRY_PAGE_NUMBER, XML_TOK_INDEX_TYPE_PAGE_NUMBER },
+ { XML_INDEX_ENTRY_CHAPTER, XML_TOK_INDEX_TYPE_CHAPTER },
+ { XML_INDEX_ENTRY_LINK_START, XML_TOK_INDEX_TYPE_LINK_START },
+ { XML_INDEX_ENTRY_LINK_END, XML_TOK_INDEX_TYPE_LINK_END },
+ { XML_INDEX_ENTRY_BIBLIOGRAPHY, XML_TOK_INDEX_TYPE_BIBLIOGRAPHY },
+ { XML_TOKEN_INVALID, TemplateTokenType(0) }
+};
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLIndexTemplateContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
+{
+ SvXMLImportContext* pContext = nullptr;
+
+ if (IsTokenInNamespace(nElement, XML_NAMESPACE_TEXT) || IsTokenInNamespace(nElement, XML_NAMESPACE_LO_EXT))
+ {
+ TemplateTokenType nToken;
+ if (SvXMLUnitConverter::convertEnum(nToken, SvXMLImport::getNameFromToken(nElement),
+ aTemplateTokenTypeMap))
+ {
+ // can this index accept this kind of token?
+ if (pAllowedTokenTypesMap[nToken])
+ {
+ switch (nToken)
+ {
+ case XML_TOK_INDEX_TYPE_ENTRY_TEXT:
+ pContext = new XMLIndexSimpleEntryContext(
+ GetImport(), "TokenEntryText", *this);
+ break;
+
+ case XML_TOK_INDEX_TYPE_PAGE_NUMBER:
+ pContext = new XMLIndexSimpleEntryContext(
+ GetImport(), "TokenPageNumber", *this);
+ break;
+
+ case XML_TOK_INDEX_TYPE_LINK_START:
+ pContext = new XMLIndexSimpleEntryContext(
+ GetImport(), "TokenHyperlinkStart", *this);
+ break;
+
+ case XML_TOK_INDEX_TYPE_LINK_END:
+ pContext = new XMLIndexSimpleEntryContext(
+ GetImport(), "TokenHyperlinkEnd", *this);
+ break;
+
+ case XML_TOK_INDEX_TYPE_TEXT:
+ pContext = new XMLIndexSpanEntryContext(
+ GetImport(), *this);
+ break;
+
+ case XML_TOK_INDEX_TYPE_TAB_STOP:
+ pContext = new XMLIndexTabStopEntryContext(
+ GetImport(), *this);
+ break;
+
+ case XML_TOK_INDEX_TYPE_BIBLIOGRAPHY:
+ pContext = new XMLIndexBibliographyEntryContext(
+ GetImport(), *this);
+ break;
+
+ case XML_TOK_INDEX_TYPE_CHAPTER:
+ pContext = new XMLIndexChapterInfoEntryContext(
+ GetImport(), *this, bTOC );
+ break;
+
+ default:
+ // ignore!
+ break;
+ }
+ }
+ }
+ }
+
+ // ignore unknown
+ return pContext;
+}
+
+
+// maps for the XMLIndexTemplateContext constructor
+
+
+// table of content and user defined index:
+
+const SvXMLEnumMapEntry<sal_uInt16> aSvLevelNameTOCMap[] =
+{
+ { XML_1, 1 },
+ { XML_2, 2 },
+ { XML_3, 3 },
+ { XML_4, 4 },
+ { XML_5, 5 },
+ { XML_6, 6 },
+ { XML_7, 7 },
+ { XML_8, 8 },
+ { XML_9, 9 },
+ { XML_10, 10 },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+const char* aLevelStylePropNameTOCMap[] =
+ { nullptr, "ParaStyleLevel1", "ParaStyleLevel2", "ParaStyleLevel3",
+ "ParaStyleLevel4", "ParaStyleLevel5", "ParaStyleLevel6",
+ "ParaStyleLevel7", "ParaStyleLevel8", "ParaStyleLevel9",
+ "ParaStyleLevel10", nullptr };
+
+const bool aAllowedTokenTypesTOC[] =
+{
+ true, // XML_TOK_INDEX_TYPE_ENTRY_TEXT =
+ true, // XML_TOK_INDEX_TYPE_TAB_STOP,
+ true, // XML_TOK_INDEX_TYPE_TEXT,
+ true, // XML_TOK_INDEX_TYPE_PAGE_NUMBER,
+ true, // XML_TOK_INDEX_TYPE_CHAPTER,
+ true, // XML_TOK_INDEX_TYPE_LINK_START,
+ true, // XML_TOK_INDEX_TYPE_LINK_END,
+ false // XML_TOK_INDEX_TYPE_BIBLIOGRAPHY
+};
+
+const bool aAllowedTokenTypesUser[] =
+{
+ true, // XML_TOK_INDEX_TYPE_ENTRY_TEXT =
+ true, // XML_TOK_INDEX_TYPE_TAB_STOP,
+ true, // XML_TOK_INDEX_TYPE_TEXT,
+ true, // XML_TOK_INDEX_TYPE_PAGE_NUMBER,
+ true, // XML_TOK_INDEX_TYPE_CHAPTER,
+ true, // XML_TOK_INDEX_TYPE_LINK_START,
+ true, // XML_TOK_INDEX_TYPE_LINK_END,
+ false // XML_TOK_INDEX_TYPE_BIBLIOGRAPHY
+};
+
+
+// alphabetical index
+
+const SvXMLEnumMapEntry<sal_uInt16> aLevelNameAlphaMap[] =
+{
+ { XML_SEPARATOR, 1 },
+ { XML_1, 2 },
+ { XML_2, 3 },
+ { XML_3, 4 },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+const char* aLevelStylePropNameAlphaMap[] =
+ { nullptr, "ParaStyleSeparator", "ParaStyleLevel1", "ParaStyleLevel2",
+ "ParaStyleLevel3", nullptr };
+
+const bool aAllowedTokenTypesAlpha[] =
+{
+ true, // XML_TOK_INDEX_TYPE_ENTRY_TEXT =
+ true, // XML_TOK_INDEX_TYPE_TAB_STOP,
+ true, // XML_TOK_INDEX_TYPE_TEXT,
+ true, // XML_TOK_INDEX_TYPE_PAGE_NUMBER,
+ true, // XML_TOK_INDEX_TYPE_CHAPTER,
+ false, // XML_TOK_INDEX_TYPE_LINK_START,
+ false, // XML_TOK_INDEX_TYPE_LINK_END,
+ false // XML_TOK_INDEX_TYPE_BIBLIOGRAPHY
+};
+
+
+// bibliography index:
+
+const SvXMLEnumMapEntry<sal_uInt16> aLevelNameBibliographyMap[] =
+{
+ { XML_ARTICLE, 1 },
+ { XML_BOOK, 2 },
+ { XML_BOOKLET, 3 },
+ { XML_CONFERENCE, 4 },
+ { XML_CUSTOM1, 5 },
+ { XML_CUSTOM2, 6 },
+ { XML_CUSTOM3, 7 },
+ { XML_CUSTOM4, 8 },
+ { XML_CUSTOM5, 9 },
+ { XML_EMAIL, 10 },
+ { XML_INBOOK, 11 },
+ { XML_INCOLLECTION, 12 },
+ { XML_INPROCEEDINGS, 13 },
+ { XML_JOURNAL, 14 },
+ { XML_MANUAL, 15 },
+ { XML_MASTERSTHESIS, 16 },
+ { XML_MISC, 17 },
+ { XML_PHDTHESIS, 18 },
+ { XML_PROCEEDINGS, 19 },
+ { XML_TECHREPORT, 20 },
+ { XML_UNPUBLISHED, 21 },
+ { XML_WWW, 22 },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+// TODO: replace with real property names, when available
+const char* aLevelStylePropNameBibliographyMap[] =
+{
+ nullptr, "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
+ "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
+ "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
+ "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
+ "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
+ "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
+ "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
+ "ParaStyleLevel1", nullptr };
+
+const bool aAllowedTokenTypesBibliography[] =
+{
+ true, // XML_TOK_INDEX_TYPE_ENTRY_TEXT =
+ true, // XML_TOK_INDEX_TYPE_TAB_STOP,
+ true, // XML_TOK_INDEX_TYPE_TEXT,
+ true, // XML_TOK_INDEX_TYPE_PAGE_NUMBER,
+ false, // XML_TOK_INDEX_TYPE_CHAPTER,
+ false, // XML_TOK_INDEX_TYPE_LINK_START,
+ false, // XML_TOK_INDEX_TYPE_LINK_END,
+ true // XML_TOK_INDEX_TYPE_BIBLIOGRAPHY
+};
+
+
+// table, illustration and object index
+
+// no name map
+const SvXMLEnumMapEntry<sal_uInt16>* aLevelNameTableMap = nullptr;
+
+const char* aLevelStylePropNameTableMap[] =
+ { nullptr, "ParaStyleLevel1", nullptr };
+
+const bool aAllowedTokenTypesTable[] =
+{
+ true, // XML_TOK_INDEX_TYPE_ENTRY_TEXT =
+ true, // XML_TOK_INDEX_TYPE_TAB_STOP,
+ true, // XML_TOK_INDEX_TYPE_TEXT,
+ true, // XML_TOK_INDEX_TYPE_PAGE_NUMBER,
+ true, // XML_TOK_INDEX_TYPE_CHAPTER,
+ true, // XML_TOK_INDEX_TYPE_LINK_START,
+ true, // XML_TOK_INDEX_TYPE_LINK_END,
+ false // XML_TOK_INDEX_TYPE_BIBLIOGRAPHY
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexTemplateContext.hxx b/xmloff/source/text/XMLIndexTemplateContext.hxx
new file mode 100644
index 0000000000..424693d7e4
--- /dev/null
+++ b/xmloff/source/text/XMLIndexTemplateContext.hxx
@@ -0,0 +1,125 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmltoken.hxx>
+
+#include <vector>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/beans/PropertyValues.hpp>
+
+
+namespace com::sun::star {
+ namespace xml::sax { class XAttributeList; }
+ namespace beans { class XPropertySet; }
+}
+template<typename EnumT> struct SvXMLEnumMapEntry;
+
+
+// constants for the XMLIndexTemplateContext constructor
+
+// TOC and user defined index:
+extern const SvXMLEnumMapEntry<sal_uInt16> aSvLevelNameTOCMap[];
+extern const char* aLevelStylePropNameTOCMap[];
+extern const bool aAllowedTokenTypesTOC[];
+extern const bool aAllowedTokenTypesUser[];
+
+// alphabetical index:
+extern const SvXMLEnumMapEntry<sal_uInt16> aLevelNameAlphaMap[];
+extern const char* aLevelStylePropNameAlphaMap[];
+extern const bool aAllowedTokenTypesAlpha[];
+
+// bibliography:
+extern const SvXMLEnumMapEntry<sal_uInt16> aLevelNameBibliographyMap[];
+extern const char* aLevelStylePropNameBibliographyMap[];
+extern const bool aAllowedTokenTypesBibliography[];
+
+// table, illustration and object tables:
+extern const SvXMLEnumMapEntry<sal_uInt16>* aLevelNameTableMap; // NULL: no outline-level
+extern const char* aLevelStylePropNameTableMap[];
+extern const bool aAllowedTokenTypesTable[];
+
+
+/**
+ * Import index entry templates
+ */
+class XMLIndexTemplateContext : public SvXMLImportContext
+{
+ // pick up PropertyValues to be turned into a sequence.
+ ::std::vector< css::beans::PropertyValues > aValueVector;
+
+ OUString sStyleName;
+
+ const SvXMLEnumMapEntry<sal_uInt16>* pOutlineLevelNameMap;
+ enum ::xmloff::token::XMLTokenEnum eOutlineLevelAttrName;
+ const char** pOutlineLevelStylePropMap;
+ const bool* pAllowedTokenTypesMap;
+
+ sal_Int32 nOutlineLevel;
+ bool bStyleNameOK;
+ bool bOutlineLevelOK;
+ bool bTOC;
+
+ // PropertySet of current index
+ css::uno::Reference<css::beans::XPropertySet> & rPropertySet;
+
+public:
+ template<typename EnumT>
+ XMLIndexTemplateContext(
+ SvXMLImport& rImport,
+ css::uno::Reference<css::beans::XPropertySet> & rPropSet,
+ const SvXMLEnumMapEntry<EnumT>* aLevelNameMap,
+ enum ::xmloff::token::XMLTokenEnum eLevelAttrName,
+ const char** aLevelStylePropNameMap,
+ const bool* aAllowedTokenTypes,
+ bool bTOC_=false)
+ : XMLIndexTemplateContext(rImport,rPropSet,
+ reinterpret_cast<const SvXMLEnumMapEntry<sal_uInt16>*>(aLevelNameMap),
+ eLevelAttrName, aLevelStylePropNameMap, aAllowedTokenTypes, bTOC_) {}
+ XMLIndexTemplateContext(
+ SvXMLImport& rImport,
+ css::uno::Reference<css::beans::XPropertySet> & rPropSet,
+ const SvXMLEnumMapEntry<sal_uInt16>* aLevelNameMap,
+ enum ::xmloff::token::XMLTokenEnum eLevelAttrName,
+ const char** aLevelStylePropNameMap,
+ const bool* aAllowedTokenTypes,
+ bool bTOC);
+
+ virtual ~XMLIndexTemplateContext() override;
+
+ /** add template; to be called by child template entry contexts */
+ void addTemplateEntry(
+ const css::beans::PropertyValues& aValues);
+
+protected:
+
+ virtual void SAL_CALL startFastElement(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexTitleTemplateContext.cxx b/xmloff/source/text/XMLIndexTitleTemplateContext.cxx
new file mode 100644
index 0000000000..5d1f47fdb8
--- /dev/null
+++ b/xmloff/source/text/XMLIndexTitleTemplateContext.cxx
@@ -0,0 +1,95 @@
+/* -*- 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 "XMLIndexTitleTemplateContext.hxx"
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <sal/log.hxx>
+
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+using ::xmloff::token::XML_STYLE_NAME;
+
+
+XMLIndexTitleTemplateContext::XMLIndexTitleTemplateContext(
+ SvXMLImport& rImport,
+ Reference<XPropertySet> & rPropSet)
+: SvXMLImportContext(rImport)
+, bStyleNameOK(false)
+, rTOCPropertySet(rPropSet)
+{
+}
+
+
+XMLIndexTitleTemplateContext::~XMLIndexTitleTemplateContext()
+{
+}
+
+void XMLIndexTitleTemplateContext::startFastElement(
+ sal_Int32 /*nElement*/,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ // there's only one attribute: style-name
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ if ( aIter.getToken() == XML_ELEMENT(TEXT, XML_STYLE_NAME) )
+ {
+ sStyleName = aIter.toString();
+ OUString sDisplayStyleName = GetImport().GetStyleDisplayName(
+ XmlStyleFamily::TEXT_PARAGRAPH, sStyleName );
+ const Reference < css::container::XNameContainer >&
+ rStyles = GetImport().GetTextImport()->GetParaStyles();
+ bStyleNameOK = rStyles.is() && rStyles->hasByName( sDisplayStyleName );
+ }
+ else
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+}
+
+void XMLIndexTitleTemplateContext::endFastElement(sal_Int32 )
+{
+ Any aAny;
+
+ aAny <<= sContent.makeStringAndClear();
+ rTOCPropertySet->setPropertyValue("Title", aAny);
+
+ if (bStyleNameOK)
+ {
+ aAny <<= GetImport().GetStyleDisplayName(
+ XmlStyleFamily::TEXT_PARAGRAPH,
+ sStyleName );
+ rTOCPropertySet->setPropertyValue("ParaStyleHeading", aAny);
+ }
+}
+
+void XMLIndexTitleTemplateContext::characters(
+ const OUString& sString)
+{
+ sContent.append(sString);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexTitleTemplateContext.hxx b/xmloff/source/text/XMLIndexTitleTemplateContext.hxx
new file mode 100644
index 0000000000..2de1954997
--- /dev/null
+++ b/xmloff/source/text/XMLIndexTitleTemplateContext.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/.
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <com/sun/star/uno/Reference.h>
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+
+
+namespace com::sun::star {
+ namespace beans { class XPropertySet; }
+ namespace xml::sax { class XAttributeList; }
+}
+
+
+/**
+ * Import index title templates
+ */
+class XMLIndexTitleTemplateContext : public SvXMLImportContext
+{
+ // paragraph style
+ OUString sStyleName;
+ bool bStyleNameOK;
+
+ // content
+ OUStringBuffer sContent;
+
+ // TOC property set
+ css::uno::Reference<css::beans::XPropertySet> & rTOCPropertySet;
+
+public:
+
+ XMLIndexTitleTemplateContext(
+ SvXMLImport& rImport,
+ css::uno::Reference<css::beans::XPropertySet> & rPropSet);
+
+ virtual ~XMLIndexTitleTemplateContext() override;
+
+protected:
+
+ /** process parameters */
+ virtual void SAL_CALL startFastElement(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+
+ /** set values */
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ /** pick up title characters */
+ virtual void SAL_CALL characters(const OUString& sString) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexUserSourceContext.cxx b/xmloff/source/text/XMLIndexUserSourceContext.cxx
new file mode 100644
index 0000000000..e139a66c83
--- /dev/null
+++ b/xmloff/source/text/XMLIndexUserSourceContext.cxx
@@ -0,0 +1,157 @@
+/* -*- 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 "XMLIndexUserSourceContext.hxx"
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <sax/tools/converter.hxx>
+#include "XMLIndexTemplateContext.hxx"
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <rtl/ustring.hxx>
+
+
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Any;
+using namespace ::xmloff::token;
+
+XMLIndexUserSourceContext::XMLIndexUserSourceContext(
+ SvXMLImport& rImport,
+ Reference<XPropertySet> & rPropSet)
+ : XMLIndexSourceBaseContext(rImport, rPropSet, UseStyles::Level),
+ bUseObjects(false),
+ bUseGraphic(false),
+ bUseMarks(false),
+ bUseTables(false),
+ bUseFrames(false),
+ bUseLevelFromSource(false),
+ bUseLevelParagraphStyles(false)
+{
+}
+
+XMLIndexUserSourceContext::~XMLIndexUserSourceContext()
+{
+}
+
+void XMLIndexUserSourceContext::ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)
+{
+ bool bTmp(false);
+
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(TEXT, XML_USE_INDEX_MARKS):
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bUseMarks = bTmp;
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_USE_OBJECTS):
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bUseObjects = bTmp;
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_USE_GRAPHICS):
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bUseGraphic = bTmp;
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_USE_TABLES):
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bUseTables = bTmp;
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_USE_FLOATING_FRAMES):
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bUseFrames = bTmp;
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_COPY_OUTLINE_LEVELS):
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bUseLevelFromSource = bTmp;
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_USE_INDEX_SOURCE_STYLES):
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bUseLevelParagraphStyles = bTmp;
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_INDEX_NAME):
+ sIndexName = aIter.toString();
+ break;
+
+ default:
+ XMLIndexSourceBaseContext::ProcessAttribute(aIter);
+ break;
+ }
+}
+
+void XMLIndexUserSourceContext::endFastElement(sal_Int32 nElement)
+{
+ rIndexPropertySet->setPropertyValue("CreateFromEmbeddedObjects", css::uno::Any(bUseObjects));
+ rIndexPropertySet->setPropertyValue("CreateFromGraphicObjects", css::uno::Any(bUseGraphic));
+ rIndexPropertySet->setPropertyValue("UseLevelFromSource", css::uno::Any(bUseLevelFromSource));
+ rIndexPropertySet->setPropertyValue("CreateFromMarks", css::uno::Any(bUseMarks));
+ rIndexPropertySet->setPropertyValue("CreateFromTables", css::uno::Any(bUseTables));
+ rIndexPropertySet->setPropertyValue("CreateFromTextFrames", css::uno::Any(bUseFrames));
+ rIndexPropertySet->setPropertyValue("CreateFromLevelParagraphStyles", css::uno::Any(bUseLevelParagraphStyles));
+
+ if( !sIndexName.isEmpty() )
+ {
+ rIndexPropertySet->setPropertyValue("UserIndexName", css::uno::Any(sIndexName));
+ }
+
+ XMLIndexSourceBaseContext::endFastElement(nElement);
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLIndexUserSourceContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ if ( nElement == XML_ELEMENT(TEXT, XML_USER_INDEX_ENTRY_TEMPLATE) )
+ {
+ return new XMLIndexTemplateContext(GetImport(), rIndexPropertySet,
+ aSvLevelNameTOCMap,
+ XML_OUTLINE_LEVEL,
+ aLevelStylePropNameTOCMap,
+ aAllowedTokenTypesUser);
+ }
+ else
+ {
+ return XMLIndexSourceBaseContext::createFastChildContext(nElement,
+ xAttrList);
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLIndexUserSourceContext.hxx b/xmloff/source/text/XMLIndexUserSourceContext.hxx
new file mode 100644
index 0000000000..c275f8a053
--- /dev/null
+++ b/xmloff/source/text/XMLIndexUserSourceContext.hxx
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include "XMLIndexSourceBaseContext.hxx"
+#include <com/sun/star/uno/Reference.h>
+
+
+namespace com::sun::star {
+ namespace xml::sax { class XAttributeList; }
+ namespace beans { class XPropertySet; }
+}
+
+
+/**
+ * Import user defined index source element
+ */
+class XMLIndexUserSourceContext : public XMLIndexSourceBaseContext
+{
+ bool bUseObjects;
+ bool bUseGraphic;
+ bool bUseMarks;
+ bool bUseTables;
+ bool bUseFrames;
+ bool bUseLevelFromSource;
+ bool bUseLevelParagraphStyles;
+ OUString sIndexName;
+
+public:
+
+ XMLIndexUserSourceContext(
+ SvXMLImport& rImport,
+ css::uno::Reference<css::beans::XPropertySet> & rPropSet);
+
+ virtual ~XMLIndexUserSourceContext() override;
+
+protected:
+
+ virtual void ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter) override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLLineNumberingExport.cxx b/xmloff/source/text/XMLLineNumberingExport.cxx
new file mode 100644
index 0000000000..613f2d0334
--- /dev/null
+++ b/xmloff/source/text/XMLLineNumberingExport.cxx
@@ -0,0 +1,185 @@
+/* -*- 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 "XMLLineNumberingExport.hxx"
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/text/XLineNumberingProperties.hpp>
+#include <com/sun/star/style/LineNumberPosition.hpp>
+#include <o3tl/any.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlement.hxx>
+
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::text::XLineNumberingProperties;
+
+
+XMLLineNumberingExport::XMLLineNumberingExport(SvXMLExport& rExp)
+: rExport(rExp)
+{
+}
+
+SvXMLEnumMapEntry<sal_uInt16> const aLineNumberPositionMap[] =
+{
+ { XML_LEFT, style::LineNumberPosition::LEFT },
+ { XML_RIGHT, style::LineNumberPosition::RIGHT },
+ { XML_INSIDE, style::LineNumberPosition::INSIDE },
+ { XML_OUTSIDE, style::LineNumberPosition::OUTSIDE },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+
+void XMLLineNumberingExport::Export()
+{
+ // export element if we have line numbering info
+ Reference<XLineNumberingProperties> xSupplier(rExport.GetModel(),
+ UNO_QUERY);
+ if (!xSupplier.is())
+ return;
+
+ Reference<XPropertySet> xLineNumbering =
+ xSupplier->getLineNumberingProperties();
+
+ if (!xLineNumbering.is())
+ return;
+
+ // char style
+ Any aAny = xLineNumbering->getPropertyValue("CharStyleName");
+ OUString sTmp;
+ aAny >>= sTmp;
+ if (!sTmp.isEmpty())
+ {
+ rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_STYLE_NAME,
+ rExport.EncodeStyleName( sTmp ));
+ }
+
+ // enable
+ aAny = xLineNumbering->getPropertyValue("IsOn");
+ if (! *o3tl::doAccess<bool>(aAny))
+ {
+ rExport.AddAttribute(XML_NAMESPACE_TEXT,
+ XML_NUMBER_LINES, XML_FALSE);
+ }
+
+ // count empty lines
+ aAny = xLineNumbering->getPropertyValue("CountEmptyLines");
+ if (! *o3tl::doAccess<bool>(aAny))
+ {
+ rExport.AddAttribute(XML_NAMESPACE_TEXT,
+ XML_COUNT_EMPTY_LINES, XML_FALSE);
+ }
+
+ // count in frames
+ aAny = xLineNumbering->getPropertyValue("CountLinesInFrames");
+ if (*o3tl::doAccess<bool>(aAny))
+ {
+ rExport.AddAttribute(XML_NAMESPACE_TEXT,
+ XML_COUNT_IN_TEXT_BOXES, XML_TRUE);
+ }
+
+ // restart numbering
+ aAny = xLineNumbering->getPropertyValue("RestartAtEachPage");
+ if (*o3tl::doAccess<bool>(aAny))
+ {
+ rExport.AddAttribute(XML_NAMESPACE_TEXT,
+ XML_RESTART_ON_PAGE, XML_TRUE);
+ }
+
+ // Distance
+ aAny = xLineNumbering->getPropertyValue("Distance");
+ sal_Int32 nLength = 0;
+ aAny >>= nLength;
+ if (nLength != 0)
+ {
+ OUStringBuffer sBuf;
+ rExport.GetMM100UnitConverter().convertMeasureToXML(
+ sBuf, nLength);
+ rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_OFFSET,
+ sBuf.makeStringAndClear());
+ }
+
+ // NumberingType
+ OUStringBuffer sNumPosBuf;
+ aAny = xLineNumbering->getPropertyValue("NumberingType");
+ sal_Int16 nFormat = 0;
+ aAny >>= nFormat;
+ rExport.GetMM100UnitConverter().convertNumFormat( sNumPosBuf, nFormat );
+ rExport.AddAttribute(XML_NAMESPACE_STYLE, XML_NUM_FORMAT,
+ sNumPosBuf.makeStringAndClear());
+ SvXMLUnitConverter::convertNumLetterSync( sNumPosBuf, nFormat );
+ if( !sNumPosBuf.isEmpty() )
+ {
+ rExport.AddAttribute(XML_NAMESPACE_STYLE,
+ XML_NUM_LETTER_SYNC,
+ sNumPosBuf.makeStringAndClear() );
+ }
+
+ // number position
+ aAny = xLineNumbering->getPropertyValue("NumberPosition");
+ sal_uInt16 nPosition = 0;
+ aAny >>= nPosition;
+ if (SvXMLUnitConverter::convertEnum(sNumPosBuf, nPosition,
+ aLineNumberPositionMap))
+ {
+ rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_NUMBER_POSITION,
+ sNumPosBuf.makeStringAndClear());
+ }
+
+ // sInterval
+ aAny = xLineNumbering->getPropertyValue("Interval");
+ sal_Int16 nLineInterval = 0;
+ aAny >>= nLineInterval;
+ rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_INCREMENT,
+ OUString::number(nLineInterval));
+
+ SvXMLElementExport aConfigElem(rExport, XML_NAMESPACE_TEXT,
+ XML_LINENUMBERING_CONFIGURATION,
+ true, true);
+
+ // line separator
+ aAny = xLineNumbering->getPropertyValue("SeparatorText");
+ OUString sSeparator;
+ aAny >>= sSeparator;
+ if (sSeparator.isEmpty())
+ return;
+
+ // SeparatorInterval
+ aAny = xLineNumbering->getPropertyValue("SeparatorInterval");
+ sal_Int16 nLineDistance = 0;
+ aAny >>= nLineDistance;
+ rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_INCREMENT,
+ OUString::number(nLineDistance));
+
+ SvXMLElementExport aSeparatorElem(rExport, XML_NAMESPACE_TEXT,
+ XML_LINENUMBERING_SEPARATOR,
+ true, false);
+ rExport.Characters(sSeparator);
+ // else: no configuration: don't save -> default
+ // can't even get supplier: don't save -> default
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLLineNumberingExport.hxx b/xmloff/source/text/XMLLineNumberingExport.hxx
new file mode 100644
index 0000000000..4beb2a2b46
--- /dev/null
+++ b/xmloff/source/text/XMLLineNumberingExport.hxx
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * 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 .
+ */
+
+#pragma once
+
+class SvXMLExport;
+
+/** export <text:linenumbering-configuration> and its child elements */
+class XMLLineNumberingExport
+{
+ SvXMLExport& rExport;
+
+public:
+ explicit XMLLineNumberingExport(SvXMLExport& rExp);
+
+ void Export();
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLLineNumberingImportContext.cxx b/xmloff/source/text/XMLLineNumberingImportContext.cxx
new file mode 100644
index 0000000000..0ba08972df
--- /dev/null
+++ b/xmloff/source/text/XMLLineNumberingImportContext.cxx
@@ -0,0 +1,233 @@
+/* -*- 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 <XMLLineNumberingImportContext.hxx>
+#include "XMLLineNumberingSeparatorImportContext.hxx"
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/text/XLineNumberingProperties.hpp>
+#include <com/sun/star/style/LineNumberPosition.hpp>
+#include <com/sun/star/style/NumberingType.hpp>
+#include <sax/tools/converter.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlement.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::style;
+using namespace ::xmloff::token;
+
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::xml::sax::XFastAttributeList;
+using ::com::sun::star::text::XLineNumberingProperties;
+
+
+constexpr OUStringLiteral gsCharStyleName(u"CharStyleName");
+constexpr OUStringLiteral gsCountEmptyLines(u"CountEmptyLines");
+constexpr OUStringLiteral gsCountLinesInFrames(u"CountLinesInFrames");
+constexpr OUStringLiteral gsDistance(u"Distance");
+constexpr OUStringLiteral gsInterval(u"Interval");
+constexpr OUStringLiteral gsSeparatorText(u"SeparatorText");
+constexpr OUStringLiteral gsNumberPosition(u"NumberPosition");
+constexpr OUStringLiteral gsNumberingType(u"NumberingType");
+constexpr OUStringLiteral gsIsOn(u"IsOn");
+constexpr OUStringLiteral gsRestartAtEachPage(u"RestartAtEachPage");
+constexpr OUStringLiteral gsSeparatorInterval(u"SeparatorInterval");
+
+XMLLineNumberingImportContext::XMLLineNumberingImportContext(
+ SvXMLImport& rImport)
+: SvXMLStyleContext(rImport, XmlStyleFamily::TEXT_LINENUMBERINGCONFIG)
+, sNumFormat(GetXMLToken(XML_1))
+, sNumLetterSync(GetXMLToken(XML_FALSE))
+, nOffset(-1)
+, nNumberPosition(style::LineNumberPosition::LEFT)
+, nIncrement(-1)
+, nSeparatorIncrement(-1)
+, bNumberLines(true)
+, bCountEmptyLines(true)
+, bCountInFloatingFrames(false)
+, bRestartNumbering(false)
+{
+}
+
+XMLLineNumberingImportContext::~XMLLineNumberingImportContext()
+{
+}
+
+void XMLLineNumberingImportContext::SetAttribute( sal_Int32 nElement,
+ const OUString& rValue )
+{
+ bool bTmp(false);
+ sal_Int32 nTmp;
+
+ switch (nElement)
+ {
+ case XML_ELEMENT(TEXT, XML_STYLE_NAME):
+ sStyleName = rValue;
+ break;
+
+ case XML_ELEMENT(TEXT, XML_NUMBER_LINES):
+ if (::sax::Converter::convertBool(bTmp, rValue))
+ {
+ bNumberLines = bTmp;
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_COUNT_EMPTY_LINES):
+ if (::sax::Converter::convertBool(bTmp, rValue))
+ {
+ bCountEmptyLines = bTmp;
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_COUNT_IN_TEXT_BOXES):
+ if (::sax::Converter::convertBool(bTmp, rValue))
+ {
+ bCountInFloatingFrames = bTmp;
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_RESTART_ON_PAGE):
+ if (::sax::Converter::convertBool(bTmp, rValue))
+ {
+ bRestartNumbering = bTmp;
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_OFFSET):
+ if (GetImport().GetMM100UnitConverter().
+ convertMeasureToCore(nTmp, rValue))
+ {
+ nOffset = nTmp;
+ }
+ break;
+
+ case XML_ELEMENT(STYLE, XML_NUM_FORMAT):
+ sNumFormat = rValue;
+ break;
+
+ case XML_ELEMENT(STYLE, XML_NUM_LETTER_SYNC):
+ sNumLetterSync = rValue;
+ break;
+
+ case XML_ELEMENT(TEXT, XML_NUMBER_POSITION):
+ {
+ static const SvXMLEnumMapEntry<sal_Int16> aLineNumberPositionMap[] =
+ {
+ { XML_LEFT, style::LineNumberPosition::LEFT },
+ { XML_RIGHT, style::LineNumberPosition::RIGHT },
+ { XML_INSIDE, style::LineNumberPosition::INSIDE },
+ { XML_OUTSIDE, style::LineNumberPosition::OUTSIDE },
+ { XML_TOKEN_INVALID, 0 }
+ };
+
+ (void)SvXMLUnitConverter::convertEnum(nNumberPosition, rValue,
+ aLineNumberPositionMap);
+ break;
+ }
+
+ case XML_ELEMENT(TEXT, XML_INCREMENT):
+ if (::sax::Converter::convertNumber(nTmp, rValue, 0))
+ {
+ nIncrement = static_cast<sal_Int16>(nTmp);
+ }
+ break;
+ }
+}
+
+void XMLLineNumberingImportContext::CreateAndInsert(bool)
+{
+ // insert and block mode is handled in insertStyleFamily
+
+ // we'll try to get the LineNumberingProperties
+ Reference<XLineNumberingProperties> xSupplier(GetImport().GetModel(),
+ UNO_QUERY);
+ if (!xSupplier.is())
+ return;
+
+ Reference<XPropertySet> xLineNumbering =
+ xSupplier->getLineNumberingProperties();
+
+ if (!xLineNumbering.is())
+ return;
+
+ Any aAny;
+
+ // set style name (if it exists)
+ if ( GetImport().GetStyles()->FindStyleChildContext(
+ XmlStyleFamily::TEXT_TEXT, sStyleName ) != nullptr )
+ {
+ aAny <<= GetImport().GetStyleDisplayName(
+ XmlStyleFamily::TEXT_TEXT, sStyleName );
+ xLineNumbering->setPropertyValue(gsCharStyleName, aAny);
+ }
+
+ xLineNumbering->setPropertyValue(gsSeparatorText, Any(sSeparator));
+ xLineNumbering->setPropertyValue(gsDistance, Any(nOffset));
+ xLineNumbering->setPropertyValue(gsNumberPosition, Any(nNumberPosition));
+
+ if (nIncrement >= 0)
+ {
+ xLineNumbering->setPropertyValue(gsInterval, Any(nIncrement));
+ }
+
+ if (nSeparatorIncrement >= 0)
+ {
+ xLineNumbering->setPropertyValue(gsSeparatorInterval, Any(nSeparatorIncrement));
+ }
+
+ xLineNumbering->setPropertyValue(gsIsOn, Any(bNumberLines));
+ xLineNumbering->setPropertyValue(gsCountEmptyLines, Any(bCountEmptyLines));
+ xLineNumbering->setPropertyValue(gsCountLinesInFrames, Any(bCountInFloatingFrames));
+ xLineNumbering->setPropertyValue(gsRestartAtEachPage, Any(bRestartNumbering));
+
+ sal_Int16 nNumType = NumberingType::ARABIC;
+ GetImport().GetMM100UnitConverter().convertNumFormat( nNumType,
+ sNumFormat,
+ sNumLetterSync );
+ xLineNumbering->setPropertyValue(gsNumberingType, Any(nNumType));
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLLineNumberingImportContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
+{
+ if ( nElement == XML_ELEMENT(TEXT, XML_LINENUMBERING_SEPARATOR) )
+ return new XMLLineNumberingSeparatorImportContext(GetImport(), *this);
+ return nullptr;
+}
+
+void XMLLineNumberingImportContext::SetSeparatorText(
+ const OUString& sText)
+{
+ sSeparator = sText;
+}
+
+void XMLLineNumberingImportContext::SetSeparatorIncrement(
+ sal_Int16 nIncr)
+{
+ nSeparatorIncrement = nIncr;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLLineNumberingSeparatorImportContext.cxx b/xmloff/source/text/XMLLineNumberingSeparatorImportContext.cxx
new file mode 100644
index 0000000000..1482494aed
--- /dev/null
+++ b/xmloff/source/text/XMLLineNumberingSeparatorImportContext.cxx
@@ -0,0 +1,78 @@
+/* -*- 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 "XMLLineNumberingSeparatorImportContext.hxx"
+
+#include <sax/tools/converter.hxx>
+#include <XMLLineNumberingImportContext.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+
+
+using namespace ::com::sun::star::uno;
+
+using ::xmloff::token::XML_INCREMENT;
+
+
+XMLLineNumberingSeparatorImportContext::XMLLineNumberingSeparatorImportContext(
+ SvXMLImport& rImport,
+ XMLLineNumberingImportContext& rLineNumbering) :
+ SvXMLImportContext(rImport),
+ rLineNumberingContext(rLineNumbering)
+{
+}
+
+XMLLineNumberingSeparatorImportContext::~XMLLineNumberingSeparatorImportContext()
+{
+}
+
+void XMLLineNumberingSeparatorImportContext::startFastElement(
+ sal_Int32 /*nElement*/,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
+ {
+ if ( aIter.getToken() == XML_ELEMENT(TEXT, XML_INCREMENT) )
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertNumber(nTmp, aIter.toView(), 0))
+ {
+ rLineNumberingContext.SetSeparatorIncrement(static_cast<sal_Int16>(nTmp));
+ }
+ // else: invalid number -> ignore
+ }
+ // else: unknown attribute -> ignore
+ }
+}
+
+void XMLLineNumberingSeparatorImportContext::characters(
+ const OUString& rChars )
+{
+ sSeparatorBuf.append(rChars);
+}
+
+void XMLLineNumberingSeparatorImportContext::endFastElement(sal_Int32 )
+{
+ rLineNumberingContext.SetSeparatorText(sSeparatorBuf.makeStringAndClear());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLLineNumberingSeparatorImportContext.hxx b/xmloff/source/text/XMLLineNumberingSeparatorImportContext.hxx
new file mode 100644
index 0000000000..110aae6dc9
--- /dev/null
+++ b/xmloff/source/text/XMLLineNumberingSeparatorImportContext.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/.
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/uno/Reference.h>
+
+
+namespace com::sun::star {
+ namespace xml::sax { class XAttributeList; }
+}
+class XMLLineNumberingImportContext;
+
+
+/** import <text:linenumbering-separator> elements */
+class XMLLineNumberingSeparatorImportContext : public SvXMLImportContext
+{
+ OUStringBuffer sSeparatorBuf;
+ XMLLineNumberingImportContext& rLineNumberingContext;
+
+public:
+
+
+ XMLLineNumberingSeparatorImportContext(
+ SvXMLImport& rImport,
+ XMLLineNumberingImportContext& rLineNumbering);
+
+ virtual ~XMLLineNumberingSeparatorImportContext() override;
+
+protected:
+
+ virtual void SAL_CALL startFastElement( sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& ) override;
+
+ virtual void SAL_CALL characters( const OUString& rChars ) override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLPropertyBackpatcher.cxx b/xmloff/source/text/XMLPropertyBackpatcher.cxx
new file mode 100644
index 0000000000..fef92ad213
--- /dev/null
+++ b/xmloff/source/text/XMLPropertyBackpatcher.cxx
@@ -0,0 +1,208 @@
+/* -*- 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 <memory>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/uno/Reference.h>
+
+#include <rtl/ustring.hxx>
+#include "XMLPropertyBackpatcher.hxx"
+#include <utility>
+#include <xmloff/txtimp.hxx>
+
+using ::std::map;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::beans::XPropertySet;
+
+
+template<class A>
+XMLPropertyBackpatcher<A>::XMLPropertyBackpatcher(
+ OUString sPropName)
+: sPropertyName(std::move(sPropName))
+{
+}
+
+
+template<class A>
+XMLPropertyBackpatcher<A>::~XMLPropertyBackpatcher()
+{
+}
+
+
+template<class A>
+void XMLPropertyBackpatcher<A>::ResolveId(
+ const OUString& sName,
+ A aValue)
+{
+ // insert ID into ID map
+ aIDMap[sName] = aValue;
+
+ // backpatch old references, if backpatch list exists
+ auto it = aBackpatchListMap.find(sName);
+ if (it == aBackpatchListMap.end())
+ return;
+
+ // aah, we have a backpatch list!
+ std::unique_ptr<BackpatchListType> pList = std::move(it->second);
+
+ // a) remove list from list map
+ aBackpatchListMap.erase(it);
+
+ // b) for every item, set SequenceNumber
+ // (and preserve Property, if appropriate)
+ Any aAny;
+ aAny <<= aValue;
+ for(const auto& rBackpatch : *pList)
+ {
+ rBackpatch->setPropertyValue(sPropertyName, aAny);
+ }
+ // else: no backpatch list -> then we're finished
+}
+
+template<class A>
+void XMLPropertyBackpatcher<A>::SetProperty(
+ const Reference<XPropertySet> & xPropSet,
+ const OUString& sName)
+{
+ if (aIDMap.count(sName))
+ {
+ // we know this ID -> set property
+ xPropSet->setPropertyValue(sPropertyName, css::uno::Any(aIDMap[sName]));
+ }
+ else
+ {
+ // ID unknown -> into backpatch list for later fixup
+ if (! aBackpatchListMap.count(sName))
+ {
+ // create backpatch list for this name
+ aBackpatchListMap.emplace(sName, new BackpatchListType);
+ }
+
+ // insert footnote
+ aBackpatchListMap[sName]->push_back(xPropSet);
+ }
+}
+
+// force instantiation of templates
+template class XMLPropertyBackpatcher<sal_Int16>;
+template class XMLPropertyBackpatcher<OUString>;
+
+struct XMLTextImportHelper::BackpatcherImpl
+{
+ /// backpatcher for references to footnotes and endnotes
+ ::std::unique_ptr< XMLPropertyBackpatcher<sal_Int16> >
+ m_pFootnoteBackpatcher;
+
+ /// backpatchers for references to sequences
+ ::std::unique_ptr< XMLPropertyBackpatcher<sal_Int16> >
+ m_pSequenceIdBackpatcher;
+
+ ::std::unique_ptr< XMLPropertyBackpatcher< OUString> >
+ m_pSequenceNameBackpatcher;
+};
+
+std::shared_ptr<XMLTextImportHelper::BackpatcherImpl>
+XMLTextImportHelper::MakeBackpatcherImpl()
+{
+ // n.b.: the shared_ptr stores the dtor!
+ return std::make_shared<BackpatcherImpl>();
+}
+
+static OUString GetSequenceNumber()
+{
+ return "SequenceNumber";
+}
+
+
+// XMLTextImportHelper
+
+// Code from XMLTextImportHelper using the XMLPropertyBackpatcher is
+// implemented here. The reason is that in the unxsols2 environment,
+// all templates are instantiated as file local (switch
+// -instances=static), and thus are not accessible from the outside.
+
+// The previous solution was to force additional instantiation of
+// XMLPropertyBackpatcher in txtimp.cxx. This solution combines all
+// usage of the XMLPropertyBackpatcher in XMLPropertyBackpatcher.cxx
+// instead.
+
+
+XMLPropertyBackpatcher<sal_Int16>& XMLTextImportHelper::GetFootnoteBP()
+{
+ if (!m_xBackpatcherImpl->m_pFootnoteBackpatcher)
+ {
+ m_xBackpatcherImpl->m_pFootnoteBackpatcher.reset(
+ new XMLPropertyBackpatcher<sal_Int16>(GetSequenceNumber()));
+ }
+ return *m_xBackpatcherImpl->m_pFootnoteBackpatcher;
+}
+
+XMLPropertyBackpatcher<sal_Int16>& XMLTextImportHelper::GetSequenceIdBP()
+{
+ if (!m_xBackpatcherImpl->m_pSequenceIdBackpatcher)
+ {
+ m_xBackpatcherImpl->m_pSequenceIdBackpatcher.reset(
+ new XMLPropertyBackpatcher<sal_Int16>(GetSequenceNumber()));
+ }
+ return *m_xBackpatcherImpl->m_pSequenceIdBackpatcher;
+}
+
+XMLPropertyBackpatcher<OUString>& XMLTextImportHelper::GetSequenceNameBP()
+{
+ if (!m_xBackpatcherImpl->m_pSequenceNameBackpatcher)
+ {
+ m_xBackpatcherImpl->m_pSequenceNameBackpatcher.reset(
+ new XMLPropertyBackpatcher<OUString>("SourceName"));
+ }
+ return *m_xBackpatcherImpl->m_pSequenceNameBackpatcher;
+}
+
+void XMLTextImportHelper::InsertFootnoteID(
+ const OUString& sXMLId,
+ sal_Int16 nAPIId)
+{
+ GetFootnoteBP().ResolveId(sXMLId, nAPIId);
+}
+
+void XMLTextImportHelper::ProcessFootnoteReference(
+ const OUString& sXMLId,
+ const Reference<XPropertySet> & xPropSet)
+{
+ GetFootnoteBP().SetProperty(xPropSet, sXMLId);
+}
+
+void XMLTextImportHelper::InsertSequenceID(
+ const OUString& sXMLId,
+ const OUString& sName,
+ sal_Int16 nAPIId)
+{
+ GetSequenceIdBP().ResolveId(sXMLId, nAPIId);
+ GetSequenceNameBP().ResolveId(sXMLId, sName);
+}
+
+void XMLTextImportHelper::ProcessSequenceReference(
+ const OUString& sXMLId,
+ const Reference<XPropertySet> & xPropSet)
+{
+ GetSequenceIdBP().SetProperty(xPropSet, sXMLId);
+ GetSequenceNameBP().SetProperty(xPropSet, sXMLId);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLPropertyBackpatcher.hxx b/xmloff/source/text/XMLPropertyBackpatcher.hxx
new file mode 100644
index 0000000000..3b3f273208
--- /dev/null
+++ b/xmloff/source/text/XMLPropertyBackpatcher.hxx
@@ -0,0 +1,97 @@
+/* -*- 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 .
+ */
+
+
+#pragma once
+
+#include <rtl/ustring.hxx>
+
+#include <map>
+#include <memory>
+#include <vector>
+
+namespace com::sun::star {
+ namespace beans { class XPropertySet; }
+ namespace uno { template<class A> class Reference; }
+}
+
+
+/** This class maintains an OUString->sal_Int16 mapping for cases in
+ * which an XPropertySet needs to be filled with values that are not
+ * yet known.
+ *
+ * A good example for appropriate use are footnotes and references to
+ * footnotes. Internally, the LibreOffice API numbers footnotes, and
+ * references to footnotes refer to that internal numbering. In the
+ * XML file format, these numbers are replaced with name strings. Now
+ * if during import of a document a reference to a footnote is
+ * encountered, two things can happen: 1) The footnote already
+ * appeared in the document. In this case the name is already known
+ * and the proper ID can be requested from the footnote. 2) The
+ * footnote will appear later in the document. In this case the ID is
+ * not yet known, and the reference-ID property of the reference
+ * cannot be determined. Hence, the reference has to be stored and the
+ * ID needs to bet set later, when the footnote is eventually found in
+ * the document.
+ *
+ * This class simplifies this process: If the footnote is found,
+ * ResolveId with the XML name and the ID is called. When a reference
+ * is encountered, SetProperty gets called with the reference's
+ * XPropertySet and the XML name. All remaining tasks are handled by
+ * the class.
+ */
+template <class A>
+class XMLPropertyBackpatcher
+{
+
+ /// name of property that gets set or backpatched
+ OUString sPropertyName;
+
+ /// backpatch list type
+ typedef ::std::vector<
+ css::uno::Reference<css::beans::XPropertySet> > BackpatchListType;
+
+ /// backpatch list for unresolved IDs
+ ::std::map<const OUString, std::unique_ptr<BackpatchListType>> aBackpatchListMap;
+
+ /// mapping of names -> IDs
+ ::std::map<const OUString, A> aIDMap;
+
+public:
+
+ explicit XMLPropertyBackpatcher(
+ OUString sPropertyName);
+
+ ~XMLPropertyBackpatcher();
+
+ /// resolve a known ID.
+ /// Call this as soon as the value for a particular name is known.
+ void ResolveId(
+ const OUString& sName,
+ A aValue);
+
+ /// Set property with the proper value for this name. If the value
+ /// is not yet known, store the XPropertySet in the backpatch list.
+ /// Use this whenever the value should be set, even if it is not yet known.
+ void SetProperty(
+ const css::uno::Reference<css::beans::XPropertySet> & xPropSet,
+ const OUString& sName);
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLRedlineExport.cxx b/xmloff/source/text/XMLRedlineExport.cxx
new file mode 100644
index 0000000000..33ddcdb179
--- /dev/null
+++ b/xmloff/source/text/XMLRedlineExport.cxx
@@ -0,0 +1,656 @@
+/* -*- 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 "XMLRedlineExport.hxx"
+#include <o3tl/any.hxx>
+#include <tools/debug.hxx>
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <osl/diagnose.h>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/UnknownPropertyException.hpp>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+
+#include <com/sun/star/container/XEnumeration.hpp>
+#include <com/sun/star/document/XRedlinesSupplier.hpp>
+#include <com/sun/star/text/XText.hpp>
+#include <com/sun/star/text/XTextContent.hpp>
+#include <com/sun/star/text/XTextSection.hpp>
+#include <com/sun/star/util/DateTime.hpp>
+
+#include <sax/tools/converter.hxx>
+
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <unotools/securityoptions.hxx>
+#include <tools/date.hxx>
+#include <tools/datetime.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+using ::com::sun::star::beans::PropertyValue;
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::beans::UnknownPropertyException;
+using ::com::sun::star::document::XRedlinesSupplier;
+using ::com::sun::star::container::XEnumerationAccess;
+using ::com::sun::star::container::XEnumeration;
+using ::com::sun::star::text::XText;
+using ::com::sun::star::text::XTextContent;
+using ::com::sun::star::text::XTextSection;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::Sequence;
+
+
+XMLRedlineExport::XMLRedlineExport(SvXMLExport& rExp)
+: sDeletion(GetXMLToken(XML_DELETION))
+, sFormatChange(GetXMLToken(XML_FORMAT_CHANGE))
+, sInsertion(GetXMLToken(XML_INSERTION))
+, rExport(rExp)
+, pCurrentChangesList(nullptr)
+{
+}
+
+
+XMLRedlineExport::~XMLRedlineExport()
+{
+}
+
+
+void XMLRedlineExport::ExportChange(
+ const Reference<XPropertySet> & rPropSet,
+ bool bAutoStyle)
+{
+ if (bAutoStyle)
+ {
+ // For the headers/footers, we have to collect the autostyles
+ // here. For the general case, however, it's better to collect
+ // the autostyles by iterating over the global redline
+ // list. So that's what we do: Here, we collect autostyles
+ // only if we have no current list of changes. For the
+ // main-document case, the autostyles are collected in
+ // ExportChangesListAutoStyles().
+ if (pCurrentChangesList != nullptr)
+ ExportChangeAutoStyle(rPropSet);
+ }
+ else
+ {
+ ExportChangeInline(rPropSet);
+ }
+}
+
+
+void XMLRedlineExport::ExportChangesList(bool bAutoStyles)
+{
+ if (bAutoStyles)
+ {
+ ExportChangesListAutoStyles();
+ }
+ else
+ {
+ ExportChangesListElements();
+ }
+}
+
+
+void XMLRedlineExport::ExportChangesList(
+ const Reference<XText> & rText,
+ bool bAutoStyles)
+{
+ // in the header/footer case, auto styles are collected from the
+ // inline change elements.
+ if (bAutoStyles)
+ return;
+
+ // look for changes list for this XText
+ ChangesMapType::iterator aFind = aChangeMap.find(rText);
+ if (aFind == aChangeMap.end())
+ return;
+
+ ChangesVectorType& rChangesList = aFind->second;
+
+ // export only if changes are found
+ if (rChangesList.empty())
+ return;
+
+ // changes container element
+ SvXMLElementExport aChanges(rExport, XML_NAMESPACE_TEXT,
+ XML_TRACKED_CHANGES,
+ true, true);
+
+ // iterate over changes list
+ for (auto const& change : rChangesList)
+ {
+ ExportChangedRegion(change);
+ }
+ // else: changes list empty -> ignore
+ // else: no changes list found -> empty
+}
+
+void XMLRedlineExport::SetCurrentXText(
+ const Reference<XText> & rText)
+{
+ if (rText.is())
+ {
+ // look for appropriate list in map; use the found one, or create new
+ ChangesMapType::iterator aIter = aChangeMap.find(rText);
+ if (aIter == aChangeMap.end())
+ {
+ auto rv = aChangeMap.emplace(std::piecewise_construct, std::forward_as_tuple(rText), std::forward_as_tuple());
+ pCurrentChangesList = &rv.first->second;
+ }
+ else
+ pCurrentChangesList = &aIter->second;
+ }
+ else
+ {
+ // don't record changes
+ SetCurrentXText();
+ }
+}
+
+void XMLRedlineExport::SetCurrentXText()
+{
+ pCurrentChangesList = nullptr;
+}
+
+
+void XMLRedlineExport::ExportChangesListElements()
+{
+ // get redlines (aka tracked changes) from the model
+ Reference<XRedlinesSupplier> xSupplier(rExport.GetModel(), uno::UNO_QUERY);
+ if (!xSupplier.is())
+ return;
+
+ Reference<XEnumerationAccess> aEnumAccess = xSupplier->getRedlines();
+
+ // redline protection key
+ Reference<XPropertySet> aDocPropertySet( rExport.GetModel(),
+ uno::UNO_QUERY );
+ // redlining enabled?
+ bool bEnabled = *o3tl::doAccess<bool>(aDocPropertySet->getPropertyValue(
+ "RecordChanges" ));
+
+ // only export if we have redlines or attributes
+ if ( !(aEnumAccess->hasElements() || bEnabled) )
+ return;
+
+
+ // export only if we have changes, but tracking is not enabled
+ if ( !bEnabled != !aEnumAccess->hasElements() )
+ {
+ rExport.AddAttribute(
+ XML_NAMESPACE_TEXT, XML_TRACK_CHANGES,
+ bEnabled ? XML_TRUE : XML_FALSE );
+ }
+
+ // changes container element
+ SvXMLElementExport aChanges(rExport, XML_NAMESPACE_TEXT,
+ XML_TRACKED_CHANGES,
+ true, true);
+
+ // get enumeration and iterate over elements
+ Reference<XEnumeration> aEnum = aEnumAccess->createEnumeration();
+ while (aEnum->hasMoreElements())
+ {
+ Any aAny = aEnum->nextElement();
+ Reference<XPropertySet> xPropSet;
+ aAny >>= xPropSet;
+
+ DBG_ASSERT(xPropSet.is(),
+ "can't get XPropertySet; skipping Redline");
+ if (xPropSet.is())
+ {
+ // export only if not in header or footer
+ // (those must be exported with their XText)
+ aAny = xPropSet->getPropertyValue("IsInHeaderFooter");
+ if (! *o3tl::doAccess<bool>(aAny))
+ {
+ // and finally, export change
+ ExportChangedRegion(xPropSet);
+ }
+ }
+ // else: no XPropertySet -> no export
+ }
+ // else: no redlines -> no export
+ // else: no XRedlineSupplier -> no export
+}
+
+void XMLRedlineExport::ExportChangeAutoStyle(
+ const Reference<XPropertySet> & rPropSet)
+{
+ // record change (if changes should be recorded)
+ if (nullptr != pCurrentChangesList)
+ {
+ // put redline in list if it's collapsed or the redline start
+ Any aIsStart = rPropSet->getPropertyValue("IsStart");
+ Any aIsCollapsed = rPropSet->getPropertyValue("IsCollapsed");
+
+ if ( *o3tl::doAccess<bool>(aIsStart) ||
+ *o3tl::doAccess<bool>(aIsCollapsed) )
+ pCurrentChangesList->push_back(rPropSet);
+ }
+
+ // get XText for export of redline auto styles
+ Any aAny = rPropSet->getPropertyValue("RedlineText");
+ Reference<XText> xText;
+ aAny >>= xText;
+ if (xText.is())
+ {
+ // export the auto styles
+ rExport.GetTextParagraphExport()->collectTextAutoStyles(xText);
+ }
+}
+
+void XMLRedlineExport::ExportChangesListAutoStyles()
+{
+ // get redlines (aka tracked changes) from the model
+ Reference<XRedlinesSupplier> xSupplier(rExport.GetModel(), uno::UNO_QUERY);
+ if (!xSupplier.is())
+ return;
+
+ Reference<XEnumerationAccess> aEnumAccess = xSupplier->getRedlines();
+
+ // only export if we actually have redlines
+ if (!aEnumAccess->hasElements())
+ return;
+
+ // get enumeration and iterate over elements
+ Reference<XEnumeration> aEnum = aEnumAccess->createEnumeration();
+ while (aEnum->hasMoreElements())
+ {
+ Any aAny = aEnum->nextElement();
+ Reference<XPropertySet> xPropSet;
+ aAny >>= xPropSet;
+
+ DBG_ASSERT(xPropSet.is(),
+ "can't get XPropertySet; skipping Redline");
+ if (xPropSet.is())
+ {
+
+ // export only if not in header or footer
+ // (those must be exported with their XText)
+ aAny = xPropSet->getPropertyValue("IsInHeaderFooter");
+ if (! *o3tl::doAccess<bool>(aAny))
+ {
+ ExportChangeAutoStyle(xPropSet);
+ }
+ }
+ }
+}
+
+void XMLRedlineExport::ExportChangeInline(
+ const Reference<XPropertySet> & rPropSet)
+{
+ // determine element name (depending on collapsed, start/end)
+ enum XMLTokenEnum eElement = XML_TOKEN_INVALID;
+ Any aAny = rPropSet->getPropertyValue("IsCollapsed");
+ bool bCollapsed = *o3tl::doAccess<bool>(aAny);
+ if (bCollapsed)
+ {
+ eElement = XML_CHANGE;
+ }
+ else
+ {
+ aAny = rPropSet->getPropertyValue("IsStart");
+ const bool bStart = *o3tl::doAccess<bool>(aAny);
+ eElement = bStart ? XML_CHANGE_START : XML_CHANGE_END;
+ }
+
+ if (XML_TOKEN_INVALID != eElement)
+ {
+ // we always need the ID
+ rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_CHANGE_ID,
+ GetRedlineID(rPropSet));
+
+ // export the element (no whitespace because we're in the text body)
+ SvXMLElementExport aChangeElem(rExport, XML_NAMESPACE_TEXT,
+ eElement, false, false);
+ }
+}
+
+
+void XMLRedlineExport::ExportChangedRegion(
+ const Reference<XPropertySet> & rPropSet)
+{
+ // Redline-ID
+ rExport.AddAttributeIdLegacy(XML_NAMESPACE_TEXT, GetRedlineID(rPropSet));
+
+ // merge-last-paragraph
+ Any aAny = rPropSet->getPropertyValue("MergeLastPara");
+ if( ! *o3tl::doAccess<bool>(aAny) )
+ rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_MERGE_LAST_PARAGRAPH,
+ XML_FALSE);
+
+ // export change region element
+ SvXMLElementExport aChangedRegion(rExport, XML_NAMESPACE_TEXT,
+ XML_CHANGED_REGION, true, true);
+
+
+ // scope for (first) change element
+ {
+ aAny = rPropSet->getPropertyValue("RedlineType");
+ OUString sType;
+ aAny >>= sType;
+ SvXMLElementExport aChange(rExport, XML_NAMESPACE_TEXT,
+ ConvertTypeName(sType), true, true);
+
+ ExportChangeInfo(rPropSet);
+
+ // get XText from the redline and export (if the XText exists)
+ aAny = rPropSet->getPropertyValue("RedlineText");
+ Reference<XText> xText;
+ aAny >>= xText;
+ if (xText.is())
+ {
+ rExport.GetTextParagraphExport()->exportText(xText);
+ // default parameters: bProgress, bExportParagraph ???
+ }
+ // else: no text interface -> content is inline and will
+ // be exported there
+ }
+
+ // changed change? Hierarchical changes can only be two levels
+ // deep. Here we check for the second level.
+ aAny = rPropSet->getPropertyValue("RedlineSuccessorData");
+ Sequence<PropertyValue> aSuccessorData;
+ aAny >>= aSuccessorData;
+
+ // if we actually got a hierarchical change, make element and
+ // process change info
+ if (aSuccessorData.hasElements())
+ {
+ // The only change that can be "undone" is an insertion -
+ // after all, you can't re-insert a deletion, but you can
+ // delete an insertion. This assumption is asserted in
+ // ExportChangeInfo(Sequence<PropertyValue>&).
+ SvXMLElementExport aSecondChangeElem(
+ rExport, XML_NAMESPACE_TEXT, XML_INSERTION,
+ true, true);
+
+ ExportChangeInfo(aSuccessorData);
+ }
+ // else: no hierarchical change
+}
+
+
+OUString const & XMLRedlineExport::ConvertTypeName(
+ std::u16string_view sApiName)
+{
+ if (sApiName == u"Delete")
+ {
+ return sDeletion;
+ }
+ else if (sApiName == u"Insert")
+ {
+ return sInsertion;
+ }
+ else if (sApiName == u"Format")
+ {
+ return sFormatChange;
+ }
+ else
+ {
+ OSL_FAIL("unknown redline type");
+ static constexpr OUString sUnknownChange(u"UnknownChange"_ustr);
+ return sUnknownChange;
+ }
+}
+
+
+/** Create a Redline-ID */
+OUString XMLRedlineExport::GetRedlineID(
+ const Reference<XPropertySet> & rPropSet)
+{
+ Any aAny = rPropSet->getPropertyValue("RedlineIdentifier");
+ OUString sTmp;
+ aAny >>= sTmp;
+
+ return "ct" + sTmp;
+}
+
+
+void XMLRedlineExport::ExportChangeInfo(
+ const Reference<XPropertySet> & rPropSet)
+{
+ bool bRemovePersonalInfo = SvtSecurityOptions::IsOptionSet(
+ SvtSecurityOptions::EOption::DocWarnRemovePersonalInfo ) && !SvtSecurityOptions::IsOptionSet(
+ SvtSecurityOptions::EOption::DocWarnKeepRedlineInfo);
+
+ SvXMLElementExport aChangeInfo(rExport, XML_NAMESPACE_OFFICE,
+ XML_CHANGE_INFO, true, true);
+
+ Any aAny = rPropSet->getPropertyValue("RedlineAuthor");
+ OUString sTmp;
+ aAny >>= sTmp;
+ if (!sTmp.isEmpty())
+ {
+ SvXMLElementExport aCreatorElem( rExport, XML_NAMESPACE_DC,
+ XML_CREATOR, true,
+ false );
+ rExport.Characters(bRemovePersonalInfo
+ ? "Author" + OUString::number(rExport.GetInfoID(sTmp))
+ : sTmp );
+ }
+
+ aAny = rPropSet->getPropertyValue("RedlineMovedID");
+ sal_uInt32 nTmp(0);
+ aAny >>= nTmp;
+ if (nTmp > 1)
+ {
+ SvXMLElementExport aCreatorElem(rExport, XML_NAMESPACE_LO_EXT, XML_MOVE_ID, true, false);
+ rExport.Characters( OUString::number( nTmp ) );
+ }
+
+ aAny = rPropSet->getPropertyValue("RedlineDateTime");
+ util::DateTime aDateTime;
+ aAny >>= aDateTime;
+ {
+ OUStringBuffer sBuf;
+ ::sax::Converter::convertDateTime(sBuf, bRemovePersonalInfo
+ ? util::DateTime(0, 0, 0, 0, 1, 1, 1970, true) // Epoch time
+ : aDateTime, nullptr);
+ SvXMLElementExport aDateElem( rExport, XML_NAMESPACE_DC,
+ XML_DATE, true,
+ false );
+ rExport.Characters(sBuf.makeStringAndClear());
+ }
+
+ // comment as <text:p> sequence
+ aAny = rPropSet->getPropertyValue("RedlineComment");
+ aAny >>= sTmp;
+ WriteComment( sTmp );
+}
+
+// write RedlineSuccessorData
+void XMLRedlineExport::ExportChangeInfo(
+ const Sequence<PropertyValue> & rPropertyValues)
+{
+ OUString sComment;
+ bool bRemovePersonalInfo = SvtSecurityOptions::IsOptionSet(
+ SvtSecurityOptions::EOption::DocWarnRemovePersonalInfo ) && !SvtSecurityOptions::IsOptionSet(
+ SvtSecurityOptions::EOption::DocWarnKeepRedlineInfo);
+
+ SvXMLElementExport aChangeInfo(rExport, XML_NAMESPACE_OFFICE,
+ XML_CHANGE_INFO, true, true);
+
+ for(const PropertyValue& rVal : rPropertyValues)
+ {
+ if( rVal.Name == "RedlineAuthor" )
+ {
+ OUString sTmp;
+ rVal.Value >>= sTmp;
+ if (!sTmp.isEmpty())
+ {
+ SvXMLElementExport aCreatorElem( rExport, XML_NAMESPACE_DC,
+ XML_CREATOR, true,
+ false );
+ rExport.Characters(bRemovePersonalInfo
+ ? "Author" + OUString::number(rExport.GetInfoID(sTmp))
+ : sTmp );
+ }
+ }
+ else if( rVal.Name == "RedlineComment" )
+ {
+ rVal.Value >>= sComment;
+ }
+ else if( rVal.Name == "RedlineDateTime" )
+ {
+ util::DateTime aDateTime;
+ rVal.Value >>= aDateTime;
+ OUStringBuffer sBuf;
+ ::sax::Converter::convertDateTime(sBuf, bRemovePersonalInfo
+ ? util::DateTime(0, 0, 0, 0, 1, 1, 1970, true) // Epoch time
+ : aDateTime, nullptr);
+ SvXMLElementExport aDateElem( rExport, XML_NAMESPACE_DC,
+ XML_DATE, true,
+ false );
+ rExport.Characters(sBuf.makeStringAndClear());
+ }
+ else if( rVal.Name == "RedlineType" )
+ {
+ // check if this is an insertion; cf. comment at calling location
+ OUString sTmp;
+ rVal.Value >>= sTmp;
+ DBG_ASSERT(sTmp == "Insert",
+ "hierarchical change must be insertion");
+ }
+ // else: unknown value -> ignore
+ }
+
+ // finally write comment paragraphs
+ WriteComment( sComment );
+}
+
+void XMLRedlineExport::ExportStartOrEndRedline(
+ const Reference<XPropertySet> & rPropSet,
+ bool bStart)
+{
+ if( ! rPropSet.is() )
+ return;
+
+ // get appropriate (start or end) property
+ Any aAny;
+ try
+ {
+ aAny = rPropSet->getPropertyValue(bStart ? OUString("StartRedline") : OUString("EndRedline"));
+ }
+ catch(const UnknownPropertyException&)
+ {
+ // If we don't have the property, there's nothing to do.
+ return;
+ }
+
+ Sequence<PropertyValue> aValues;
+ aAny >>= aValues;
+
+ // seek for redline properties
+ bool bIsCollapsed = false;
+ bool bIsStart = true;
+ OUString sId;
+ bool bIdOK = false; // have we seen an ID?
+ for(const auto& rValue : std::as_const(aValues))
+ {
+ if (rValue.Name == "RedlineIdentifier")
+ {
+ rValue.Value >>= sId;
+ bIdOK = true;
+ }
+ else if (rValue.Name == "IsCollapsed")
+ {
+ bIsCollapsed = *o3tl::doAccess<bool>(rValue.Value);
+ }
+ else if (rValue.Name == "IsStart")
+ {
+ bIsStart = *o3tl::doAccess<bool>(rValue.Value);
+ }
+ }
+
+ if( !bIdOK )
+ return;
+
+ SAL_WARN_IF( sId.isEmpty(), "xmloff", "Redlines must have IDs" );
+
+ // TODO: use GetRedlineID or eliminate that function
+ rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_CHANGE_ID,
+ "ct" + sId);
+
+ // export the element
+ // (whitespace because we're not inside paragraphs)
+ SvXMLElementExport aChangeElem(
+ rExport, XML_NAMESPACE_TEXT,
+ bIsCollapsed ? XML_CHANGE :
+ ( bIsStart ? XML_CHANGE_START : XML_CHANGE_END ),
+ true, true);
+}
+
+void XMLRedlineExport::ExportStartOrEndRedline(
+ const Reference<XTextContent> & rContent,
+ bool bStart)
+{
+ Reference<XPropertySet> xPropSet(rContent, uno::UNO_QUERY);
+ if (xPropSet.is())
+ {
+ ExportStartOrEndRedline(xPropSet, bStart);
+ }
+ else
+ {
+ OSL_FAIL("XPropertySet expected");
+ }
+}
+
+void XMLRedlineExport::ExportStartOrEndRedline(
+ const Reference<XTextSection> & rSection,
+ bool bStart)
+{
+ Reference<XPropertySet> xPropSet(rSection, uno::UNO_QUERY);
+ if (xPropSet.is())
+ {
+ ExportStartOrEndRedline(xPropSet, bStart);
+ }
+ else
+ {
+ OSL_FAIL("XPropertySet expected");
+ }
+}
+
+void XMLRedlineExport::WriteComment(std::u16string_view rComment)
+{
+ if (rComment.empty())
+ return;
+
+ // iterate over all string-pieces separated by return (0x0a) and
+ // put each inside a paragraph element.
+ SvXMLTokenEnumerator aEnumerator(rComment, char(0x0a));
+ std::u16string_view aSubString;
+ while (aEnumerator.getNextToken(aSubString))
+ {
+ SvXMLElementExport aParagraph(
+ rExport, XML_NAMESPACE_TEXT, XML_P, true, false);
+ rExport.Characters(OUString(aSubString));
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLRedlineExport.hxx b/xmloff/source/text/XMLRedlineExport.hxx
new file mode 100644
index 0000000000..9031aacdbd
--- /dev/null
+++ b/xmloff/source/text/XMLRedlineExport.hxx
@@ -0,0 +1,163 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/Sequence.h>
+
+#include <vector>
+#include <memory>
+#include <map>
+
+class SvXMLExport;
+namespace com::sun::star {
+ namespace beans { class XPropertySet; }
+ namespace beans { struct PropertyValue; }
+ namespace text { class XText; }
+ namespace text { class XTextContent; }
+ namespace text { class XTextSection; }
+}
+
+// store a list of redline properties
+typedef ::std::vector<
+ css::uno::Reference<css::beans::XPropertySet> > ChangesVectorType;
+
+// store a list of redline properties for each XText
+typedef ::std::map<
+ css::uno::Reference< css::text::XText>,
+ ChangesVectorType > ChangesMapType;
+
+
+/**
+ * This class handles the export of redline portions.
+ * It is to be called from XMLTextParagraphExport.
+ */
+class XMLRedlineExport
+{
+ const OUString sDeletion;
+ const OUString sFormatChange;
+ const OUString sInsertion;
+
+ SvXMLExport& rExport;
+
+
+ // handling of change recording:
+
+ // To support change tracking in headers and footers we need to
+ // write these changes separately. To do this, we record the
+ // changes for headers and footers. For the main document body, we
+ // get the complete list of changes from the document, which
+ // should be much more efficient than recording all of those.
+
+ ChangesMapType aChangeMap; /// map of recorded changes
+
+ /// list of current changes; is NULL or points to member of aChangeMap
+ ChangesVectorType* pCurrentChangesList;
+
+
+public:
+ explicit XMLRedlineExport(SvXMLExport& rExp);
+
+ ~XMLRedlineExport();
+
+ /// export a change
+ void ExportChange(
+ /// PropertySet of RedlinePortion
+ const css::uno::Reference<css::beans::XPropertySet> & rPropSet,
+ bool bAutoStyle);
+
+ /// export the list of changes (complete list minus recorded changed)
+ void ExportChangesList(bool bAutoStyles);
+
+ /// export the list of changes (recorded changes for this XText only)
+ void ExportChangesList(
+ const css::uno::Reference<css::text::XText> & rText,
+ bool bAutoStyles);
+
+ /// set the current XText for which changes should be recorded.
+ /// An empty XText means: don't record changes
+ void SetCurrentXText(
+ const css::uno::Reference<css::text::XText> & rText);
+
+ /// Do not record changes.
+ /// Same as SetCurrentXText(Reference<XText>) with empty argument.
+ void SetCurrentXText();
+
+ /// export redline marks which start or end at start nodes,
+ /// i.e. that include the complete paragraph/table/section
+ void ExportStartOrEndRedline(
+ const css::uno::Reference<
+ css::beans::XPropertySet> & rPropSet,
+ bool bStart); /// start or end of text entity (e.g. paragraph)?
+
+ /// convenience method, calls XPropertySet-version of this method
+ void ExportStartOrEndRedline(
+ /// XTextContent; must also be an XPropertySet
+ const css::uno::Reference<css::text::XTextContent> & rContent,
+ bool bStart);
+
+ /// convenience method, calls XPropertySet-version of this method
+ void ExportStartOrEndRedline(
+ /// XTextSection; must also be an XPropertySet
+ const css::uno::Reference<css::text::XTextSection> & rSection,
+ bool bStart);
+
+private:
+
+ /// export the change mark contained in the text body
+ void ExportChangeInline(
+ /// PropertySet of RedlinePortion
+ const css::uno::Reference<css::beans::XPropertySet> & rPropSet);
+
+ /// export the auto styles used in this change
+ void ExportChangeAutoStyle(
+ /// PropertySet of RedlinePortion
+ const css::uno::Reference<css::beans::XPropertySet> & rPropSet);
+
+ /// export the changes list (<text:tracked-changes>)
+ void ExportChangesListElements();
+
+ /// export the auto styles needed by the changes list
+ void ExportChangesListAutoStyles();
+
+ /// export the changed-region element
+ void ExportChangedRegion(
+ const css::uno::Reference<css::beans::XPropertySet> & rPropSet);
+
+ /// export a change-info element (from a PropertySet)
+ void ExportChangeInfo(
+ const css::uno::Reference<css::beans::XPropertySet> & rPropSet);
+
+ /// export a change-info element (from PropertyValues)
+ void ExportChangeInfo(
+ const css::uno::Sequence<css::beans::PropertyValue> & rValues);
+
+ /// convert the change type from API to XML names
+ OUString const & ConvertTypeName(std::u16string_view sApiName);
+
+ /// Get ID string!
+ static OUString GetRedlineID(
+ const css::uno::Reference<css::beans::XPropertySet> & rPropSet);
+
+ /// write a comment string as sequence of <text:p> elements
+ void WriteComment(std::u16string_view rComment);
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLSectionExport.cxx b/xmloff/source/text/XMLSectionExport.cxx
new file mode 100644
index 0000000000..fc3adc0c88
--- /dev/null
+++ b/xmloff/source/text/XMLSectionExport.cxx
@@ -0,0 +1,1836 @@
+/* -*- 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 "XMLSectionExport.hxx"
+#include <o3tl/any.hxx>
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <osl/diagnose.h>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/lang/Locale.hpp>
+#include <com/sun/star/container/XIndexReplace.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/PropertyValues.hpp>
+#include <com/sun/star/text/XTextSection.hpp>
+#include <com/sun/star/text/SectionFileLink.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/text/XDocumentIndex.hpp>
+#include <com/sun/star/text/BibliographyDataField.hpp>
+#include <com/sun/star/text/XTextFieldsSupplier.hpp>
+#include <com/sun/star/text/XChapterNumberingSupplier.hpp>
+#include <com/sun/star/text/ChapterFormat.hpp>
+
+#include <comphelper/base64.hxx>
+
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/families.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/xmlement.hxx>
+#include <txtflde.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::uno;
+using namespace ::xmloff::token;
+
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::beans::PropertyValue;
+using ::com::sun::star::beans::PropertyValues;
+using ::com::sun::star::container::XIndexReplace;
+using ::com::sun::star::container::XNameAccess;
+using ::com::sun::star::container::XNamed;
+using ::com::sun::star::lang::Locale;
+
+
+XMLSectionExport::XMLSectionExport(
+ SvXMLExport& rExp,
+ XMLTextParagraphExport& rParaExp)
+: rExport(rExp)
+, rParaExport(rParaExp)
+, bHeadingDummiesExported( false )
+{
+}
+
+
+void XMLSectionExport::ExportSectionStart(
+ const Reference<XTextSection> & rSection,
+ bool bAutoStyles)
+{
+ Reference<XPropertySet> xPropertySet(rSection, UNO_QUERY);
+
+ // always export section (auto) style
+ if (bAutoStyles)
+ {
+ // get PropertySet and add section style
+ GetParaExport().Add( XmlStyleFamily::TEXT_SECTION, xPropertySet );
+ }
+ else
+ {
+ // always export section style
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_STYLE_NAME,
+ GetParaExport().Find(
+ XmlStyleFamily::TEXT_SECTION,
+ xPropertySet, "" ) );
+
+ // xml:id for RDF metadata
+ GetExport().AddAttributeXmlId(rSection);
+
+ // export index or regular section
+ Reference<XDocumentIndex> xIndex;
+ if (GetIndex(rSection, xIndex))
+ {
+ if (xIndex.is())
+ {
+ // we are an index
+ ExportIndexStart(xIndex);
+ }
+ else
+ {
+ // we are an index header
+ ExportIndexHeaderStart(rSection);
+ }
+ }
+ else
+ {
+ // we are not an index
+ ExportRegularSectionStart(rSection);
+ }
+ }
+}
+
+bool XMLSectionExport::GetIndex(
+ const Reference<XTextSection> & rSection,
+ Reference<XDocumentIndex> & rIndex)
+{
+ // first, reset result
+ bool bRet = false;
+ rIndex = nullptr;
+
+ // get section Properties
+ Reference<XPropertySet> xSectionPropSet(rSection, UNO_QUERY);
+
+ // then check if this section happens to be inside an index
+ if (xSectionPropSet->getPropertySetInfo()->
+ hasPropertyByName("DocumentIndex"))
+ {
+ Any aAny = xSectionPropSet->getPropertyValue("DocumentIndex");
+ Reference<XDocumentIndex> xDocumentIndex;
+ aAny >>= xDocumentIndex;
+
+ // OK, are we inside of an index
+ if (xDocumentIndex.is())
+ {
+ // is the enclosing index identical with "our" section?
+ Reference<XPropertySet> xIndexPropSet(xDocumentIndex, UNO_QUERY);
+ aAny = xIndexPropSet->getPropertyValue("ContentSection");
+ Reference<XTextSection> xEnclosingSection;
+ aAny >>= xEnclosingSection;
+
+ // if the enclosing section is "our" section, then we are an index!
+ if (rSection == xEnclosingSection)
+ {
+ rIndex = xDocumentIndex;
+ bRet = true;
+ }
+ // else: index header or regular section
+
+ // is the enclosing index identical with the header section?
+ aAny = xIndexPropSet->getPropertyValue("HeaderSection");
+ // now mis-named: contains header section
+ aAny >>= xEnclosingSection;
+
+ // if the enclosing section is "our" section, then we are an index!
+ if (rSection == xEnclosingSection)
+ {
+ bRet = true;
+ }
+ // else: regular section
+ }
+ // else: we aren't even inside of an index
+ }
+ // else: we don't even know what an index is.
+
+ return bRet;
+}
+
+
+void XMLSectionExport::ExportSectionEnd(
+ const Reference<XTextSection> & rSection,
+ bool bAutoStyles)
+{
+ // no end section for styles
+ if (bAutoStyles)
+ return;
+
+ enum XMLTokenEnum eElement = XML_TOKEN_INVALID;
+
+ // export index or regular section end
+ Reference<XDocumentIndex> xIndex;
+ if (GetIndex(rSection, xIndex))
+ {
+ if (xIndex.is())
+ {
+ // index end: close index body element
+ GetExport().EndElement( XML_NAMESPACE_TEXT, XML_INDEX_BODY,
+ true );
+ GetExport().IgnorableWhitespace();
+
+ switch (MapSectionType(xIndex->getServiceName()))
+ {
+ case TEXT_SECTION_TYPE_TOC:
+ eElement = XML_TABLE_OF_CONTENT;
+ break;
+
+ case TEXT_SECTION_TYPE_ILLUSTRATION:
+ eElement = XML_ILLUSTRATION_INDEX;
+ break;
+
+ case TEXT_SECTION_TYPE_ALPHABETICAL:
+ eElement = XML_ALPHABETICAL_INDEX;
+ break;
+
+ case TEXT_SECTION_TYPE_TABLE:
+ eElement = XML_TABLE_INDEX;
+ break;
+
+ case TEXT_SECTION_TYPE_OBJECT:
+ eElement = XML_OBJECT_INDEX;
+ break;
+
+ case TEXT_SECTION_TYPE_USER:
+ eElement = XML_USER_INDEX;
+ break;
+
+ case TEXT_SECTION_TYPE_BIBLIOGRAPHY:
+ eElement = XML_BIBLIOGRAPHY;
+ break;
+
+ default:
+ OSL_FAIL("unknown index type");
+ // default: skip index!
+ break;
+ }
+ }
+ else
+ {
+ eElement = XML_INDEX_TITLE;
+ }
+ }
+ else
+ {
+ eElement = XML_SECTION;
+ }
+
+ if (XML_TOKEN_INVALID != eElement)
+ {
+ // any old attributes?
+ GetExport().CheckAttrList();
+
+ // element surrounded by whitespace
+ GetExport().EndElement( XML_NAMESPACE_TEXT, eElement, true);
+ GetExport().IgnorableWhitespace();
+ }
+ else
+ {
+ OSL_FAIL("Need element name!");
+ }
+ // else: autostyles -> ignore
+}
+
+void XMLSectionExport::ExportIndexStart(
+ const Reference<XDocumentIndex> & rIndex)
+{
+ // get PropertySet
+ Reference<XPropertySet> xPropertySet(rIndex, UNO_QUERY);
+
+ switch (MapSectionType(rIndex->getServiceName()))
+ {
+ case TEXT_SECTION_TYPE_TOC:
+ ExportTableOfContentStart(xPropertySet);
+ break;
+
+ case TEXT_SECTION_TYPE_ILLUSTRATION:
+ ExportIllustrationIndexStart(xPropertySet);
+ break;
+
+ case TEXT_SECTION_TYPE_ALPHABETICAL:
+ ExportAlphabeticalIndexStart(xPropertySet);
+ break;
+
+ case TEXT_SECTION_TYPE_TABLE:
+ ExportTableIndexStart(xPropertySet);
+ break;
+
+ case TEXT_SECTION_TYPE_OBJECT:
+ ExportObjectIndexStart(xPropertySet);
+ break;
+
+ case TEXT_SECTION_TYPE_USER:
+ ExportUserIndexStart(xPropertySet);
+ break;
+
+ case TEXT_SECTION_TYPE_BIBLIOGRAPHY:
+ ExportBibliographyStart(xPropertySet);
+ break;
+
+ default:
+ // skip index
+ OSL_FAIL("unknown index type");
+ break;
+ }
+}
+
+void XMLSectionExport::ExportIndexHeaderStart(
+ const Reference<XTextSection> & rSection)
+{
+ // export name, dammit!
+ Reference<XNamed> xName(rSection, UNO_QUERY);
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xName->getName());
+
+ // format already handled -> export only start element
+ GetExport().StartElement( XML_NAMESPACE_TEXT, XML_INDEX_TITLE, true );
+ GetExport().IgnorableWhitespace();
+}
+
+
+SvXMLEnumStringMapEntry<SectionTypeEnum> const aIndexTypeMap[] =
+{
+ ENUM_STRING_MAP_ENTRY( "com.sun.star.text.ContentIndex", TEXT_SECTION_TYPE_TOC ),
+ ENUM_STRING_MAP_ENTRY( "com.sun.star.text.DocumentIndex", TEXT_SECTION_TYPE_ALPHABETICAL ),
+ ENUM_STRING_MAP_ENTRY( "com.sun.star.text.TableIndex", TEXT_SECTION_TYPE_TABLE ),
+ ENUM_STRING_MAP_ENTRY( "com.sun.star.text.ObjectIndex", TEXT_SECTION_TYPE_OBJECT ),
+ ENUM_STRING_MAP_ENTRY( "com.sun.star.text.Bibliography", TEXT_SECTION_TYPE_BIBLIOGRAPHY ),
+ ENUM_STRING_MAP_ENTRY( "com.sun.star.text.UserIndex", TEXT_SECTION_TYPE_USER ),
+ ENUM_STRING_MAP_ENTRY( "com.sun.star.text.IllustrationsIndex", TEXT_SECTION_TYPE_ILLUSTRATION ),
+ { nullptr, 0, SectionTypeEnum(0) }
+};
+
+enum SectionTypeEnum XMLSectionExport::MapSectionType(
+ std::u16string_view rServiceName)
+{
+ enum SectionTypeEnum eType = TEXT_SECTION_TYPE_UNKNOWN;
+
+ SvXMLUnitConverter::convertEnum(eType, rServiceName, aIndexTypeMap);
+
+ // TODO: index header section types, etc.
+
+ return eType;
+}
+
+void XMLSectionExport::ExportRegularSectionStart(
+ const Reference<XTextSection> & rSection)
+{
+ // style name already handled in ExportSectionStart(...)
+
+ Reference<XNamed> xName(rSection, UNO_QUERY);
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xName->getName());
+
+ // get XPropertySet for other values
+ Reference<XPropertySet> xPropSet(rSection, UNO_QUERY);
+
+ // condition and display
+ Any aAny = xPropSet->getPropertyValue("Condition");
+ OUString sCond;
+ aAny >>= sCond;
+ enum XMLTokenEnum eDisplay = XML_TOKEN_INVALID;
+ if (!sCond.isEmpty())
+ {
+ OUString sQValue =
+ GetExport().GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OOOW,
+ sCond, false );
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_CONDITION, sQValue);
+ eDisplay = XML_CONDITION;
+
+ // #97450# store hidden-status (of conditional sections only)
+ aAny = xPropSet->getPropertyValue("IsCurrentlyVisible");
+ if (! *o3tl::doAccess<bool>(aAny))
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_IS_HIDDEN,
+ XML_TRUE);
+ }
+ }
+ else
+ {
+ eDisplay = XML_NONE;
+ }
+ aAny = xPropSet->getPropertyValue("IsVisible");
+ if (! *o3tl::doAccess<bool>(aAny))
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_DISPLAY, eDisplay);
+ }
+
+ // protect + protection key
+ aAny = xPropSet->getPropertyValue("IsProtected");
+ if (*o3tl::doAccess<bool>(aAny))
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_PROTECTED, XML_TRUE);
+ }
+ Sequence<sal_Int8> aPassword;
+ xPropSet->getPropertyValue("ProtectionKey") >>= aPassword;
+ if (aPassword.hasElements())
+ {
+ OUStringBuffer aBuffer;
+ ::comphelper::Base64::encode(aBuffer, aPassword);
+ // in ODF 1.0/1.1 the algorithm was left unspecified so we can write anything
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_PROTECTION_KEY,
+ aBuffer.makeStringAndClear());
+ if (aPassword.getLength() == 32 && GetExport().getSaneDefaultVersion() >= SvtSaveOptions::ODFSVER_012)
+ {
+ // attribute exists in ODF 1.2 or later; default is SHA1 so no need to write that
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
+ // write the URL from ODF 1.2, not the W3C one
+ "http://www.w3.org/2000/09/xmldsig#sha256");
+ }
+ }
+
+ // export element
+ GetExport().IgnorableWhitespace();
+ GetExport().StartElement( XML_NAMESPACE_TEXT, XML_SECTION, true );
+
+ // data source
+ // unfortunately, we have to test all relevant strings for non-zero length
+ aAny = xPropSet->getPropertyValue("FileLink");
+ SectionFileLink aFileLink;
+ aAny >>= aFileLink;
+
+ aAny = xPropSet->getPropertyValue("LinkRegion");
+ OUString sRegionName;
+ aAny >>= sRegionName;
+
+ if ( !aFileLink.FileURL.isEmpty() ||
+ !aFileLink.FilterName.isEmpty() ||
+ !sRegionName.isEmpty())
+ {
+ if (!aFileLink.FileURL.isEmpty())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_HREF,
+ GetExport().GetRelativeReference( aFileLink.FileURL) );
+ }
+
+ if (!aFileLink.FilterName.isEmpty())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_FILTER_NAME,
+ aFileLink.FilterName);
+ }
+
+ if (!sRegionName.isEmpty())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_SECTION_NAME,
+ sRegionName);
+ }
+
+ SvXMLElementExport aElem(GetExport(),
+ XML_NAMESPACE_TEXT, XML_SECTION_SOURCE,
+ true, true);
+ }
+ else
+ {
+ // check for DDE first
+ if (xPropSet->getPropertySetInfo()->hasPropertyByName("DDECommandFile"))
+ {
+ // data source DDE
+ // unfortunately, we have to test all relevant strings for
+ // non-zero length
+ aAny = xPropSet->getPropertyValue("DDECommandFile");
+ OUString sApplication;
+ aAny >>= sApplication;
+ aAny = xPropSet->getPropertyValue("DDECommandType");
+ OUString sTopic;
+ aAny >>= sTopic;
+ aAny = xPropSet->getPropertyValue("DDECommandElement");
+ OUString sItem;
+ aAny >>= sItem;
+
+ if ( !sApplication.isEmpty() ||
+ !sTopic.isEmpty() ||
+ !sItem.isEmpty())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_OFFICE,
+ XML_DDE_APPLICATION, sApplication);
+ GetExport().AddAttribute(XML_NAMESPACE_OFFICE, XML_DDE_TOPIC,
+ sTopic);
+ GetExport().AddAttribute(XML_NAMESPACE_OFFICE, XML_DDE_ITEM,
+ sItem);
+
+ aAny = xPropSet->getPropertyValue("IsAutomaticUpdate");
+ if (*o3tl::doAccess<bool>(aAny))
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_OFFICE,
+ XML_AUTOMATIC_UPDATE, XML_TRUE);
+ }
+
+ SvXMLElementExport aElem(GetExport(),
+ XML_NAMESPACE_OFFICE,
+ XML_DDE_SOURCE, true, true);
+ }
+ // else: no DDE data source
+ }
+ // else: no DDE on this system
+ }
+}
+
+void XMLSectionExport::ExportTableOfContentStart(
+ const Reference<XPropertySet> & rPropertySet)
+{
+ // export TOC element start
+ ExportBaseIndexStart(XML_TABLE_OF_CONTENT, rPropertySet);
+
+ // scope for table-of-content-source element
+ {
+ // TOC specific index source attributes:
+
+ // outline-level: 1..10
+ sal_Int16 nLevel = sal_Int16();
+ if( rPropertySet->getPropertyValue("Level") >>= nLevel )
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT,
+ XML_OUTLINE_LEVEL,
+ OUString::number(nLevel));
+ }
+
+ // use outline level
+ ExportBoolean(rPropertySet, "CreateFromOutline",
+ XML_USE_OUTLINE_LEVEL, true);
+
+ // use index marks
+ ExportBoolean(rPropertySet, "CreateFromMarks",
+ XML_USE_INDEX_MARKS, true);
+
+ // use level styles
+ ExportBoolean(rPropertySet, "CreateFromLevelParagraphStyles",
+ XML_USE_INDEX_SOURCE_STYLES, false);
+
+ ExportBaseIndexSource(TEXT_SECTION_TYPE_TOC, rPropertySet);
+ }
+
+ ExportBaseIndexBody(TEXT_SECTION_TYPE_TOC, rPropertySet);
+}
+
+void XMLSectionExport::ExportObjectIndexStart(
+ const Reference<XPropertySet> & rPropertySet)
+{
+ // export index start
+ ExportBaseIndexStart(XML_OBJECT_INDEX, rPropertySet);
+
+ // scope for index source element
+ {
+ ExportBoolean(rPropertySet, "CreateFromOtherEmbeddedObjects",
+ XML_USE_OTHER_OBJECTS, false);
+ ExportBoolean(rPropertySet, "CreateFromStarCalc",
+ XML_USE_SPREADSHEET_OBJECTS, false);
+ ExportBoolean(rPropertySet, "CreateFromStarChart",
+ XML_USE_CHART_OBJECTS, false);
+ ExportBoolean(rPropertySet, "CreateFromStarDraw",
+ XML_USE_DRAW_OBJECTS, false);
+ ExportBoolean(rPropertySet, "CreateFromStarMath",
+ XML_USE_MATH_OBJECTS, false);
+
+ ExportBaseIndexSource(TEXT_SECTION_TYPE_OBJECT, rPropertySet);
+ }
+
+ ExportBaseIndexBody(TEXT_SECTION_TYPE_OBJECT, rPropertySet);
+}
+
+void XMLSectionExport::ExportIllustrationIndexStart(
+ const Reference<XPropertySet> & rPropertySet)
+{
+ // export index start
+ ExportBaseIndexStart(XML_ILLUSTRATION_INDEX, rPropertySet);
+
+ // scope for index source element
+ {
+ // export common attributes for illustration and table indices
+ ExportTableAndIllustrationIndexSourceAttributes(rPropertySet);
+
+ ExportBaseIndexSource(TEXT_SECTION_TYPE_ILLUSTRATION, rPropertySet);
+ }
+
+ ExportBaseIndexBody(TEXT_SECTION_TYPE_ILLUSTRATION, rPropertySet);
+}
+
+void XMLSectionExport::ExportTableIndexStart(
+ const Reference<XPropertySet> & rPropertySet)
+{
+ // export index start
+ ExportBaseIndexStart(XML_TABLE_INDEX, rPropertySet);
+
+ // scope for index source element
+ {
+ // export common attributes for illustration and table indices
+ ExportTableAndIllustrationIndexSourceAttributes(rPropertySet);
+
+ ExportBaseIndexSource(TEXT_SECTION_TYPE_TABLE, rPropertySet);
+ }
+
+ ExportBaseIndexBody(TEXT_SECTION_TYPE_TABLE, rPropertySet);
+}
+
+void XMLSectionExport::ExportAlphabeticalIndexStart(
+ const Reference<XPropertySet> & rPropertySet)
+{
+ // export TOC element start
+ ExportBaseIndexStart(XML_ALPHABETICAL_INDEX, rPropertySet);
+
+ // scope for table-of-content-source element
+ {
+
+ // style name (if present)
+ Any aAny = rPropertySet->getPropertyValue("MainEntryCharacterStyleName");
+ OUString sStyleName;
+ aAny >>= sStyleName;
+ if (!sStyleName.isEmpty())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT,
+ XML_MAIN_ENTRY_STYLE_NAME,
+ GetExport().EncodeStyleName( sStyleName ));
+ }
+
+ // other (boolean) attributes
+ ExportBoolean(rPropertySet, "IsCaseSensitive", XML_IGNORE_CASE,
+ false, true);
+ ExportBoolean(rPropertySet, "UseAlphabeticalSeparators",
+ XML_ALPHABETICAL_SEPARATORS, false);
+ ExportBoolean(rPropertySet, "UseCombinedEntries", XML_COMBINE_ENTRIES,
+ true);
+ ExportBoolean(rPropertySet, "UseDash", XML_COMBINE_ENTRIES_WITH_DASH,
+ false);
+ ExportBoolean(rPropertySet, "UseKeyAsEntry", XML_USE_KEYS_AS_ENTRIES,
+ false);
+ ExportBoolean(rPropertySet, "UsePP", XML_COMBINE_ENTRIES_WITH_PP,
+ true);
+ ExportBoolean(rPropertySet, "UseUpperCase", XML_CAPITALIZE_ENTRIES,
+ false);
+ ExportBoolean(rPropertySet, "IsCommaSeparated", XML_COMMA_SEPARATED,
+ false);
+
+ // sort algorithm
+ aAny = rPropertySet->getPropertyValue("SortAlgorithm");
+ OUString sAlgorithm;
+ aAny >>= sAlgorithm;
+ if (!sAlgorithm.isEmpty())
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_SORT_ALGORITHM,
+ sAlgorithm );
+ }
+
+ // locale
+ aAny = rPropertySet->getPropertyValue("Locale");
+ Locale aLocale;
+ aAny >>= aLocale;
+ GetExport().AddLanguageTagAttributes( XML_NAMESPACE_FO, XML_NAMESPACE_STYLE, aLocale, true);
+
+ ExportBaseIndexSource(TEXT_SECTION_TYPE_ALPHABETICAL, rPropertySet);
+ }
+
+ ExportBaseIndexBody(TEXT_SECTION_TYPE_ALPHABETICAL, rPropertySet);
+}
+
+void XMLSectionExport::ExportUserIndexStart(
+ const Reference<XPropertySet> & rPropertySet)
+{
+ // export TOC element start
+ ExportBaseIndexStart(XML_USER_INDEX, rPropertySet);
+
+ // scope for table-of-content-source element
+ {
+ // bool attributes
+ ExportBoolean(rPropertySet, "CreateFromEmbeddedObjects",
+ XML_USE_OBJECTS, false);
+ ExportBoolean(rPropertySet, "CreateFromGraphicObjects",
+ XML_USE_GRAPHICS, false);
+ ExportBoolean(rPropertySet, "CreateFromMarks",
+ XML_USE_INDEX_MARKS, false);
+ ExportBoolean(rPropertySet, "CreateFromTables",
+ XML_USE_TABLES, false);
+ ExportBoolean(rPropertySet, "CreateFromTextFrames",
+ XML_USE_FLOATING_FRAMES, false);
+ ExportBoolean(rPropertySet, "UseLevelFromSource",
+ XML_COPY_OUTLINE_LEVELS, false);
+ ExportBoolean(rPropertySet, "CreateFromLevelParagraphStyles",
+ XML_USE_INDEX_SOURCE_STYLES, false);
+
+ Any aAny = rPropertySet->getPropertyValue( "UserIndexName" );
+ OUString sIndexName;
+ aAny >>= sIndexName;
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_INDEX_NAME,
+ sIndexName);
+
+ ExportBaseIndexSource(TEXT_SECTION_TYPE_USER, rPropertySet);
+ }
+
+ ExportBaseIndexBody(TEXT_SECTION_TYPE_USER, rPropertySet);
+}
+
+void XMLSectionExport::ExportBibliographyStart(
+ const Reference<XPropertySet> & rPropertySet)
+{
+ // export TOC element start
+ ExportBaseIndexStart(XML_BIBLIOGRAPHY, rPropertySet);
+
+ // scope for table-of-content-source element
+ {
+ // No attributes. Fine.
+
+ ExportBaseIndexSource(TEXT_SECTION_TYPE_BIBLIOGRAPHY, rPropertySet);
+ }
+
+ ExportBaseIndexBody(TEXT_SECTION_TYPE_BIBLIOGRAPHY, rPropertySet);
+}
+
+
+void XMLSectionExport::ExportBaseIndexStart(
+ XMLTokenEnum eElement,
+ const Reference<XPropertySet> & rPropertySet)
+{
+ // protect + protection key
+ Any aAny = rPropertySet->getPropertyValue("IsProtected");
+ if (*o3tl::doAccess<bool>(aAny))
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_PROTECTED, XML_TRUE);
+ }
+
+ // index name
+ OUString sIndexName;
+ rPropertySet->getPropertyValue("Name") >>= sIndexName;
+ if ( !sIndexName.isEmpty() )
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, sIndexName);
+ }
+
+ // index Element start
+ GetExport().IgnorableWhitespace();
+ GetExport().StartElement( XML_NAMESPACE_TEXT, eElement, false );
+}
+
+const XMLTokenEnum aTypeSourceElementNameMap[] =
+{
+ XML_TABLE_OF_CONTENT_SOURCE, // TOC
+ XML_TABLE_INDEX_SOURCE, // table index
+ XML_ILLUSTRATION_INDEX_SOURCE, // illustration index
+ XML_OBJECT_INDEX_SOURCE, // object index
+ XML_USER_INDEX_SOURCE, // user index
+ XML_ALPHABETICAL_INDEX_SOURCE, // alphabetical index
+ XML_BIBLIOGRAPHY_SOURCE // bibliography
+};
+
+void XMLSectionExport::ExportBaseIndexSource(
+ SectionTypeEnum eType,
+ const Reference<XPropertySet> & rPropertySet)
+{
+ // check type
+ OSL_ENSURE(eType >= TEXT_SECTION_TYPE_TOC, "illegal index type");
+ OSL_ENSURE(eType <= TEXT_SECTION_TYPE_BIBLIOGRAPHY, "illegal index type");
+
+ Any aAny;
+
+ // common attributes; not supported by bibliography
+ if (eType != TEXT_SECTION_TYPE_BIBLIOGRAPHY)
+ {
+ // document or chapter index?
+ aAny = rPropertySet->getPropertyValue("CreateFromChapter");
+ if (*o3tl::doAccess<bool>(aAny))
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT,
+ XML_INDEX_SCOPE, XML_CHAPTER);
+ }
+
+ // tab-stops relative to margin?
+ aAny = rPropertySet->getPropertyValue("IsRelativeTabstops");
+ if (! *o3tl::doAccess<bool>(aAny))
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT,
+ XML_RELATIVE_TAB_STOP_POSITION,
+ XML_FALSE);
+ }
+ }
+
+ // the index source element (all indices)
+ SvXMLElementExport aElem(GetExport(),
+ XML_NAMESPACE_TEXT,
+ GetXMLToken(
+ aTypeSourceElementNameMap[
+ eType - TEXT_SECTION_TYPE_TOC]),
+ true, true);
+
+ // scope for title template (all indices)
+ {
+ // header style name
+ aAny = rPropertySet->getPropertyValue("ParaStyleHeading");
+ OUString sStyleName;
+ aAny >>= sStyleName;
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT,
+ XML_STYLE_NAME,
+ GetExport().EncodeStyleName( sStyleName ));
+
+ // title template
+ SvXMLElementExport aHeaderTemplate(GetExport(),
+ XML_NAMESPACE_TEXT,
+ XML_INDEX_TITLE_TEMPLATE,
+ true, false);
+
+ // title as element content
+ aAny = rPropertySet->getPropertyValue("Title");
+ OUString sTitleString;
+ aAny >>= sTitleString;
+ GetExport().Characters(sTitleString);
+ }
+
+ // export level templates (all indices)
+ aAny = rPropertySet->getPropertyValue("LevelFormat");
+ Reference<XIndexReplace> xLevelTemplates;
+ aAny >>= xLevelTemplates;
+
+ // iterate over level formats;
+ // skip element 0 (empty template for title)
+ sal_Int32 nLevelCount = xLevelTemplates->getCount();
+ for(sal_Int32 i = 1; i<nLevelCount; i++)
+ {
+ // get sequence
+ Sequence<PropertyValues> aTemplateSequence;
+ aAny = xLevelTemplates->getByIndex(i);
+ aAny >>= aTemplateSequence;
+
+ // export the sequence (abort export if an error occurred; #91214#)
+ bool bResult =
+ ExportIndexTemplate(eType, i, rPropertySet, aTemplateSequence);
+ if ( !bResult )
+ break;
+ }
+
+ // only TOC and user index:
+ // styles from which to build the index (LevelParagraphStyles)
+ if ( (TEXT_SECTION_TYPE_TOC == eType) ||
+ (TEXT_SECTION_TYPE_USER == eType) )
+ {
+ aAny = rPropertySet->getPropertyValue("LevelParagraphStyles");
+ Reference<XIndexReplace> xLevelParagraphStyles;
+ aAny >>= xLevelParagraphStyles;
+ ExportLevelParagraphStyles(xLevelParagraphStyles);
+ }
+ else if (TEXT_SECTION_TYPE_ILLUSTRATION == eType
+ || TEXT_SECTION_TYPE_OBJECT == eType
+ || TEXT_SECTION_TYPE_TABLE == eType)
+ {
+ Any const any(rPropertySet->getPropertyValue("CreateFromParagraphStyle"));
+ if (any.hasValue() &&
+ (rExport.getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED))
+ {
+ OUString const styleName(any.get<OUString>());
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_STYLE_NAME,
+ GetExport().EncodeStyleName(styleName));
+
+ SvXMLElementExport const e(GetExport(),
+ XML_NAMESPACE_LO_EXT, XML_INDEX_SOURCE_STYLE, true, false);
+ }
+ }
+}
+
+
+void XMLSectionExport::ExportBaseIndexBody(
+ SectionTypeEnum eType,
+ const Reference<XPropertySet> &)
+{
+ // type not used; checked anyway.
+ OSL_ENSURE(eType >= TEXT_SECTION_TYPE_TOC, "illegal index type");
+ OSL_ENSURE(eType <= TEXT_SECTION_TYPE_BIBLIOGRAPHY, "illegal index type");
+
+ // export start only
+
+ // any old attributes?
+ GetExport().CheckAttrList();
+
+ // start surrounded by whitespace
+ GetExport().IgnorableWhitespace();
+ GetExport().StartElement( XML_NAMESPACE_TEXT, XML_INDEX_BODY, true );
+}
+
+void XMLSectionExport::ExportTableAndIllustrationIndexSourceAttributes(
+ const Reference<XPropertySet> & rPropertySet)
+{
+ // use caption
+ Any aAny = rPropertySet->getPropertyValue("CreateFromLabels");
+ if (! *o3tl::doAccess<bool>(aAny))
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT,
+ XML_USE_CAPTION, XML_FALSE);
+ }
+
+ // sequence name
+ aAny = rPropertySet->getPropertyValue("LabelCategory");
+ OUString sSequenceName;
+ aAny >>= sSequenceName;
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT,
+ XML_CAPTION_SEQUENCE_NAME,
+ sSequenceName);
+
+ // caption format
+ aAny = rPropertySet->getPropertyValue("LabelDisplayType");
+ sal_Int16 nType = 0;
+ aAny >>= nType;
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT,
+ XML_CAPTION_SEQUENCE_FORMAT,
+ XMLTextFieldExport::MapReferenceType(nType));
+}
+
+
+// map index of LevelFormats to attribute value;
+// level 0 is always the header
+const XMLTokenEnum aLevelNameTOCMap[] =
+ { XML_TOKEN_INVALID, XML_1, XML_2, XML_3, XML_4, XML_5, XML_6, XML_7,
+ XML_8, XML_9, XML_10, XML_TOKEN_INVALID };
+const XMLTokenEnum aLevelNameTableMap[] =
+ { XML_TOKEN_INVALID, XML__EMPTY, XML_TOKEN_INVALID };
+const XMLTokenEnum aLevelNameAlphaMap[] =
+ { XML_TOKEN_INVALID, XML_SEPARATOR, XML_1, XML_2, XML_3, XML_TOKEN_INVALID };
+const XMLTokenEnum aLevelNameBibliographyMap[] =
+ { XML_TOKEN_INVALID, XML_ARTICLE, XML_BOOK, XML_BOOKLET, XML_CONFERENCE,
+ XML_CUSTOM1, XML_CUSTOM2, XML_CUSTOM3, XML_CUSTOM4,
+ XML_CUSTOM5, XML_EMAIL, XML_INBOOK, XML_INCOLLECTION,
+ XML_INPROCEEDINGS, XML_JOURNAL,
+ XML_MANUAL, XML_MASTERSTHESIS, XML_MISC, XML_PHDTHESIS,
+ XML_PROCEEDINGS, XML_TECHREPORT, XML_UNPUBLISHED, XML_WWW,
+ XML_TOKEN_INVALID };
+
+static const XMLTokenEnum* aTypeLevelNameMap[] =
+{
+ aLevelNameTOCMap, // TOC
+ aLevelNameTableMap, // table index
+ aLevelNameTableMap, // illustration index
+ aLevelNameTableMap, // object index
+ aLevelNameTOCMap, // user index
+ aLevelNameAlphaMap, // alphabetical index
+ aLevelNameBibliographyMap // bibliography
+};
+
+static const char* aLevelStylePropNameTOCMap[] =
+ { nullptr, "ParaStyleLevel1", "ParaStyleLevel2", "ParaStyleLevel3",
+ "ParaStyleLevel4", "ParaStyleLevel5", "ParaStyleLevel6",
+ "ParaStyleLevel7", "ParaStyleLevel8", "ParaStyleLevel9",
+ "ParaStyleLevel10", nullptr };
+static const char* aLevelStylePropNameTableMap[] =
+ { nullptr, "ParaStyleLevel1", nullptr };
+static const char* aLevelStylePropNameAlphaMap[] =
+ { nullptr, "ParaStyleSeparator", "ParaStyleLevel1", "ParaStyleLevel2",
+ "ParaStyleLevel3", nullptr };
+static const char* aLevelStylePropNameBibliographyMap[] =
+ // TODO: replace with real property names, when available
+ { nullptr, "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
+ "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
+ "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
+ "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
+ "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
+ "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
+ "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
+ "ParaStyleLevel1",
+ nullptr };
+
+static const char** aTypeLevelStylePropNameMap[] =
+{
+ aLevelStylePropNameTOCMap, // TOC
+ aLevelStylePropNameTableMap, // table index
+ aLevelStylePropNameTableMap, // illustration index
+ aLevelStylePropNameTableMap, // object index
+ aLevelStylePropNameTOCMap, // user index
+ aLevelStylePropNameAlphaMap, // alphabetical index
+ aLevelStylePropNameBibliographyMap // bibliography
+};
+
+const XMLTokenEnum aTypeLevelAttrMap[] =
+{
+ XML_OUTLINE_LEVEL, // TOC
+ XML_TOKEN_INVALID, // table index
+ XML_TOKEN_INVALID, // illustration index
+ XML_TOKEN_INVALID, // object index
+ XML_OUTLINE_LEVEL, // user index
+ XML_OUTLINE_LEVEL, // alphabetical index
+ XML_BIBLIOGRAPHY_TYPE // bibliography
+};
+
+const XMLTokenEnum aTypeElementNameMap[] =
+{
+ XML_TABLE_OF_CONTENT_ENTRY_TEMPLATE, // TOC
+ XML_TABLE_INDEX_ENTRY_TEMPLATE, // table index
+ XML_ILLUSTRATION_INDEX_ENTRY_TEMPLATE, // illustration index
+ XML_OBJECT_INDEX_ENTRY_TEMPLATE, // object index
+ XML_USER_INDEX_ENTRY_TEMPLATE, // user index
+ XML_ALPHABETICAL_INDEX_ENTRY_TEMPLATE, // alphabetical index
+ XML_BIBLIOGRAPHY_ENTRY_TEMPLATE // bibliography
+};
+
+
+bool XMLSectionExport::ExportIndexTemplate(
+ SectionTypeEnum eType,
+ sal_Int32 nOutlineLevel,
+ const Reference<XPropertySet> & rPropertySet,
+ const Sequence<Sequence<PropertyValue> > & rValues)
+{
+ OSL_ENSURE(eType >= TEXT_SECTION_TYPE_TOC, "illegal index type");
+ OSL_ENSURE(eType <= TEXT_SECTION_TYPE_BIBLIOGRAPHY, "illegal index type");
+ OSL_ENSURE(nOutlineLevel >= 0, "illegal outline level");
+
+ if ( (eType >= TEXT_SECTION_TYPE_TOC) &&
+ (eType <= TEXT_SECTION_TYPE_BIBLIOGRAPHY) &&
+ (nOutlineLevel >= 0) )
+ {
+ // get level name and level attribute name from aLevelNameMap;
+ const XMLTokenEnum eLevelAttrName(
+ aTypeLevelAttrMap[eType-TEXT_SECTION_TYPE_TOC]);
+ const XMLTokenEnum eLevelName(
+ aTypeLevelNameMap[eType-TEXT_SECTION_TYPE_TOC][nOutlineLevel]);
+
+ // #92124#: some old documents may be broken, then they have
+ // too many template levels; we need to recognize this and
+ // export only as many as is legal for the respective index
+ // type. To do this, we simply return an error flag, which
+ // will then abort further template level exports.
+ OSL_ENSURE(XML_TOKEN_INVALID != eLevelName, "can't find level name");
+ if ( XML_TOKEN_INVALID == eLevelName )
+ {
+ // output level not found? Then end of templates! #91214#
+ return false;
+ }
+
+ // output level name
+ if ((XML_TOKEN_INVALID != eLevelName) && (XML_TOKEN_INVALID != eLevelAttrName))
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT,
+ GetXMLToken(eLevelAttrName),
+ GetXMLToken(eLevelName));
+ }
+
+ // paragraph level style name
+ const char* pPropName(
+ aTypeLevelStylePropNameMap[eType-TEXT_SECTION_TYPE_TOC][nOutlineLevel]);
+ OSL_ENSURE(nullptr != pPropName, "can't find property name");
+ if (nullptr != pPropName)
+ {
+ Any aAny = rPropertySet->getPropertyValue(
+ OUString::createFromAscii(pPropName));
+ OUString sParaStyleName;
+ aAny >>= sParaStyleName;
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT,
+ XML_STYLE_NAME,
+ GetExport().EncodeStyleName( sParaStyleName ));
+ }
+
+ // template element
+ const XMLTokenEnum eElementName(
+ aTypeElementNameMap[eType - TEXT_SECTION_TYPE_TOC]);
+ SvXMLElementExport aLevelTemplate(GetExport(),
+ XML_NAMESPACE_TEXT,
+ GetXMLToken(eElementName),
+ true, true);
+
+ // export sequence
+ for(auto& rValue : rValues)
+ {
+ ExportIndexTemplateElement(
+ eType, //i90246
+ rValue);
+ }
+ }
+
+ return true;
+}
+
+namespace {
+
+enum TemplateTypeEnum
+{
+ TOK_TTYPE_ENTRY_NUMBER,
+ TOK_TTYPE_ENTRY_TEXT,
+ TOK_TTYPE_TAB_STOP,
+ TOK_TTYPE_TEXT,
+ TOK_TTYPE_PAGE_NUMBER,
+ TOK_TTYPE_CHAPTER_INFO,
+ TOK_TTYPE_HYPERLINK_START,
+ TOK_TTYPE_HYPERLINK_END,
+ TOK_TTYPE_BIBLIOGRAPHY,
+ TOK_TTYPE_INVALID
+};
+
+enum TemplateParamEnum
+{
+ TOK_TPARAM_TOKEN_TYPE,
+ TOK_TPARAM_CHAR_STYLE,
+ TOK_TPARAM_TAB_RIGHT_ALIGNED,
+ TOK_TPARAM_TAB_POSITION,
+ TOK_TPARAM_TAB_WITH_TAB, // #i21237#
+ TOK_TPARAM_TAB_FILL_CHAR,
+ TOK_TPARAM_TEXT,
+ TOK_TPARAM_CHAPTER_FORMAT,
+ TOK_TPARAM_CHAPTER_LEVEL,//i53420
+ TOK_TPARAM_BIBLIOGRAPHY_DATA
+};
+
+}
+
+SvXMLEnumStringMapEntry<TemplateTypeEnum> const aTemplateTypeMap[] =
+{
+ ENUM_STRING_MAP_ENTRY( "TokenEntryNumber", TOK_TTYPE_ENTRY_NUMBER ),
+ ENUM_STRING_MAP_ENTRY( "TokenEntryText", TOK_TTYPE_ENTRY_TEXT ),
+ ENUM_STRING_MAP_ENTRY( "TokenTabStop", TOK_TTYPE_TAB_STOP ),
+ ENUM_STRING_MAP_ENTRY( "TokenText", TOK_TTYPE_TEXT ),
+ ENUM_STRING_MAP_ENTRY( "TokenPageNumber", TOK_TTYPE_PAGE_NUMBER ),
+ ENUM_STRING_MAP_ENTRY( "TokenChapterInfo", TOK_TTYPE_CHAPTER_INFO ),
+ ENUM_STRING_MAP_ENTRY( "TokenHyperlinkStart", TOK_TTYPE_HYPERLINK_START ),
+ ENUM_STRING_MAP_ENTRY( "TokenHyperlinkEnd", TOK_TTYPE_HYPERLINK_END ),
+ ENUM_STRING_MAP_ENTRY( "TokenBibliographyDataField", TOK_TTYPE_BIBLIOGRAPHY ),
+ { nullptr, 0, TemplateTypeEnum(0)}
+};
+
+SvXMLEnumStringMapEntry<TemplateParamEnum> const aTemplateParamMap[] =
+{
+ ENUM_STRING_MAP_ENTRY( "TokenType", TOK_TPARAM_TOKEN_TYPE ),
+ ENUM_STRING_MAP_ENTRY( "CharacterStyleName", TOK_TPARAM_CHAR_STYLE ),
+ ENUM_STRING_MAP_ENTRY( "TabStopRightAligned", TOK_TPARAM_TAB_RIGHT_ALIGNED ),
+ ENUM_STRING_MAP_ENTRY( "TabStopPosition", TOK_TPARAM_TAB_POSITION ),
+ ENUM_STRING_MAP_ENTRY( "TabStopFillCharacter", TOK_TPARAM_TAB_FILL_CHAR ),
+ // #i21237#
+ ENUM_STRING_MAP_ENTRY( "WithTab", TOK_TPARAM_TAB_WITH_TAB ),
+ ENUM_STRING_MAP_ENTRY( "Text", TOK_TPARAM_TEXT ),
+ ENUM_STRING_MAP_ENTRY( "ChapterFormat", TOK_TPARAM_CHAPTER_FORMAT ),
+ ENUM_STRING_MAP_ENTRY( "ChapterLevel", TOK_TPARAM_CHAPTER_LEVEL ),//i53420
+ ENUM_STRING_MAP_ENTRY( "BibliographyDataField", TOK_TPARAM_BIBLIOGRAPHY_DATA ),
+ { nullptr, 0, TemplateParamEnum(0)}
+};
+
+SvXMLEnumMapEntry<sal_Int16> const aBibliographyDataFieldMap[] =
+{
+ { XML_ADDRESS, BibliographyDataField::ADDRESS },
+ { XML_ANNOTE, BibliographyDataField::ANNOTE },
+ { XML_AUTHOR, BibliographyDataField::AUTHOR },
+ { XML_BIBLIOGRAPHY_TYPE, BibliographyDataField::BIBILIOGRAPHIC_TYPE },
+ { XML_BOOKTITLE, BibliographyDataField::BOOKTITLE },
+ { XML_CHAPTER, BibliographyDataField::CHAPTER },
+ { XML_CUSTOM1, BibliographyDataField::CUSTOM1 },
+ { XML_CUSTOM2, BibliographyDataField::CUSTOM2 },
+ { XML_CUSTOM3, BibliographyDataField::CUSTOM3 },
+ { XML_CUSTOM4, BibliographyDataField::CUSTOM4 },
+ { XML_CUSTOM5, BibliographyDataField::CUSTOM5 },
+ { XML_EDITION, BibliographyDataField::EDITION },
+ { XML_EDITOR, BibliographyDataField::EDITOR },
+ { XML_HOWPUBLISHED, BibliographyDataField::HOWPUBLISHED },
+ { XML_IDENTIFIER, BibliographyDataField::IDENTIFIER },
+ { XML_INSTITUTION, BibliographyDataField::INSTITUTION },
+ { XML_ISBN, BibliographyDataField::ISBN },
+ { XML_JOURNAL, BibliographyDataField::JOURNAL },
+ { XML_MONTH, BibliographyDataField::MONTH },
+ { XML_NOTE, BibliographyDataField::NOTE },
+ { XML_NUMBER, BibliographyDataField::NUMBER },
+ { XML_ORGANIZATIONS, BibliographyDataField::ORGANIZATIONS },
+ { XML_PAGES, BibliographyDataField::PAGES },
+ { XML_PUBLISHER, BibliographyDataField::PUBLISHER },
+ { XML_REPORT_TYPE, BibliographyDataField::REPORT_TYPE },
+ { XML_SCHOOL, BibliographyDataField::SCHOOL },
+ { XML_SERIES, BibliographyDataField::SERIES },
+ { XML_TITLE, BibliographyDataField::TITLE },
+ { XML_URL, BibliographyDataField::URL },
+ { XML_VOLUME, BibliographyDataField::VOLUME },
+ { XML_YEAR, BibliographyDataField::YEAR },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+void XMLSectionExport::ExportIndexTemplateElement(
+ SectionTypeEnum eType, //i90246
+ const Sequence<PropertyValue> & rValues)
+{
+ // variables for template values
+
+ // char style
+ OUString sCharStyle;
+ bool bCharStyleOK = false;
+
+ // text
+ OUString sText;
+ bool bTextOK = false;
+
+ // tab position
+ bool bRightAligned = false;
+
+ // tab position
+ sal_Int32 nTabPosition = 0;
+ bool bTabPositionOK = false;
+
+ // fill character
+ OUString sFillChar;
+ bool bFillCharOK = false;
+
+ // chapter format
+ sal_Int16 nChapterFormat = 0;
+ bool bChapterFormatOK = false;
+
+ // outline max level
+ sal_Int16 nLevel = 0;
+ bool bLevelOK = false;
+
+ // Bibliography Data
+ sal_Int16 nBibliographyData = 0;
+ bool bBibliographyDataOK = false;
+
+ // With Tab Stop #i21237#
+ bool bWithTabStop = false;
+ bool bWithTabStopOK = false;
+
+ //i90246, the ODF version being written to is:
+ const SvtSaveOptions::ODFSaneDefaultVersion aODFVersion = rExport.getSaneDefaultVersion();
+ //the above version cannot be used for old OOo (OOo 1.0) formats!
+
+ // token type
+ enum TemplateTypeEnum nTokenType = TOK_TTYPE_INVALID;
+
+ for(const auto& rValue : rValues)
+ {
+ TemplateParamEnum nToken;
+ if ( SvXMLUnitConverter::convertEnum( nToken, rValue.Name,
+ aTemplateParamMap ) )
+ {
+ // Only use direct and default values.
+ // Wrong. no property states, so ignore.
+ // if ( (beans::PropertyState_DIRECT_VALUE == rValues[i].State) ||
+ // (beans::PropertyState_DEFAULT_VALUE == rValues[i].State) )
+
+ switch (nToken)
+ {
+ case TOK_TPARAM_TOKEN_TYPE:
+ {
+ OUString sVal;
+ rValue.Value >>= sVal;
+ SvXMLUnitConverter::convertEnum( nTokenType, sVal, aTemplateTypeMap);
+ break;
+ }
+
+ case TOK_TPARAM_CHAR_STYLE:
+ // only valid, if not empty
+ rValue.Value >>= sCharStyle;
+ bCharStyleOK = !sCharStyle.isEmpty();
+ break;
+
+ case TOK_TPARAM_TEXT:
+ rValue.Value >>= sText;
+ bTextOK = true;
+ break;
+
+ case TOK_TPARAM_TAB_RIGHT_ALIGNED:
+ bRightAligned =
+ *o3tl::doAccess<bool>(rValue.Value);
+ break;
+
+ case TOK_TPARAM_TAB_POSITION:
+ rValue.Value >>= nTabPosition;
+ bTabPositionOK = true;
+ break;
+
+ // #i21237#
+ case TOK_TPARAM_TAB_WITH_TAB:
+ bWithTabStop = *o3tl::doAccess<bool>(rValue.Value);
+ bWithTabStopOK = true;
+ break;
+
+ case TOK_TPARAM_TAB_FILL_CHAR:
+ rValue.Value >>= sFillChar;
+ bFillCharOK = true;
+ break;
+
+ case TOK_TPARAM_CHAPTER_FORMAT:
+ rValue.Value >>= nChapterFormat;
+ bChapterFormatOK = true;
+ break;
+//---> i53420
+ case TOK_TPARAM_CHAPTER_LEVEL:
+ rValue.Value >>= nLevel;
+ bLevelOK = true;
+ break;
+ case TOK_TPARAM_BIBLIOGRAPHY_DATA:
+ rValue.Value >>= nBibliographyData;
+ bBibliographyDataOK = true;
+ break;
+ }
+ }
+ }
+
+ // convert type to token (and check validity) ...
+ XMLTokenEnum eElement(XML_TOKEN_INVALID);
+ sal_uInt16 nNamespace(XML_NAMESPACE_TEXT);
+ switch(nTokenType)
+ {
+ case TOK_TTYPE_ENTRY_TEXT:
+ eElement = XML_INDEX_ENTRY_TEXT;
+ break;
+ case TOK_TTYPE_TAB_STOP:
+ // test validity
+ if ( bRightAligned || bTabPositionOK || bFillCharOK )
+ {
+ eElement = XML_INDEX_ENTRY_TAB_STOP;
+ }
+ break;
+ case TOK_TTYPE_TEXT:
+ // test validity
+ if (bTextOK)
+ {
+ eElement = XML_INDEX_ENTRY_SPAN;
+ }
+ break;
+ case TOK_TTYPE_PAGE_NUMBER:
+ eElement = XML_INDEX_ENTRY_PAGE_NUMBER;
+ break;
+ case TOK_TTYPE_CHAPTER_INFO: // keyword index
+ eElement = XML_INDEX_ENTRY_CHAPTER;
+ break;
+ case TOK_TTYPE_ENTRY_NUMBER: // table of content
+ eElement = XML_INDEX_ENTRY_CHAPTER;
+ break;
+ case TOK_TTYPE_HYPERLINK_START:
+ eElement = XML_INDEX_ENTRY_LINK_START;
+ break;
+ case TOK_TTYPE_HYPERLINK_END:
+ eElement = XML_INDEX_ENTRY_LINK_END;
+ break;
+ case TOK_TTYPE_BIBLIOGRAPHY:
+ if (bBibliographyDataOK)
+ {
+ eElement = XML_INDEX_ENTRY_BIBLIOGRAPHY;
+ }
+ break;
+ default:
+ ; // unknown/unimplemented template
+ break;
+ }
+
+ if (eType != TEXT_SECTION_TYPE_TOC)
+ {
+ switch (nTokenType)
+ {
+ case TOK_TTYPE_HYPERLINK_START:
+ case TOK_TTYPE_HYPERLINK_END:
+ if (SvtSaveOptions::ODFSVER_012 < aODFVersion)
+ {
+ assert(eType == TEXT_SECTION_TYPE_ILLUSTRATION
+ || eType == TEXT_SECTION_TYPE_OBJECT
+ || eType == TEXT_SECTION_TYPE_TABLE
+ || eType == TEXT_SECTION_TYPE_USER);
+ // ODF 1.3 OFFICE-3941
+ nNamespace = (SvtSaveOptions::ODFSVER_013 <= aODFVersion)
+ ? XML_NAMESPACE_TEXT
+ : XML_NAMESPACE_LO_EXT;
+ }
+ else
+ {
+ eElement = XML_TOKEN_INVALID; // not allowed in ODF <= 1.2
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ //--->i90246
+ //check the ODF version being exported
+ if (aODFVersion == SvtSaveOptions::ODFSVER_011
+ || aODFVersion == SvtSaveOptions::ODFSVER_010)
+ {
+ bLevelOK = false;
+ if (TOK_TTYPE_CHAPTER_INFO == nTokenType)
+ {
+ //if we are emitting for ODF 1.1 or 1.0, this information can be used for alphabetical index only
+ //it's not permitted in other indexes
+ if (eType != TEXT_SECTION_TYPE_ALPHABETICAL)
+ {
+ eElement = XML_TOKEN_INVALID; //not permitted, invalidate the element
+ }
+ else //maps format for 1.1 & 1.0
+ {
+ // a few word here: OOo up to 2.4 uses the field chapter info in Alphabetical index
+ // in a way different from the ODF 1.1/1.0 specification:
+
+ // ODF1.1/1.0 OOo display in chapter info ODF1.2
+ // (used in alphabetical index only
+
+ // number chapter number without pre/postfix plain-number
+ // number-and-name chapter number without pre/postfix plus title plain-number-and-name
+
+ // with issue i89791 the reading of ODF 1.1 and 1.0 was corrected
+ // this one corrects the writing back from ODF 1.2 to ODF 1.1/1.0
+ // unfortunately if there is another application which interprets correctly ODF1.1/1.0,
+ // the resulting alphabetical index will be rendered wrong by OOo 2.4 version
+
+ switch( nChapterFormat )
+ {
+ case ChapterFormat::DIGIT:
+ nChapterFormat = ChapterFormat::NUMBER;
+ break;
+ case ChapterFormat::NO_PREFIX_SUFFIX:
+ nChapterFormat = ChapterFormat::NAME_NUMBER;
+ break;
+ }
+ }
+ }
+ else if (TOK_TTYPE_ENTRY_NUMBER == nTokenType)
+ {
+ //in case of ODF 1.1 or 1.0 the only allowed number format is "number"
+ //so, force it...
+ // The only expected 'foreign' nChapterFormat is
+ // ' ChapterFormat::DIGIT', forced to 'none, since the
+ // 'value allowed in ODF 1.1 and 1.0 is 'number' the default
+ // this can be obtained by simply disabling the chapter format
+ bChapterFormatOK = false;
+ }
+ }
+
+ // ... and write Element
+ if (eElement == XML_TOKEN_INVALID)
+ return;
+
+ // character style (for most templates)
+ if (bCharStyleOK)
+ {
+ switch (nTokenType)
+ {
+ case TOK_TTYPE_ENTRY_TEXT:
+ case TOK_TTYPE_TEXT:
+ case TOK_TTYPE_PAGE_NUMBER:
+ case TOK_TTYPE_ENTRY_NUMBER:
+ case TOK_TTYPE_HYPERLINK_START:
+ case TOK_TTYPE_HYPERLINK_END:
+ case TOK_TTYPE_BIBLIOGRAPHY:
+ case TOK_TTYPE_CHAPTER_INFO:
+ case TOK_TTYPE_TAB_STOP:
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT,
+ XML_STYLE_NAME,
+ GetExport().EncodeStyleName( sCharStyle) );
+ break;
+ default:
+ ; // nothing: no character style
+ break;
+ }
+ }
+
+ // tab properties
+ if (TOK_TTYPE_TAB_STOP == nTokenType)
+ {
+ // tab type
+ GetExport().AddAttribute(XML_NAMESPACE_STYLE, XML_TYPE,
+ bRightAligned ? XML_RIGHT : XML_LEFT);
+
+ if (bTabPositionOK && (! bRightAligned))
+ {
+ // position for left tabs (convert to measure)
+ OUStringBuffer sBuf;
+ GetExport().GetMM100UnitConverter().convertMeasureToXML(sBuf,
+ nTabPosition);
+ GetExport().AddAttribute(XML_NAMESPACE_STYLE,
+ XML_POSITION,
+ sBuf.makeStringAndClear());
+ }
+
+ // fill char ("leader char")
+ if (bFillCharOK && !sFillChar.isEmpty())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_STYLE,
+ XML_LEADER_CHAR, sFillChar);
+ }
+
+ // #i21237#
+ if (bWithTabStopOK && ! bWithTabStop)
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_STYLE,
+ XML_WITH_TAB,
+ XML_FALSE);
+ }
+ }
+
+ // bibliography data
+ if (TOK_TTYPE_BIBLIOGRAPHY == nTokenType)
+ {
+ OSL_ENSURE(bBibliographyDataOK, "need bibl data");
+ OUStringBuffer sBuf;
+ if (SvXMLUnitConverter::convertEnum( sBuf, nBibliographyData,
+ aBibliographyDataFieldMap ) )
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT,
+ XML_BIBLIOGRAPHY_DATA_FIELD,
+ sBuf.makeStringAndClear());
+ }
+ }
+
+ // chapter info
+ if (TOK_TTYPE_CHAPTER_INFO == nTokenType)
+ {
+ OSL_ENSURE(bChapterFormatOK, "need chapter info");
+ GetExport().AddAttribute(
+ XML_NAMESPACE_TEXT, XML_DISPLAY,
+ XMLTextFieldExport::MapChapterDisplayFormat(nChapterFormat));
+//---> i53420
+ if (bLevelOK)
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_OUTLINE_LEVEL,
+ OUString::number(nLevel));
+ }
+
+//--->i53420
+ if (TOK_TTYPE_ENTRY_NUMBER == nTokenType)
+ {
+ if (bChapterFormatOK)
+ GetExport().AddAttribute(
+ XML_NAMESPACE_TEXT, XML_DISPLAY,
+ XMLTextFieldExport::MapChapterDisplayFormat(nChapterFormat));
+
+ if (bLevelOK)
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_OUTLINE_LEVEL,
+ OUString::number(nLevel));
+ }
+ // export template
+ SvXMLElementExport aTemplateElement(GetExport(), nNamespace,
+ GetXMLToken(eElement),
+ true, false)
+ ;
+
+ // entry text or span element: write text
+ if (TOK_TTYPE_TEXT == nTokenType)
+ {
+ GetExport().Characters(sText);
+ }
+}
+
+void XMLSectionExport::ExportLevelParagraphStyles(
+ Reference<XIndexReplace> const & xLevelParagraphStyles)
+{
+ // iterate over levels
+ sal_Int32 nPLevelCount = xLevelParagraphStyles->getCount();
+ for(sal_Int32 nLevel = 0; nLevel < nPLevelCount; nLevel++)
+ {
+ Any aAny = xLevelParagraphStyles->getByIndex(nLevel);
+ Sequence<OUString> aStyleNames;
+ aAny >>= aStyleNames;
+
+ // export only if at least one style is contained
+ if (aStyleNames.hasElements())
+ {
+ // level attribute; we count 1..10; API 0..9
+ sal_Int32 nLevelPlusOne = nLevel + 1;
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT,
+ XML_OUTLINE_LEVEL,
+ OUString::number(nLevelPlusOne));
+
+ // source styles element
+ SvXMLElementExport aParaStyles(GetExport(),
+ XML_NAMESPACE_TEXT,
+ XML_INDEX_SOURCE_STYLES,
+ true, true);
+
+ // iterate over styles in this level
+ for(const auto& rStyleName : std::as_const(aStyleNames))
+ {
+ // stylename attribute
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT,
+ XML_STYLE_NAME,
+ GetExport().EncodeStyleName(rStyleName) );
+
+ // element
+ SvXMLElementExport aParaStyle(GetExport(),
+ XML_NAMESPACE_TEXT,
+ XML_INDEX_SOURCE_STYLE,
+ true, false);
+ }
+ }
+ }
+}
+
+void XMLSectionExport::ExportBoolean(
+ const Reference<XPropertySet> & rPropSet,
+ const OUString& sPropertyName,
+ enum XMLTokenEnum eAttributeName,
+ bool bDefault,
+ bool bInvert)
+{
+ OSL_ENSURE(eAttributeName != XML_TOKEN_INVALID, "Need attribute name");
+
+ Any aAny = rPropSet->getPropertyValue(sPropertyName);
+ bool bTmp = *o3tl::doAccess<bool>(aAny);
+
+ // value = value ^ bInvert
+ // omit if value == default
+ if ( (bTmp != bInvert) != bDefault )
+ {
+ // export non-default value (since default is omitted)
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT,
+ eAttributeName,
+ bDefault ? XML_FALSE : XML_TRUE);
+ }
+}
+
+void XMLSectionExport::ExportBibliographyConfiguration(SvXMLExport& rExport)
+{
+ // first: get field master (via text field supplier)
+ Reference<XTextFieldsSupplier> xTextFieldsSupp( rExport.GetModel(),
+ UNO_QUERY );
+ if ( !xTextFieldsSupp.is() )
+ return;
+
+ static constexpr OUString sFieldMaster_Bibliography(u"com.sun.star.text.FieldMaster.Bibliography"_ustr);
+
+ // get bibliography field master
+ Reference<XNameAccess> xMasters =
+ xTextFieldsSupp->getTextFieldMasters();
+ if ( !xMasters->hasByName(sFieldMaster_Bibliography) )
+ return;
+
+ Any aAny =
+ xMasters->getByName(sFieldMaster_Bibliography);
+ Reference<XPropertySet> xPropSet;
+ aAny >>= xPropSet;
+
+ OSL_ENSURE( xPropSet.is(), "field master must have XPropSet" );
+
+ OUString sTmp;
+
+ aAny = xPropSet->getPropertyValue("BracketBefore");
+ aAny >>= sTmp;
+ rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_PREFIX, sTmp);
+
+ aAny = xPropSet->getPropertyValue("BracketAfter");
+ aAny >>= sTmp;
+ rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_SUFFIX, sTmp);
+
+ aAny = xPropSet->getPropertyValue("IsNumberEntries");
+ if (*o3tl::doAccess<bool>(aAny))
+ {
+ rExport.AddAttribute(XML_NAMESPACE_TEXT,
+ XML_NUMBERED_ENTRIES, XML_TRUE);
+ }
+
+ aAny = xPropSet->getPropertyValue("IsSortByPosition");
+ if (! *o3tl::doAccess<bool>(aAny))
+ {
+ rExport.AddAttribute(XML_NAMESPACE_TEXT,
+ XML_SORT_BY_POSITION, XML_FALSE);
+ }
+
+ // sort algorithm
+ aAny = xPropSet->getPropertyValue("SortAlgorithm");
+ OUString sAlgorithm;
+ aAny >>= sAlgorithm;
+ if( !sAlgorithm.isEmpty() )
+ {
+ rExport.AddAttribute( XML_NAMESPACE_TEXT,
+ XML_SORT_ALGORITHM, sAlgorithm );
+ }
+
+ // locale
+ aAny = xPropSet->getPropertyValue("Locale");
+ Locale aLocale;
+ aAny >>= aLocale;
+ rExport.AddLanguageTagAttributes( XML_NAMESPACE_FO, XML_NAMESPACE_STYLE, aLocale, true);
+
+ // configuration element
+ SvXMLElementExport aElement(rExport, XML_NAMESPACE_TEXT,
+ XML_BIBLIOGRAPHY_CONFIGURATION,
+ true, true);
+
+ // sort keys
+ aAny = xPropSet->getPropertyValue("SortKeys");
+ Sequence<Sequence<PropertyValue> > aKeys;
+ aAny >>= aKeys;
+ for(const Sequence<PropertyValue> & rKey : std::as_const(aKeys))
+ {
+ for(const PropertyValue& rValue : rKey)
+ {
+ if (rValue.Name == "SortKey")
+ {
+ sal_Int16 nKey = 0;
+ rValue.Value >>= nKey;
+ OUStringBuffer sBuf;
+ if (SvXMLUnitConverter::convertEnum( sBuf, nKey,
+ aBibliographyDataFieldMap ) )
+ {
+ rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_KEY,
+ sBuf.makeStringAndClear());
+ }
+ }
+ else if (rValue.Name == "IsSortAscending")
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rValue.Value);
+ rExport.AddAttribute(XML_NAMESPACE_TEXT,
+ XML_SORT_ASCENDING,
+ bTmp ? XML_TRUE : XML_FALSE);
+ }
+ }
+
+ SvXMLElementExport aKeyElem(rExport,
+ XML_NAMESPACE_TEXT, XML_SORT_KEY,
+ true, true);
+ }
+}
+
+
+bool XMLSectionExport::IsMuteSection(
+ const Reference<XTextSection> & rSection) const
+{
+ bool bRet = false;
+
+ // a section is mute if
+ // 1) it exists
+ // 2) the SaveLinkedSections flag (at the export) is false
+ // 3) the IsGlobalDocumentSection property is true
+ // 4) it is not an Index
+
+ if ( (!rExport.IsSaveLinkedSections()) && rSection.is() )
+ {
+ // walk the section chain and set bRet if any is linked
+ for(Reference<XTextSection> aSection(rSection);
+ aSection.is();
+ aSection = aSection->getParentSection())
+ {
+ // check if it is a global document section (linked or index)
+ Reference<XPropertySet> xPropSet(aSection, UNO_QUERY);
+ if (xPropSet.is())
+ {
+ Any aAny = xPropSet->getPropertyValue("IsGlobalDocumentSection");
+
+ if ( *o3tl::doAccess<bool>(aAny) )
+ {
+ Reference<XDocumentIndex> xIndex;
+ if (! GetIndex(rSection, xIndex))
+ {
+ bRet = true;
+
+ // early out if result is known
+ break;
+ }
+ }
+ }
+ // section has no properties: ignore
+ }
+ }
+ // else: no section, or always save sections: default (false)
+
+ return bRet;
+}
+
+bool XMLSectionExport::IsMuteSection(
+ const Reference<XTextContent> & rSection,
+ bool bDefault) const
+{
+ // default: like default argument
+ bool bRet = bDefault;
+
+ Reference<XPropertySet> xPropSet(rSection->getAnchor(), UNO_QUERY);
+ if (xPropSet.is())
+ {
+ if (xPropSet->getPropertySetInfo()->hasPropertyByName("TextSection"))
+ {
+ Any aAny = xPropSet->getPropertyValue("TextSection");
+ Reference<XTextSection> xSection;
+ aAny >>= xSection;
+
+ bRet = IsMuteSection(xSection);
+ }
+ // else: return default
+ }
+ // else: return default
+
+ return bRet;
+}
+
+bool XMLSectionExport::IsInSection(
+ const Reference<XTextSection> & rEnclosingSection,
+ const Reference<XTextContent> & rContent,
+ bool bDefault)
+{
+ // default: like default argument
+ bool bRet = bDefault;
+ OSL_ENSURE(rEnclosingSection.is(), "enclosing section expected");
+
+ Reference<XPropertySet> xPropSet(rContent, UNO_QUERY);
+ if (xPropSet.is())
+ {
+ if (xPropSet->getPropertySetInfo()->hasPropertyByName("TextSection"))
+ {
+ Any aAny = xPropSet->getPropertyValue("TextSection");
+ Reference<XTextSection> xSection;
+ aAny >>= xSection;
+
+ // now walk chain of text sections (if we have one)
+ if (xSection.is())
+ {
+ do
+ {
+ bRet = (rEnclosingSection == xSection);
+ xSection = xSection->getParentSection();
+ }
+ while (!bRet && xSection.is());
+ }
+ else
+ bRet = false; // no section -> can't be inside
+ }
+ // else: no TextSection property -> return default
+ }
+ // else: no XPropertySet -> return default
+
+ return bRet;
+}
+
+
+void XMLSectionExport::ExportMasterDocHeadingDummies()
+{
+ if( bHeadingDummiesExported )
+ return;
+
+ Reference< XChapterNumberingSupplier > xCNSupplier( rExport.GetModel(),
+ UNO_QUERY );
+
+ Reference< XIndexReplace > xChapterNumbering;
+ if( xCNSupplier.is() )
+ xChapterNumbering = xCNSupplier->getChapterNumberingRules();
+
+ if( !xChapterNumbering.is() )
+ return;
+
+ sal_Int32 nCount = xChapterNumbering->getCount();
+ for( sal_Int32 nLevel = 0; nLevel < nCount; nLevel++ )
+ {
+ OUString sStyle;
+ Sequence<PropertyValue> aProperties;
+ xChapterNumbering->getByIndex( nLevel ) >>= aProperties;
+ auto pProp = std::find_if(std::cbegin(aProperties), std::cend(aProperties),
+ [](const PropertyValue& rProp) { return rProp.Name == "HeadingStyleName"; });
+ if (pProp != std::cend(aProperties))
+ pProp->Value >>= sStyle;
+
+ if( !sStyle.isEmpty() )
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
+ GetExport().EncodeStyleName( sStyle ) );
+
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_LEVEL,
+ OUString::number( nLevel + 1 ) );
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT, XML_H,
+ true, false );
+ }
+ }
+
+ bHeadingDummiesExported = true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLSectionExport.hxx b/xmloff/source/text/XMLSectionExport.hxx
new file mode 100644
index 0000000000..05180e2f2d
--- /dev/null
+++ b/xmloff/source/text/XMLSectionExport.hxx
@@ -0,0 +1,262 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <rtl/ustring.hxx>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/Sequence.h>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <xmloff/xmltoken.hxx>
+
+class SvXMLExport;
+class XMLTextParagraphExport;
+namespace com::sun::star {
+ namespace text
+ {
+ class XTextSection;
+ class XDocumentIndex;
+ class XTextContent;
+ }
+ namespace beans
+ {
+ class XPropertySet;
+ }
+ namespace container
+ {
+ class XIndexReplace;
+ }
+}
+
+
+enum SectionTypeEnum
+{
+ TEXT_SECTION_TYPE_TOC,
+ TEXT_SECTION_TYPE_TABLE,
+ TEXT_SECTION_TYPE_ILLUSTRATION,
+ TEXT_SECTION_TYPE_OBJECT,
+ TEXT_SECTION_TYPE_USER,
+ TEXT_SECTION_TYPE_ALPHABETICAL,
+ TEXT_SECTION_TYPE_BIBLIOGRAPHY,
+ TEXT_SECTION_TYPE_UNKNOWN
+};
+
+
+/**
+ * This class handles the export of sections and indices (which are,
+ * internally, just sections). It is intended to be used only from
+ * within the XMLTextParagraphExport class.
+ */
+class XMLSectionExport
+{
+ SvXMLExport& rExport;
+ XMLTextParagraphExport& rParaExport;
+
+ bool bHeadingDummiesExported;
+
+public:
+ XMLSectionExport(SvXMLExport& rExp,
+ XMLTextParagraphExport& rParaExp);
+
+ /**
+ * export section or index start and source elements. This
+ * method handles the section styles, and delegates to the
+ * appropriate section or index method.
+ */
+ void ExportSectionStart(
+ const css::uno::Reference < css::text::XTextSection > & rSection,
+ bool bAutoStyles);
+
+ /**
+ * export section or index end elements
+ */
+ void ExportSectionEnd(
+ const css::uno::Reference < css::text::XTextSection > & rSection,
+ bool bAutoStyles);
+
+ /**
+ * Should the content of this section be exported?
+ * (E.g. linked sections in global documents are not always exported)
+ */
+ bool IsMuteSection(
+ const css::uno::Reference < css::text::XTextSection > & rSection) const;
+
+ /**
+ * XTextContent-version of IsMuteSection(Reference<XTextSection>&)
+ * returns *true* for all non-section elements
+ */
+ bool IsMuteSection(
+ const css::uno::Reference < css::text::XTextContent > & rSection,
+ /// return value if this content doesn't support the section property
+ bool bDefault) const;
+
+ /**
+ * Determine whether rContent is contained in rEnclosingSection. If the
+ * current section of rContent can not be determined, return bDefault.
+ */
+ static bool IsInSection(
+ const css::uno::Reference < css::text::XTextSection > & rEnclosingSection,
+ const css::uno::Reference < css::text::XTextContent > & rContent,
+ /// return value if this content doesn't support the section property
+ bool bDefault);
+
+ /**
+ * Export the configuration element for bibliography indices.
+ *
+ * (This is part of XMLSectionExport because all section- and
+ * index-related items are handled here.)
+ */
+ static void ExportBibliographyConfiguration(SvXMLExport& rExport);
+
+ /** export a heading for every level. This is used by master documents
+ * to not lose the heading information if master documents are exported
+ * without section contents
+ */
+ void ExportMasterDocHeadingDummies();
+
+
+private:
+
+ SvXMLExport& GetExport() { return rExport; }
+ XMLTextParagraphExport& GetParaExport() { return rParaExport; }
+
+ // export methods for section and index start:
+
+ /// export an index start element.
+ void ExportIndexStart(
+ const css::uno::Reference < css::text::XDocumentIndex > & rSection);
+
+ /// export an index header start element.
+ void ExportIndexHeaderStart(
+ const css::uno::Reference < css::text::XTextSection > & rSection);
+
+ /// export a proper section (and source elements)
+ void ExportRegularSectionStart(
+ const css::uno::Reference < css::text::XTextSection > & rSection);
+
+ /// export a table of content (and source element)
+ void ExportTableOfContentStart(
+ const css::uno::Reference < css::beans::XPropertySet > & rSection);
+
+ /// export a table index (and source element)
+ void ExportTableIndexStart(
+ const css::uno::Reference < css::beans::XPropertySet > & rSection);
+
+ /// export an object index (and source element)
+ void ExportObjectIndexStart(
+ const css::uno::Reference < css::beans::XPropertySet > & rSection);
+
+ /// export an illustration index (and source element)
+ void ExportIllustrationIndexStart(
+ const css::uno::Reference < css::beans::XPropertySet > & rSection);
+
+ /// export an alphabetical/keyword index (and source element)
+ void ExportAlphabeticalIndexStart(
+ const css::uno::Reference < css::beans::XPropertySet > & rSection);
+
+ /// export a user index (and source element)
+ void ExportUserIndexStart(
+ const css::uno::Reference < css::beans::XPropertySet > & rSection);
+
+ /// export the bibliography (and source element)
+ void ExportBibliographyStart(
+ const css::uno::Reference < css::beans::XPropertySet > & rIndex);
+
+ // helper methods:
+
+ /**
+ * If this section is an index, the index is written in the
+ * rIndex parameter. The return value is sal_True for all "special"
+ * sections.
+ *
+ * Thus we have:
+ * return sal_False: regular section
+ * return sal_True, xIndex is empty: index header section
+ * return sal_True, xIndex is set: index section */
+ static bool GetIndex(
+ const css::uno::Reference < css::text::XTextSection > & rSection,
+ css::uno::Reference < css::text::XDocumentIndex > & rIndex);
+
+ /// map service name to section type
+ static enum SectionTypeEnum MapSectionType(std::u16string_view rSectionName);
+
+ /**
+ * Export the index element start (for all index types).
+ *
+ * All additional attributes (usually none) for the index element
+ * should have been set at GetExport() before calling this method.
+ */
+ void ExportBaseIndexStart(
+ ::xmloff::token::XMLTokenEnum eElement,
+ const css::uno::Reference < css::beans::XPropertySet > & rSection);
+
+ /**
+ * Export the index source element (common for all index types).
+ *
+ * All additional attributes for the source element should have
+ * been set at the GetExport() before calling this method.
+ */
+ void ExportBaseIndexSource(
+ SectionTypeEnum eType, /// index type
+ const css::uno::Reference <
+ css::beans::XPropertySet > & rSection);
+
+ /**
+ * Export the index body (common for all index types).
+ */
+ void ExportBaseIndexBody(
+ SectionTypeEnum eType, /// index type
+ const css::uno::Reference < css::beans::XPropertySet > & rSection);
+
+
+ /**
+ * Helper method to export common attributes for table and
+ * illustration indices
+ */
+ void ExportTableAndIllustrationIndexSourceAttributes(
+ const css::uno::Reference < css::beans::XPropertySet > & rSection);
+
+ /// export one template for the specific index type
+ bool ExportIndexTemplate(
+ SectionTypeEnum eType, /// index type
+ sal_Int32 nLevel, /// outline level (if applicable)
+ const css::uno::Reference< css::beans::XPropertySet> & rPropSet,
+ const css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue> > & rValues);
+
+ /// export a single template element (e.g. span or tab-stop)
+ void ExportIndexTemplateElement(
+ SectionTypeEnum eType, //i90246, needed for ODF 1.0, 1.0 and 1.2 management
+ const css::uno::Sequence<
+ css::beans::PropertyValue> & rValues);
+
+ /// export level paragraph styles
+ void ExportLevelParagraphStyles(
+ css::uno::Reference< css::container::XIndexReplace> const & xStyles);
+
+
+ /// helper to export boolean properties
+ void ExportBoolean(
+ const css::uno::Reference<css::beans::XPropertySet> & rPropSet,
+ const OUString& sPropertyName,
+ enum ::xmloff::token::XMLTokenEnum eAttributeName,
+ bool bDefault,
+ bool bInvert = false);
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLSectionFootnoteConfigExport.cxx b/xmloff/source/text/XMLSectionFootnoteConfigExport.cxx
new file mode 100644
index 0000000000..6e1c063191
--- /dev/null
+++ b/xmloff/source/text/XMLSectionFootnoteConfigExport.cxx
@@ -0,0 +1,179 @@
+/* -*- 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 "XMLSectionFootnoteConfigExport.hxx"
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/xmlprmap.hxx>
+#include <com/sun/star/style/NumberingType.hpp>
+#include <xmloff/maptype.hxx>
+
+#include <xmloff/txtprmap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+
+#include <vector>
+
+
+using namespace ::xmloff::token;
+
+using ::std::vector;
+using css::style::NumberingType::ARABIC;
+
+
+void XMLSectionFootnoteConfigExport::exportXML(
+ SvXMLExport& rExport,
+ bool bEndnote,
+ const vector<XMLPropertyState> *pProperties,
+ sal_uInt32 nIdx,
+ const rtl::Reference<XMLPropertySetMapper> & rMapper)
+{
+ // store and initialize the values
+ bool bNumOwn = false;
+ bool bNumRestart = false;
+ sal_Int16 nNumRestartAt = 0;
+ sal_Int16 nNumberingType = ARABIC;
+ OUString sNumPrefix;
+ OUString sNumSuffix;
+ bool bEnd = false;
+
+ // find entries in property states vector
+ sal_uInt32 nCount = pProperties->size();
+ for(sal_uInt32 i = 0; i < nCount; i++)
+ {
+ const XMLPropertyState& rState = (*pProperties)[i];
+
+ sal_Int16 nContextId = rMapper->GetEntryContextId(rState.mnIndex);
+ if (!bEndnote)
+ {
+ switch (nContextId)
+ {
+ case CTF_SECTION_FOOTNOTE_NUM_OWN:
+ rState.maValue >>= bNumOwn;
+ break;
+ case CTF_SECTION_FOOTNOTE_NUM_RESTART:
+ rState.maValue >>= bNumRestart;
+ break;
+ case CTF_SECTION_FOOTNOTE_NUM_RESTART_AT:
+ rState.maValue >>= nNumRestartAt;
+ break;
+ case CTF_SECTION_FOOTNOTE_NUM_TYPE:
+ rState.maValue >>= nNumberingType;
+ break;
+ case CTF_SECTION_FOOTNOTE_NUM_PREFIX:
+ rState.maValue >>= sNumPrefix;
+ break;
+ case CTF_SECTION_FOOTNOTE_NUM_SUFFIX:
+ rState.maValue >>= sNumSuffix;
+ break;
+ case CTF_SECTION_FOOTNOTE_END:
+ SAL_WARN_IF( i != nIdx, "xmloff",
+ "received wrong property state index" );
+ rState.maValue >>= bEnd;
+ break;
+ }
+ }
+ else
+ {
+ switch (nContextId)
+ {
+ case CTF_SECTION_ENDNOTE_NUM_OWN:
+ rState.maValue >>= bNumOwn;
+ break;
+ case CTF_SECTION_ENDNOTE_NUM_RESTART:
+ rState.maValue >>= bNumRestart;
+ break;
+ case CTF_SECTION_ENDNOTE_NUM_RESTART_AT:
+ rState.maValue >>= nNumRestartAt;
+ break;
+ case CTF_SECTION_ENDNOTE_NUM_TYPE:
+ rState.maValue >>= nNumberingType;
+ break;
+ case CTF_SECTION_ENDNOTE_NUM_PREFIX:
+ rState.maValue >>= sNumPrefix;
+ break;
+ case CTF_SECTION_ENDNOTE_NUM_SUFFIX:
+ rState.maValue >>= sNumSuffix;
+ break;
+ case CTF_SECTION_ENDNOTE_END:
+ SAL_WARN_IF( i != nIdx, "xmloff",
+ "received wrong property state index" );
+ rState.maValue >>= bEnd;
+ break;
+ }
+ }
+ }
+
+ // we only make an element if we have an own footnote/endnote numbering
+ if (!bEnd)
+ return;
+
+ rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_NOTE_CLASS,
+ GetXMLToken( bEndnote ? XML_ENDNOTE
+ : XML_FOOTNOTE ) );
+ // start numbering
+ if (bNumRestart)
+ {
+ // restart number is stored as 0.., but interpreted as 1..
+ rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_START_VALUE,
+ OUString::number(nNumRestartAt+1));
+ }
+
+ if (bNumOwn)
+ {
+ // prefix and suffix
+ if (!sNumPrefix.isEmpty())
+ {
+ rExport.AddAttribute(XML_NAMESPACE_STYLE, XML_NUM_PREFIX,
+ sNumPrefix);
+ }
+ if (!sNumSuffix.isEmpty())
+ {
+ rExport.AddAttribute(XML_NAMESPACE_STYLE, XML_NUM_SUFFIX,
+ sNumSuffix);
+ }
+
+ // number type: num format
+ OUStringBuffer sBuf;
+ rExport.GetMM100UnitConverter().convertNumFormat( sBuf,
+ nNumberingType );
+ rExport.AddAttribute(XML_NAMESPACE_STYLE, XML_NUM_FORMAT,
+ sBuf.makeStringAndClear());
+
+ // and letter sync, if applicable
+ SvXMLUnitConverter::convertNumLetterSync(
+ sBuf, nNumberingType );
+ if (!sBuf.isEmpty())
+ {
+ rExport.AddAttribute(XML_NAMESPACE_STYLE,
+ XML_NUM_LETTER_SYNC,
+ sBuf.makeStringAndClear());
+ }
+ }
+
+ // and finally, the element
+ SvXMLElementExport rElem(rExport, XML_NAMESPACE_TEXT,
+ XML_NOTES_CONFIGURATION,
+ true, true);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLSectionFootnoteConfigExport.hxx b/xmloff/source/text/XMLSectionFootnoteConfigExport.hxx
new file mode 100644
index 0000000000..dcbf66c2e0
--- /dev/null
+++ b/xmloff/source/text/XMLSectionFootnoteConfigExport.hxx
@@ -0,0 +1,52 @@
+/* -*- 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 .
+ */
+
+
+#pragma once
+
+#include <sal/types.h>
+
+#include <vector>
+
+class SvXMLExport;
+class XMLPropertySetMapper;
+struct XMLPropertyState;
+namespace rtl {
+ template<class X> class Reference;
+}
+
+/**
+ * Export the footnote-/endnote-configuration element in section styles.
+ *
+ * Because this class contains only one method, and all information is
+ * available during that method call, we simply make it static.
+ */
+class XMLSectionFootnoteConfigExport
+{
+
+public:
+ static void exportXML(
+ SvXMLExport& rExport,
+ bool bEndnote,
+ const ::std::vector<XMLPropertyState> * pProperties,
+ sal_uInt32 nIdx,
+ const rtl::Reference<XMLPropertySetMapper> & rMapper); /// used only for debugging
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLSectionFootnoteConfigImport.cxx b/xmloff/source/text/XMLSectionFootnoteConfigImport.cxx
new file mode 100644
index 0000000000..113e7f2d22
--- /dev/null
+++ b/xmloff/source/text/XMLSectionFootnoteConfigImport.cxx
@@ -0,0 +1,170 @@
+/* -*- 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 "XMLSectionFootnoteConfigImport.hxx"
+
+#include <rtl/ustring.hxx>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/xml/sax/XAttributeList.hpp>
+#include <com/sun/star/style/NumberingType.hpp>
+#include <sal/log.hxx>
+#include <sax/tools/converter.hxx>
+#include <utility>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlprmap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/maptype.hxx>
+#include <xmloff/txtprmap.hxx>
+
+#include <vector>
+
+
+using namespace ::xmloff::token;
+using namespace ::com::sun::star::style;
+
+using ::std::vector;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+
+
+XMLSectionFootnoteConfigImport::XMLSectionFootnoteConfigImport(
+ SvXMLImport& rImport,
+ sal_Int32 /*nElement*/,
+ vector<XMLPropertyState> & rProps,
+ rtl::Reference<XMLPropertySetMapper> xMapperRef) :
+ SvXMLImportContext(rImport),
+ rProperties(rProps),
+ rMapper(std::move(xMapperRef))
+{
+}
+
+XMLSectionFootnoteConfigImport::~XMLSectionFootnoteConfigImport()
+{
+}
+
+void XMLSectionFootnoteConfigImport::startFastElement(
+ sal_Int32 /*nElement*/,
+ const Reference<css::xml::sax::XFastAttributeList> & xAttrList)
+{
+ bool bNumOwn = false;
+ bool bNumRestart = false;
+ bool bEndnote = false;
+ sal_Int16 nNumRestartAt = 0;
+ OUString sNumPrefix;
+ OUString sNumSuffix;
+ OUString sNumFormat;
+ OUString sNumLetterSync;
+
+ // iterate over xattribute list and fill values
+ for (auto &aIter : sax_fastparser::castToFastAttributeList(xAttrList))
+ {
+ switch(aIter.getToken())
+ {
+ case XML_ELEMENT(TEXT, XML_START_VALUE):
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertNumber(nTmp, aIter.toView()))
+ {
+ nNumRestartAt = static_cast< sal_Int16 >( nTmp ) - 1;
+ bNumRestart = true;
+ }
+ break;
+ }
+ case XML_ELEMENT(TEXT, XML_NOTE_CLASS):
+ {
+ if( IsXMLToken( aIter, XML_ENDNOTE ) )
+ bEndnote = true;
+ break;
+ }
+ case XML_ELEMENT(STYLE, XML_NUM_PREFIX):
+ {
+ sNumPrefix = aIter.toString();
+ bNumOwn = true;
+ break;
+ }
+ case XML_ELEMENT(STYLE, XML_NUM_SUFFIX):
+ {
+ sNumSuffix = aIter.toString();
+ bNumOwn = true;
+ break;
+ }
+ case XML_ELEMENT(STYLE, XML_NUM_FORMAT):
+ {
+ sNumFormat = aIter.toString();
+ bNumOwn = true;
+ break;
+ }
+ case XML_ELEMENT(STYLE, XML_NUM_LETTER_SYNC):
+ {
+ sNumLetterSync = aIter.toString();
+ bNumOwn = true;
+ break;
+ }
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+
+ // OK, now we have all values and can fill the XMLPropertyState vector
+
+ sal_Int32 nIndex = rMapper->FindEntryIndex( bEndnote ?
+ CTF_SECTION_ENDNOTE_NUM_OWN : CTF_SECTION_FOOTNOTE_NUM_OWN );
+ XMLPropertyState aNumOwn( nIndex, css::uno::Any(bNumOwn) );
+ rProperties.push_back( aNumOwn );
+
+ nIndex = rMapper->FindEntryIndex( bEndnote ?
+ CTF_SECTION_ENDNOTE_NUM_RESTART : CTF_SECTION_FOOTNOTE_NUM_RESTART );
+ XMLPropertyState aNumRestart( nIndex, css::uno::Any(bNumRestart) );
+ rProperties.push_back( aNumRestart );
+
+ nIndex = rMapper->FindEntryIndex( bEndnote ?
+ CTF_SECTION_ENDNOTE_NUM_RESTART_AT :
+ CTF_SECTION_FOOTNOTE_NUM_RESTART_AT );
+ XMLPropertyState aNumRestartAtState( nIndex, css::uno::Any(nNumRestartAt) );
+ rProperties.push_back( aNumRestartAtState );
+
+ sal_Int16 nNumType = NumberingType::ARABIC;
+ GetImport().GetMM100UnitConverter().convertNumFormat( nNumType,
+ sNumFormat,
+ sNumLetterSync );
+ nIndex = rMapper->FindEntryIndex( bEndnote ?
+ CTF_SECTION_ENDNOTE_NUM_TYPE : CTF_SECTION_FOOTNOTE_NUM_TYPE );
+ XMLPropertyState aNumFormatState( nIndex, css::uno::Any(nNumType) );
+ rProperties.push_back( aNumFormatState );
+
+ nIndex = rMapper->FindEntryIndex( bEndnote ?
+ CTF_SECTION_ENDNOTE_NUM_PREFIX : CTF_SECTION_FOOTNOTE_NUM_PREFIX );
+ XMLPropertyState aPrefixState( nIndex, css::uno::Any(sNumPrefix) );
+ rProperties.push_back( aPrefixState );
+
+ nIndex = rMapper->FindEntryIndex( bEndnote ?
+ CTF_SECTION_ENDNOTE_NUM_SUFFIX : CTF_SECTION_FOOTNOTE_NUM_SUFFIX );
+ XMLPropertyState aSuffixState( nIndex, css::uno::Any(sNumSuffix) );
+ rProperties.push_back( aSuffixState );
+
+ nIndex = rMapper->FindEntryIndex( bEndnote ?
+ CTF_SECTION_ENDNOTE_END : CTF_SECTION_FOOTNOTE_END );
+ XMLPropertyState aEndState( nIndex, css::uno::Any(true) ); // we're inside the element, so this is true
+ rProperties.push_back( aEndState );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLSectionFootnoteConfigImport.hxx b/xmloff/source/text/XMLSectionFootnoteConfigImport.hxx
new file mode 100644
index 0000000000..7a25690334
--- /dev/null
+++ b/xmloff/source/text/XMLSectionFootnoteConfigImport.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/.
+ *
+ * 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 .
+ */
+
+
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <rtl/ref.hxx>
+#include <vector>
+
+
+class SvXMLImport;
+struct XMLPropertyState;
+class XMLPropertySetMapper;
+namespace com::sun::star {
+ namespace uno { template<class X> class Reference; }
+ namespace xml::sax { class XAttributeList; }
+}
+
+
+/**
+ * Import the footnote-/endnote-configuration element in section styles.
+ */
+class XMLSectionFootnoteConfigImport : public SvXMLImportContext
+{
+ ::std::vector<XMLPropertyState> & rProperties;
+ rtl::Reference<XMLPropertySetMapper> rMapper;
+
+public:
+
+
+ XMLSectionFootnoteConfigImport(
+ SvXMLImport& rImport,
+ sal_Int32 nElement,
+ ::std::vector<XMLPropertyState> & rProperties,
+ rtl::Reference<XMLPropertySetMapper> xMapperRef);
+
+ virtual ~XMLSectionFootnoteConfigImport() override;
+
+ virtual void SAL_CALL startFastElement( sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& ) override;
+
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLSectionImportContext.cxx b/xmloff/source/text/XMLSectionImportContext.cxx
new file mode 100644
index 0000000000..554096c887
--- /dev/null
+++ b/xmloff/source/text/XMLSectionImportContext.cxx
@@ -0,0 +1,324 @@
+/* -*- 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 "XMLSectionImportContext.hxx"
+#include "XMLSectionSourceImportContext.hxx"
+#include "XMLSectionSourceDDEImportContext.hxx"
+#include <comphelper/base64.hxx>
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/txtimp.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/prstylei.hxx>
+#include <sal/log.hxx>
+#include <sax/tools/converter.hxx>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/text/XTextContent.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/text/ControlCharacter.hpp>
+
+
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::xml::sax::XFastAttributeList;
+using ::com::sun::star::lang::XMultiServiceFactory;
+using ::com::sun::star::container::XNamed;
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::text;
+using namespace ::xmloff::token;
+
+
+// section import: This one is fairly tricky due to a variety of
+// limits of the core or the API. The main problem is that if you
+// insert a section within another section, you can't move the cursor
+// between the ends of the inner and the enclosing section. To avoid
+// these problems, additional markers are first inserted and later deleted.
+XMLSectionImportContext::XMLSectionImportContext( SvXMLImport& rImport )
+: SvXMLImportContext(rImport)
+, bProtect(false)
+, bCondOK(false)
+, bIsVisible(true)
+, bValid(false)
+, bSequenceOK(false)
+, bIsCurrentlyVisible(true)
+, bIsCurrentlyVisibleOK(false)
+, bHasContent(false)
+{
+}
+
+XMLSectionImportContext::~XMLSectionImportContext()
+{
+}
+
+void XMLSectionImportContext::startFastElement( sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ // process attributes
+ ProcessAttributes(xAttrList);
+
+ // process index headers:
+ bool bIsIndexHeader = (nElement & TOKEN_MASK) == XML_INDEX_TITLE;
+ if (bIsIndexHeader)
+ {
+ bValid = true;
+ }
+
+ rtl::Reference<XMLTextImportHelper> rHelper = GetImport().GetTextImport();
+
+ // valid?
+ if (!bValid)
+ return;
+
+ // create text section (as XPropertySet)
+ Reference<XMultiServiceFactory> xFactory(
+ GetImport().GetModel(),UNO_QUERY);
+ if (!xFactory.is())
+ return;
+
+ Reference<XInterface> xIfc =
+ xFactory->createInstance( bIsIndexHeader ? OUString("com.sun.star.text.IndexHeaderSection")
+ : OUString("com.sun.star.text.TextSection") );
+ if (!xIfc.is())
+ return;
+
+ Reference<XPropertySet> xPropSet(xIfc, UNO_QUERY);
+
+ // save PropertySet (for CreateChildContext)
+ xSectionPropertySet = xPropSet;
+
+ // name
+ Reference<XNamed> xNamed(xPropSet, UNO_QUERY);
+ xNamed->setName(sName);
+
+ // stylename?
+ if (!sStyleName.isEmpty())
+ {
+ XMLPropStyleContext* pStyle = rHelper->
+ FindSectionStyle(sStyleName);
+
+ if (pStyle != nullptr)
+ {
+ pStyle->FillPropertySet( xPropSet );
+ }
+ }
+
+ // IsVisible and condition (not for index headers)
+ if (! bIsIndexHeader)
+ {
+ xPropSet->setPropertyValue( "IsVisible", Any(bIsVisible) );
+
+ // #97450# hidden sections must be hidden on reload
+ // For backwards compatibility, set flag only if it is
+ // present
+ if( bIsCurrentlyVisibleOK )
+ {
+ xPropSet->setPropertyValue( "IsCurrentlyVisible", Any(bIsCurrentlyVisible));
+ }
+
+ if (bCondOK)
+ {
+ xPropSet->setPropertyValue( "Condition", Any(sCond) );
+ }
+ }
+
+ // password (only for regular sections)
+ if ( bSequenceOK &&
+ (nElement & TOKEN_MASK) == XML_SECTION )
+ {
+ xPropSet->setPropertyValue("ProtectionKey", Any(aSequence));
+ }
+
+ // protection
+ xPropSet->setPropertyValue( "IsProtected", Any(bProtect) );
+
+ // insert marker, <paragraph>, marker; then insert
+ // section over the first marker character, and delete the
+ // last paragraph (and marker) when closing a section.
+ Reference<XTextRange> xStart =
+ rHelper->GetCursor()->getStart();
+#ifndef DBG_UTIL
+ OUString sMarkerString(" ");
+#else
+ OUString sMarkerString("X");
+#endif
+ rHelper->InsertString(sMarkerString);
+ rHelper->InsertControlCharacter(
+ ControlCharacter::APPEND_PARAGRAPH );
+ rHelper->InsertString(sMarkerString);
+
+ // select first marker
+ rHelper->GetCursor()->gotoRange(xStart, false);
+ rHelper->GetCursor()->goRight(1, true);
+
+ // convert section to XTextContent
+ Reference<XTextContent> xTextContent(xSectionPropertySet,
+ UNO_QUERY);
+
+ // and insert (over marker)
+ rHelper->GetText()->insertTextContent(
+ rHelper->GetCursorAsRange(), xTextContent, true );
+
+ // and delete first marker (in section)
+ rHelper->GetText()->insertString(
+ rHelper->GetCursorAsRange(), "", true);
+
+ // finally, check for redlines that should start at
+ // the section start node
+ rHelper->RedlineAdjustStartNodeCursor(); // start ???
+
+ // xml:id for RDF metadata
+ GetImport().SetXmlId(xIfc, sXmlId);
+}
+
+void XMLSectionImportContext::ProcessAttributes(
+ const Reference<XFastAttributeList> & xAttrList )
+{
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(XML, XML_ID):
+ sXmlId = aIter.toString();
+ break;
+ case XML_ELEMENT(TEXT, XML_STYLE_NAME):
+ sStyleName = aIter.toString();
+ break;
+ case XML_ELEMENT(TEXT, XML_NAME):
+ sName = aIter.toString();
+ bValid = true;
+ break;
+ case XML_ELEMENT(TEXT, XML_CONDITION):
+ {
+ OUString sValue = aIter.toString();
+ OUString sTmp;
+ sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
+ GetKeyByAttrValueQName(sValue, &sTmp);
+ if( XML_NAMESPACE_OOOW == nPrefix )
+ {
+ sCond = sTmp;
+ bCondOK = true;
+ }
+ else
+ sCond = sValue;
+ }
+ break;
+ case XML_ELEMENT(TEXT, XML_DISPLAY):
+ if (IsXMLToken(aIter, XML_TRUE))
+ {
+ bIsVisible = true;
+ }
+ else if ( IsXMLToken(aIter, XML_NONE) ||
+ IsXMLToken(aIter, XML_CONDITION) )
+ {
+ bIsVisible = false;
+ }
+ // else: ignore
+ break;
+ case XML_ELEMENT(TEXT, XML_IS_HIDDEN):
+ {
+ bool bTmp(false);
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bIsCurrentlyVisible = !bTmp;
+ bIsCurrentlyVisibleOK = true;
+ }
+ }
+ break;
+ case XML_ELEMENT(TEXT, XML_PROTECTION_KEY):
+ ::comphelper::Base64::decode(aSequence, aIter.toString());
+ bSequenceOK = true;
+ break;
+ case XML_ELEMENT(TEXT, XML_PROTECTED):
+ // compatibility with SRC629 (or earlier) versions
+ case XML_ELEMENT(TEXT, XML_PROTECT):
+ {
+ bool bTmp(false);
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bProtect = bTmp;
+ }
+ break;
+ }
+ default:
+ // ignore
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ break;
+ }
+ }
+}
+
+void XMLSectionImportContext::endFastElement(sal_Int32 )
+{
+ // get rid of last paragraph
+ // (unless it's the only paragraph in the section)
+ rtl::Reference<XMLTextImportHelper> rHelper = GetImport().GetTextImport();
+ rHelper->GetCursor()->goRight(1, false);
+ if (bHasContent)
+ {
+ rHelper->GetCursor()->goLeft(1, true);
+ rHelper->GetText()->insertString(rHelper->GetCursorAsRange(),
+ "", true);
+ }
+
+ // and delete second marker
+ rHelper->GetCursor()->goRight(1, true);
+ rHelper->GetText()->insertString(rHelper->GetCursorAsRange(),
+ "", true);
+
+ // check for redlines to our endnode
+ rHelper->RedlineAdjustStartNodeCursor();
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLSectionImportContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ // section-source (-dde) elements
+ if ( nElement == XML_ELEMENT(TEXT, XML_SECTION_SOURCE) )
+ {
+ return new XMLSectionSourceImportContext(GetImport(),
+ xSectionPropertySet);
+ }
+ else if ( nElement == XML_ELEMENT(OFFICE, XML_DDE_SOURCE) )
+ {
+ return new XMLSectionSourceDDEImportContext(GetImport(),
+ xSectionPropertySet);
+ }
+ else
+ {
+ // otherwise: text context
+ auto pContext = GetImport().GetTextImport()->CreateTextChildContext(
+ GetImport(), nElement, xAttrList, XMLTextType::Section );
+
+ // if that fails, default context
+ if (pContext)
+ bHasContent = true;
+ else
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ return pContext;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLSectionImportContext.hxx b/xmloff/source/text/XMLSectionImportContext.hxx
new file mode 100644
index 0000000000..83f40d05eb
--- /dev/null
+++ b/xmloff/source/text/XMLSectionImportContext.hxx
@@ -0,0 +1,80 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/Sequence.h>
+
+namespace com::sun::star {
+ namespace text { class XTextRange; }
+ namespace beans { class XPropertySet; }
+ namespace xml::sax { class XAttributeList; }
+}
+
+
+/**
+ * Import text sections.
+ *
+ * This context may *also* be used for index header sections. The
+ * differentiates its behaviour based on GetLocalName().
+ */
+class XMLSectionImportContext final : public SvXMLImportContext
+{
+ /// TextSection (as XPropertySet) for passing down to data source elements
+ css::uno::Reference<css::beans::XPropertySet> xSectionPropertySet;
+
+ OUString sXmlId;
+ OUString sStyleName;
+ OUString sName;
+ OUString sCond;
+ css::uno::Sequence<sal_Int8> aSequence;
+ bool bProtect;
+ bool bCondOK;
+ bool bIsVisible;
+ bool bValid;
+ bool bSequenceOK;
+ bool bIsCurrentlyVisible;
+ bool bIsCurrentlyVisibleOK;
+
+ bool bHasContent;
+
+public:
+
+ XMLSectionImportContext( SvXMLImport& rImport );
+
+ virtual ~XMLSectionImportContext() override;
+
+private:
+
+ virtual void SAL_CALL startFastElement( sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+
+ void ProcessAttributes(
+ const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList );
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLSectionSourceDDEImportContext.cxx b/xmloff/source/text/XMLSectionSourceDDEImportContext.cxx
new file mode 100644
index 0000000000..e2d8f1ce84
--- /dev/null
+++ b/xmloff/source/text/XMLSectionSourceDDEImportContext.cxx
@@ -0,0 +1,108 @@
+/* -*- 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 "XMLSectionSourceDDEImportContext.hxx"
+#include "XMLSectionImportContext.hxx"
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <sax/tools/converter.hxx>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+#include <tools/debug.hxx>
+
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::beans::XMultiPropertySet;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::xml::sax::XFastAttributeList;
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::text;
+using namespace ::xmloff::token;
+
+XMLSectionSourceDDEImportContext::XMLSectionSourceDDEImportContext(
+ SvXMLImport& rImport,
+ Reference<XPropertySet> & rSectPropSet) :
+ SvXMLImportContext(rImport),
+ rSectionPropertySet(rSectPropSet)
+{
+}
+
+XMLSectionSourceDDEImportContext::~XMLSectionSourceDDEImportContext()
+{
+}
+
+void XMLSectionSourceDDEImportContext::startFastElement(sal_Int32 /*nElement*/,
+ const Reference<XFastAttributeList> & xAttrList)
+{
+ OUString sApplication;
+ OUString sTopic;
+ OUString sItem;
+ bool bAutomaticUpdate = false;
+
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
+ {
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(OFFICE, XML_DDE_APPLICATION):
+ sApplication = aIter.toString();
+ break;
+ case XML_ELEMENT(OFFICE, XML_DDE_TOPIC):
+ sTopic = aIter.toString();
+ break;
+ case XML_ELEMENT(OFFICE, XML_DDE_ITEM):
+ sItem = aIter.toString();
+ break;
+ case XML_ELEMENT(OFFICE, XML_AUTOMATIC_UPDATE):
+ {
+ bool bTmp(false);
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bAutomaticUpdate = bTmp;
+ }
+ break;
+ }
+ default:
+ ; // ignore
+ break;
+ }
+ }
+
+ // DDE not supported on all platforms; query property first
+ if (!rSectionPropertySet->getPropertySetInfo()->
+ hasPropertyByName("DDECommandFile"))
+ return;
+
+ // use multi property set to force single update of connection #83654#
+ Sequence<OUString> aNames { "DDECommandFile", "DDECommandType", "DDECommandElement", "IsAutomaticUpdate" };
+ Sequence<Any> aValues { Any(sApplication), Any(sTopic), Any(sItem), Any(bAutomaticUpdate) };
+
+ Reference<XMultiPropertySet> rMultiPropSet(rSectionPropertySet,
+ UNO_QUERY);
+ DBG_ASSERT(rMultiPropSet.is(), "we'd really like a XMultiPropertySet");
+ if (rMultiPropSet.is())
+ rMultiPropSet->setPropertyValues(aNames, aValues);
+ // else: ignore
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLSectionSourceDDEImportContext.hxx b/xmloff/source/text/XMLSectionSourceDDEImportContext.hxx
new file mode 100644
index 0000000000..31726f0982
--- /dev/null
+++ b/xmloff/source/text/XMLSectionSourceDDEImportContext.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <com/sun/star/uno/Reference.h>
+
+namespace com::sun::star {
+ namespace beans { class XPropertySet; }
+ namespace xml::sax { class XAttributeList; }
+}
+
+class XMLSectionSourceDDEImportContext : public SvXMLImportContext
+{
+ css::uno::Reference<css::beans::XPropertySet> & rSectionPropertySet;
+
+public:
+
+ XMLSectionSourceDDEImportContext(
+ SvXMLImport& rImport,
+ css::uno::Reference<css::beans::XPropertySet> & rSectPropSet);
+
+ virtual ~XMLSectionSourceDDEImportContext() override;
+
+protected:
+
+ virtual void SAL_CALL startFastElement(sal_Int32 nElement,
+ const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLSectionSourceImportContext.cxx b/xmloff/source/text/XMLSectionSourceImportContext.cxx
new file mode 100644
index 0000000000..e8f12a85a2
--- /dev/null
+++ b/xmloff/source/text/XMLSectionSourceImportContext.cxx
@@ -0,0 +1,97 @@
+/* -*- 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 "XMLSectionSourceImportContext.hxx"
+#include "XMLSectionImportContext.hxx"
+#include <com/sun/star/text/SectionFileLink.hpp>
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::uno::Reference;
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::text;
+using namespace ::xmloff::token;
+
+
+XMLSectionSourceImportContext::XMLSectionSourceImportContext(
+ SvXMLImport& rImport,
+ Reference<XPropertySet> & rSectPropSet) :
+ SvXMLImportContext(rImport),
+ rSectionPropertySet(rSectPropSet)
+{
+}
+
+XMLSectionSourceImportContext::~XMLSectionSourceImportContext()
+{
+}
+
+void XMLSectionSourceImportContext::startFastElement( sal_Int32 /*nElement*/,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ OUString sURL;
+ OUString sFilterName;
+ OUString sSectionName;
+
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ OUString sValue = aIter.toString();
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(XLINK, XML_HREF):
+ sURL = sValue;
+ break;
+
+ case XML_ELEMENT(TEXT, XML_FILTER_NAME):
+ sFilterName = sValue;
+ break;
+
+ case XML_ELEMENT(TEXT, XML_SECTION_NAME):
+ sSectionName = sValue;
+ break;
+
+ default:
+ ; // ignore
+ break;
+ }
+ }
+
+ if (!sURL.isEmpty() || !sFilterName.isEmpty())
+ {
+ SectionFileLink aFileLink;
+ aFileLink.FileURL = GetImport().GetAbsoluteReference( sURL );
+ aFileLink.FilterName = sFilterName;
+
+ rSectionPropertySet->setPropertyValue("FileLink", Any(aFileLink));
+ }
+
+ if (!sSectionName.isEmpty())
+ {
+ rSectionPropertySet->setPropertyValue("LinkRegion", Any(sSectionName));
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLSectionSourceImportContext.hxx b/xmloff/source/text/XMLSectionSourceImportContext.hxx
new file mode 100644
index 0000000000..f47dddcbb7
--- /dev/null
+++ b/xmloff/source/text/XMLSectionSourceImportContext.hxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <com/sun/star/uno/Reference.h>
+
+namespace com::sun::star {
+ namespace beans { class XPropertySet; }
+ namespace xml::sax { class XAttributeList; }
+}
+
+class XMLSectionSourceImportContext final : public SvXMLImportContext
+{
+ css::uno::Reference<css::beans::XPropertySet> & rSectionPropertySet;
+
+public:
+
+ XMLSectionSourceImportContext(
+ SvXMLImport& rImport,
+ css::uno::Reference<css::beans::XPropertySet> & rSectPropSet);
+
+ virtual ~XMLSectionSourceImportContext() override;
+
+ virtual void SAL_CALL startFastElement( sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLStringBufferImportContext.cxx b/xmloff/source/text/XMLStringBufferImportContext.cxx
new file mode 100644
index 0000000000..254994a3ad
--- /dev/null
+++ b/xmloff/source/text/XMLStringBufferImportContext.cxx
@@ -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/.
+ *
+ * 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 <XMLStringBufferImportContext.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlnamespace.hxx>
+
+
+using ::com::sun::star::uno::Reference;
+using ::xmloff::token::XML_P;
+
+XMLStringBufferImportContext::XMLStringBufferImportContext(
+ SvXMLImport& rImport,
+ OUStringBuffer& rBuffer) :
+ SvXMLImportContext(rImport),
+ rTextBuffer(rBuffer)
+{
+}
+
+XMLStringBufferImportContext::~XMLStringBufferImportContext()
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLStringBufferImportContext::createFastChildContext(
+ sal_Int32 /*nElement*/, const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/ )
+{
+ return new XMLStringBufferImportContext(GetImport(), rTextBuffer);
+}
+
+void XMLStringBufferImportContext::characters(const OUString& rChars )
+{
+ rTextBuffer.append(rChars);
+}
+
+void XMLStringBufferImportContext::endFastElement(sal_Int32 nElement)
+{
+ // add return for paragraph elements
+ if ( nElement == XML_ELEMENT(TEXT, XML_P) || nElement == XML_ELEMENT(LO_EXT, XML_P))
+ {
+ rTextBuffer.append(u'\x000a');
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTextCharStyleNamesElementExport.cxx b/xmloff/source/text/XMLTextCharStyleNamesElementExport.cxx
new file mode 100644
index 0000000000..4cdbbc2b05
--- /dev/null
+++ b/xmloff/source/text/XMLTextCharStyleNamesElementExport.cxx
@@ -0,0 +1,75 @@
+/* -*- 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 "XMLTextCharStyleNamesElementExport.hxx"
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <osl/diagnose.h>
+
+namespace com::sun::star::beans { class XPropertySet; }
+
+using namespace ::com::sun::star::uno;
+using ::com::sun::star::beans::XPropertySet;
+using namespace ::xmloff::token;
+
+XMLTextCharStyleNamesElementExport::XMLTextCharStyleNamesElementExport(
+ SvXMLExport& rExp,
+ bool bDoSth,
+ bool bAllStyles,
+ const Reference < XPropertySet > & rPropSet,
+ const OUString& rPropName ) :
+ rExport( rExp ),
+ nCount( 0 )
+{
+ if( !bDoSth )
+ return;
+
+ Any aAny = rPropSet->getPropertyValue( rPropName );
+ Sequence < OUString > aNames;
+ if( !(aAny >>= aNames) )
+ return;
+
+ nCount = aNames.getLength();
+ OSL_ENSURE( nCount > 0, "no char style found" );
+ if ( bAllStyles ) ++nCount;
+ if( nCount > 1 )
+ {
+ aName = rExport.GetNamespaceMap().GetQNameByKey(
+ XML_NAMESPACE_TEXT, GetXMLToken(XML_SPAN) );
+ for( sal_Int32 i = 1; i < nCount; ++i )
+ {
+ rExport.AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
+ rExport.EncodeStyleName( aNames[i - 1] ) );
+ rExport.StartElement( aName, false );
+ }
+ }
+}
+
+XMLTextCharStyleNamesElementExport::~XMLTextCharStyleNamesElementExport()
+{
+ if( nCount > 1 )
+ {
+ for( sal_Int32 i = 1; i < nCount; ++i )
+ rExport.EndElement( aName, false );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTextCharStyleNamesElementExport.hxx b/xmloff/source/text/XMLTextCharStyleNamesElementExport.hxx
new file mode 100644
index 0000000000..0eaad5d33b
--- /dev/null
+++ b/xmloff/source/text/XMLTextCharStyleNamesElementExport.hxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * 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 .
+ */
+#pragma once
+
+#include <rtl/ustring.hxx>
+#include <com/sun/star/uno/Reference.hxx>
+
+
+namespace com::sun::star {
+ namespace beans { class XPropertySet; }
+}
+
+class SvXMLExport;
+
+class XMLTextCharStyleNamesElementExport
+{
+ SvXMLExport& rExport;
+ OUString aName;
+ sal_Int32 nCount;
+
+public:
+
+ XMLTextCharStyleNamesElementExport(
+ SvXMLExport& rExp, bool bDoSomething, bool bAllStyles,
+ const css::uno::Reference < css::beans::XPropertySet > & rPropSet,
+ const OUString& rPropName );
+ ~XMLTextCharStyleNamesElementExport();
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTextColumnsContext.cxx b/xmloff/source/text/XMLTextColumnsContext.cxx
new file mode 100644
index 0000000000..09c6ac1eb9
--- /dev/null
+++ b/xmloff/source/text/XMLTextColumnsContext.cxx
@@ -0,0 +1,369 @@
+/* -*- 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 <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/text/XTextColumns.hpp>
+#include <com/sun/star/text/TextColumn.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/style/VerticalAlignment.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <sal/log.hxx>
+#include <sax/tools/converter.hxx>
+#include <xmloff/xmltkmap.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlement.hxx>
+#include <XMLTextColumnsContext.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::style;
+using namespace ::com::sun::star::beans;
+using namespace ::xmloff::token;
+
+SvXMLEnumMapEntry<sal_Int8> const pXML_Sep_Style_Enum[] =
+{
+ { XML_NONE, 0 },
+ { XML_SOLID, 1 },
+ { XML_DOTTED, 2 },
+ { XML_DASHED, 3 },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+SvXMLEnumMapEntry<VerticalAlignment> const pXML_Sep_Align_Enum[] =
+{
+ { XML_TOP, VerticalAlignment_TOP },
+ { XML_MIDDLE, VerticalAlignment_MIDDLE },
+ { XML_BOTTOM, VerticalAlignment_BOTTOM },
+ { XML_TOKEN_INVALID, VerticalAlignment(0) }
+};
+
+class XMLTextColumnContext_Impl: public SvXMLImportContext
+{
+ text::TextColumn aColumn;
+
+public:
+
+ XMLTextColumnContext_Impl( SvXMLImport& rImport, sal_Int32 nElement,
+ const uno::Reference<
+ xml::sax::XFastAttributeList > & xAttrList );
+
+ text::TextColumn& getTextColumn() { return aColumn; }
+};
+
+
+XMLTextColumnContext_Impl::XMLTextColumnContext_Impl(
+ SvXMLImport& rImport, sal_Int32 /*nElement*/,
+ const uno::Reference<
+ xml::sax::XFastAttributeList > & xAttrList ) :
+ SvXMLImportContext( rImport )
+{
+ aColumn.Width = 0;
+ aColumn.LeftMargin = 0;
+ aColumn.RightMargin = 0;
+
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ sal_Int32 nVal;
+ switch( aIter.getToken() )
+ {
+ case XML_ELEMENT(STYLE, XML_REL_WIDTH):
+ {
+ size_t nPos = aIter.toView().find( '*' );
+ if( nPos != std::string_view::npos && static_cast<sal_Int32>(nPos+1) == aIter.getLength() )
+ {
+ if (::sax::Converter::convertNumber(
+ nVal,
+ aIter.toView().substr(0, nPos),
+ 0, USHRT_MAX))
+ aColumn.Width = nVal;
+ }
+ }
+ break;
+ case XML_ELEMENT(FO, XML_START_INDENT):
+ case XML_ELEMENT(FO_COMPAT, XML_START_INDENT):
+ if( GetImport().GetMM100UnitConverter().
+ convertMeasureToCore( nVal, aIter.toView() ) )
+ aColumn.LeftMargin = nVal;
+ break;
+ case XML_ELEMENT(FO, XML_END_INDENT):
+ case XML_ELEMENT(FO_COMPAT, XML_END_INDENT):
+ if( GetImport().GetMM100UnitConverter().
+ convertMeasureToCore( nVal, aIter.toView() ) )
+ aColumn.RightMargin = nVal;
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ break;
+ }
+ }
+}
+
+class XMLTextColumnSepContext_Impl: public SvXMLImportContext
+{
+ sal_Int32 nWidth;
+ sal_Int32 nColor;
+ sal_Int8 nHeight;
+ sal_Int8 nStyle;
+ VerticalAlignment eVertAlign;
+
+public:
+
+ XMLTextColumnSepContext_Impl( SvXMLImport& rImport, sal_Int32 nElement,
+ const uno::Reference<
+ xml::sax::XFastAttributeList > & xAttrList );
+
+ sal_Int32 GetWidth() const { return nWidth; }
+ sal_Int32 GetColor() const { return nColor; }
+ sal_Int8 GetHeight() const { return nHeight; }
+ sal_Int8 GetStyle() const { return nStyle; }
+ VerticalAlignment GetVertAlign() const { return eVertAlign; }
+};
+
+
+XMLTextColumnSepContext_Impl::XMLTextColumnSepContext_Impl(
+ SvXMLImport& rImport, sal_Int32 /*nElement*/,
+ const uno::Reference<
+ xml::sax::XFastAttributeList > & xAttrList) :
+ SvXMLImportContext( rImport ),
+ nWidth( 2 ),
+ nColor( 0 ),
+ nHeight( 100 ),
+ nStyle( 1 ),
+ eVertAlign( VerticalAlignment_TOP )
+{
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
+ {
+ sal_Int32 nVal;
+ switch( aIter.getToken() )
+ {
+ case XML_ELEMENT(STYLE, XML_WIDTH):
+ if( GetImport().GetMM100UnitConverter().
+ convertMeasureToCore( nVal, aIter.toView() ) )
+ nWidth = nVal;
+ break;
+ case XML_ELEMENT(STYLE, XML_HEIGHT):
+ if (::sax::Converter::convertPercent( nVal, aIter.toView() ) &&
+ nVal >=1 && nVal <= 100 )
+ nHeight = static_cast<sal_Int8>(nVal);
+ break;
+ case XML_ELEMENT(STYLE, XML_COLOR):
+ ::sax::Converter::convertColor( nColor, aIter.toView() );
+ break;
+ case XML_ELEMENT(STYLE, XML_VERTICAL_ALIGN):
+ SvXMLUnitConverter::convertEnum( eVertAlign, aIter.toView(),
+ pXML_Sep_Align_Enum );
+ break;
+ case XML_ELEMENT(STYLE, XML_STYLE):
+ SvXMLUnitConverter::convertEnum( nStyle, aIter.toView(),
+ pXML_Sep_Style_Enum );
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+}
+
+constexpr OUStringLiteral gsSeparatorLineIsOn(u"SeparatorLineIsOn");
+constexpr OUStringLiteral gsSeparatorLineWidth(u"SeparatorLineWidth");
+constexpr OUStringLiteral gsSeparatorLineColor(u"SeparatorLineColor");
+constexpr OUStringLiteral gsSeparatorLineRelativeHeight(u"SeparatorLineRelativeHeight");
+constexpr OUStringLiteral gsSeparatorLineVerticalAlignment(u"SeparatorLineVerticalAlignment");
+constexpr OUStringLiteral gsAutomaticDistance(u"AutomaticDistance");
+constexpr OUStringLiteral gsSeparatorLineStyle(u"SeparatorLineStyle");
+
+XMLTextColumnsContext::XMLTextColumnsContext(
+ SvXMLImport& rImport, sal_Int32 nElement,
+ const Reference< xml::sax::XFastAttributeList >& xAttrList,
+ const XMLPropertyState& rProp,
+ ::std::vector< XMLPropertyState > &rProps )
+: XMLElementPropertyContext( rImport, nElement, rProp, rProps )
+, nCount( 0 )
+, bAutomatic( false )
+, nAutomaticDistance( 0 )
+{
+ sal_Int32 nVal;
+ for (auto &aIter : sax_fastparser::castToFastAttributeList(xAttrList))
+ {
+ switch(aIter.getToken())
+ {
+ case XML_ELEMENT(FO, XML_COLUMN_COUNT):
+ case XML_ELEMENT(FO_COMPAT, XML_COLUMN_COUNT):
+ if(::sax::Converter::convertNumber( nVal, aIter.toView(), 0, SHRT_MAX ))
+ nCount = static_cast<sal_Int16>(nVal);
+ break;
+ case XML_ELEMENT(FO, XML_COLUMN_GAP):
+ case XML_ELEMENT(FO_COMPAT, XML_COLUMN_GAP):
+ {
+ bAutomatic = GetImport().GetMM100UnitConverter().
+ convertMeasureToCore( nAutomaticDistance, aIter.toView() );
+ break;
+ }
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTextColumnsContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ if( nElement == XML_ELEMENT(STYLE, XML_COLUMN) )
+ {
+ const rtl::Reference<XMLTextColumnContext_Impl> xColumn{
+ new XMLTextColumnContext_Impl( GetImport(), nElement, xAttrList )};
+
+ // add new tabstop to array of tabstops
+ maColumns.push_back( xColumn );
+
+ return xColumn;
+ }
+ else if( nElement == XML_ELEMENT(STYLE, XML_COLUMN_SEP) )
+ {
+ mxColumnSep.set(
+ new XMLTextColumnSepContext_Impl( GetImport(), nElement, xAttrList ));
+
+ return mxColumnSep;
+ }
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ return nullptr;
+}
+
+void XMLTextColumnsContext::endFastElement(sal_Int32 nElement )
+{
+ Reference<XMultiServiceFactory> xFactory(GetImport().GetModel(),UNO_QUERY);
+ if( !xFactory.is() )
+ return;
+
+ Reference<XInterface> xIfc = xFactory->createInstance("com.sun.star.text.TextColumns");
+ if( !xIfc.is() )
+ return;
+
+ Reference< XTextColumns > xColumns( xIfc, UNO_QUERY );
+ if ( 0 == nCount )
+ {
+ // zero columns = no columns -> 1 column
+ xColumns->setColumnCount( 1 );
+ }
+ else if( !bAutomatic &&
+ maColumns.size() == static_cast<sal_uInt16>(nCount) )
+ {
+ // if we have column descriptions, one per column, and we don't use
+ // automatic width, then set the column widths
+
+ sal_Int32 nRelWidth = 0;
+ sal_uInt16 nColumnsWithWidth = 0;
+ sal_Int16 i;
+
+ for( i = 0; i < nCount; i++ )
+ {
+ const TextColumn& rColumn =
+ maColumns[static_cast<sal_uInt16>(i)]->getTextColumn();
+ if( rColumn.Width > 0 )
+ {
+ nRelWidth += rColumn.Width;
+ nColumnsWithWidth++;
+ }
+ }
+ if( nColumnsWithWidth < nCount )
+ {
+ sal_Int32 nColWidth = 0==nRelWidth
+ ? USHRT_MAX / nCount
+ : nRelWidth / nColumnsWithWidth;
+
+ for( i=0; i < nCount; i++ )
+ {
+ TextColumn& rColumn =
+ maColumns[static_cast<sal_uInt16>(i)]->getTextColumn();
+ if( rColumn.Width == 0 )
+ {
+ rColumn.Width = nColWidth;
+ nRelWidth += rColumn.Width;
+ if( 0 == --nColumnsWithWidth )
+ break;
+ }
+ }
+ }
+
+ Sequence< TextColumn > aColumns( static_cast<sal_Int32>(nCount) );
+ TextColumn *pTextColumns = aColumns.getArray();
+ for( i=0; i < nCount; i++ )
+ *pTextColumns++ = maColumns[static_cast<sal_uInt16>(i)]->getTextColumn();
+
+ xColumns->setColumns( aColumns );
+ }
+ else
+ {
+ // only set column count (and let the columns be distributed
+ // automatically)
+
+ xColumns->setColumnCount( nCount );
+ }
+
+ Reference < XPropertySet > xPropSet( xColumns, UNO_QUERY );
+ if( xPropSet.is() )
+ {
+ bool bOn = mxColumnSep != nullptr;
+
+ xPropSet->setPropertyValue( gsSeparatorLineIsOn, Any(bOn) );
+
+ if( mxColumnSep.is() )
+ {
+ if( mxColumnSep->GetWidth() )
+ {
+ xPropSet->setPropertyValue( gsSeparatorLineWidth, Any(mxColumnSep->GetWidth()) );
+ }
+ if( mxColumnSep->GetHeight() )
+ {
+ xPropSet->setPropertyValue( gsSeparatorLineRelativeHeight,
+ Any(mxColumnSep->GetHeight()) );
+ }
+ if ( mxColumnSep->GetStyle() )
+ {
+ xPropSet->setPropertyValue( gsSeparatorLineStyle, Any(mxColumnSep->GetStyle()) );
+ }
+
+ xPropSet->setPropertyValue( gsSeparatorLineColor, Any(mxColumnSep->GetColor()) );
+
+ xPropSet->setPropertyValue( gsSeparatorLineVerticalAlignment, Any(mxColumnSep->GetVertAlign()) );
+ }
+
+ // handle 'automatic columns': column distance
+ if( bAutomatic )
+ {
+ xPropSet->setPropertyValue( gsAutomaticDistance, Any(nAutomaticDistance) );
+ }
+ }
+
+ aProp.maValue <<= xColumns;
+
+ SetInsert( true );
+ XMLElementPropertyContext::endFastElement(nElement);
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTextColumnsExport.cxx b/xmloff/source/text/XMLTextColumnsExport.cxx
new file mode 100644
index 0000000000..ec80f2ed90
--- /dev/null
+++ b/xmloff/source/text/XMLTextColumnsExport.cxx
@@ -0,0 +1,196 @@
+/* -*- 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 <o3tl/any.hxx>
+#include <rtl/ustrbuf.hxx>
+
+
+#include <com/sun/star/text/XTextColumns.hpp>
+#include <com/sun/star/text/ColumnSeparatorStyle.hpp>
+#include <com/sun/star/text/TextColumn.hpp>
+#include <com/sun/star/style/VerticalAlignment.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include <sax/tools/converter.hxx>
+
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <XMLTextColumnsExport.hxx>
+
+using namespace ::com::sun::star::style;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::xmloff::token;
+
+
+constexpr OUStringLiteral gsSeparatorLineIsOn(u"SeparatorLineIsOn");
+constexpr OUStringLiteral gsSeparatorLineWidth(u"SeparatorLineWidth");
+constexpr OUStringLiteral gsSeparatorLineColor(u"SeparatorLineColor");
+constexpr OUStringLiteral gsSeparatorLineRelativeHeight(u"SeparatorLineRelativeHeight");
+constexpr OUStringLiteral gsSeparatorLineVerticalAlignment(u"SeparatorLineVerticalAlignment");
+constexpr OUStringLiteral gsIsAutomatic(u"IsAutomatic");
+constexpr OUStringLiteral gsAutomaticDistance(u"AutomaticDistance");
+constexpr OUStringLiteral gsSeparatorLineStyle(u"SeparatorLineStyle");
+
+XMLTextColumnsExport::XMLTextColumnsExport( SvXMLExport& rExp ) :
+ rExport( rExp )
+{
+}
+
+void XMLTextColumnsExport::exportXML( const Any& rAny )
+{
+ Reference < XTextColumns > xColumns;
+ rAny >>= xColumns;
+ if (!xColumns)
+ return;
+
+ const Sequence < TextColumn > aColumns = xColumns->getColumns();
+ sal_Int32 nCount = aColumns.getLength();
+
+ OUStringBuffer sValue;
+ GetExport().AddAttribute( XML_NAMESPACE_FO, XML_COLUMN_COUNT,
+ OUString::number(nCount ? nCount : 1) );
+
+ // handle 'automatic' columns
+ Reference < XPropertySet > xPropSet( xColumns, UNO_QUERY );
+ if( xPropSet.is() )
+ {
+ Any aAny = xPropSet->getPropertyValue( gsIsAutomatic );
+ if ( *o3tl::doAccess<bool>(aAny) )
+ {
+ aAny = xPropSet->getPropertyValue( gsAutomaticDistance );
+ sal_Int32 nDistance = 0;
+ aAny >>= nDistance;
+ OUStringBuffer aBuffer;
+ GetExport().GetMM100UnitConverter().convertMeasureToXML(
+ aBuffer, nDistance );
+ GetExport().AddAttribute( XML_NAMESPACE_FO,
+ XML_COLUMN_GAP,
+ aBuffer.makeStringAndClear() );
+ }
+ }
+
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_STYLE, XML_COLUMNS,
+ true, true );
+
+ if( xPropSet.is() )
+ {
+ Any aAny = xPropSet->getPropertyValue( gsSeparatorLineIsOn );
+ if( *o3tl::doAccess<bool>(aAny) )
+ {
+ // style:width
+ aAny = xPropSet->getPropertyValue( gsSeparatorLineWidth );
+ sal_Int32 nWidth = 0;
+ aAny >>= nWidth;
+ GetExport().GetMM100UnitConverter().convertMeasureToXML( sValue,
+ nWidth );
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_WIDTH,
+ sValue.makeStringAndClear() );
+
+ // style:color
+ aAny = xPropSet->getPropertyValue( gsSeparatorLineColor );
+ sal_Int32 nColor = 0;
+ aAny >>= nColor;
+ ::sax::Converter::convertColor( sValue, nColor );
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_COLOR,
+ sValue.makeStringAndClear() );
+
+ // style:height
+ aAny = xPropSet->getPropertyValue( gsSeparatorLineRelativeHeight );
+ sal_Int32 nHeight = 0;
+ aAny >>= nHeight;
+ ::sax::Converter::convertPercent( sValue, nHeight );
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_HEIGHT,
+ sValue.makeStringAndClear() );
+
+ // style::style
+ aAny = xPropSet->getPropertyValue( gsSeparatorLineStyle );
+ sal_Int16 nStyle = css::text::ColumnSeparatorStyle::NONE;
+ aAny >>= nStyle;
+
+ enum XMLTokenEnum eStr = XML_TOKEN_INVALID;
+ switch ( nStyle )
+ {
+ case css::text::ColumnSeparatorStyle::NONE: eStr = XML_NONE; break;
+ case css::text::ColumnSeparatorStyle::SOLID: eStr = XML_SOLID; break;
+ case css::text::ColumnSeparatorStyle::DOTTED: eStr = XML_DOTTED; break;
+ case css::text::ColumnSeparatorStyle::DASHED: eStr = XML_DASHED; break;
+ default:
+ break;
+ }
+ if ( eStr != XML_TOKEN_INVALID )
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_STYLE, eStr );
+
+ // style:vertical-align
+ aAny = xPropSet->getPropertyValue( gsSeparatorLineVerticalAlignment );
+ VerticalAlignment eVertAlign;
+ aAny >>= eVertAlign;
+
+ eStr = XML_TOKEN_INVALID;
+ switch( eVertAlign )
+ {
+// case VerticalAlignment_TOP: eStr = XML_TOP;
+ case VerticalAlignment_MIDDLE: eStr = XML_MIDDLE; break;
+ case VerticalAlignment_BOTTOM: eStr = XML_BOTTOM; break;
+ default:
+ break;
+ }
+
+ if( eStr != XML_TOKEN_INVALID)
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE,
+ XML_VERTICAL_ALIGN, eStr );
+
+ // style:column-sep
+ SvXMLElementExport aElement( GetExport(), XML_NAMESPACE_STYLE,
+ XML_COLUMN_SEP,
+ true, true );
+ }
+ }
+
+ for (const auto& rColumn : aColumns)
+ {
+ // style:rel-width
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_WIDTH,
+ OUString::number(rColumn.Width) + "*" );
+
+ // fo:margin-left
+ GetExport().GetMM100UnitConverter().convertMeasureToXML( sValue,
+ rColumn.LeftMargin );
+ GetExport().AddAttribute( XML_NAMESPACE_FO, XML_START_INDENT,
+ sValue.makeStringAndClear() );
+
+ // fo:margin-right
+ GetExport().GetMM100UnitConverter().convertMeasureToXML( sValue,
+ rColumn.RightMargin );
+ GetExport().AddAttribute( XML_NAMESPACE_FO, XML_END_INDENT,
+ sValue.makeStringAndClear() );
+
+ // style:column
+ SvXMLElementExport aElement( GetExport(), XML_NAMESPACE_STYLE, XML_COLUMN,
+ true, true );
+ }
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTextFrameContext.cxx b/xmloff/source/text/XMLTextFrameContext.cxx
new file mode 100644
index 0000000000..b00b2b84d9
--- /dev/null
+++ b/xmloff/source/text/XMLTextFrameContext.cxx
@@ -0,0 +1,1751 @@
+/* -*- 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 <o3tl/string_view.hxx>
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <comphelper/base64.hxx>
+#include <comphelper/mediamimetype.hxx>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/text/TextContentAnchorType.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/text/XTextFrame.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <com/sun/star/text/SizeType.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/document/XEventsSupplier.hpp>
+#include <com/sun/star/document/XEmbeddedObjectSupplier.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/text/HoriOrientation.hpp>
+#include <com/sun/star/text/VertOrientation.hpp>
+#include <sax/tools/converter.hxx>
+#include <utility>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmluconv.hxx>
+#include "XMLAnchorTypePropHdl.hxx"
+#include <XMLEmbeddedObjectImportContext.hxx>
+#include <xmloff/XMLBase64ImportContext.hxx>
+#include <XMLReplacementImageContext.hxx>
+#include <xmloff/prstylei.hxx>
+#include <xmloff/i18nmap.hxx>
+#include <xexptran.hxx>
+#include <xmloff/shapeimport.hxx>
+#include <xmloff/XMLEventsImportContext.hxx>
+#include <XMLImageMapContext.hxx>
+#include "XMLTextFrameContext.hxx"
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <map>
+#include <string_view>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::xml::sax;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::drawing;
+using namespace ::com::sun::star::document;
+using namespace ::xmloff::token;
+using ::com::sun::star::document::XEventsSupplier;
+
+#define XML_TEXT_FRAME_TEXTBOX 1
+#define XML_TEXT_FRAME_GRAPHIC 2
+#define XML_TEXT_FRAME_OBJECT 3
+#define XML_TEXT_FRAME_OBJECT_OLE 4
+#define XML_TEXT_FRAME_APPLET 5
+#define XML_TEXT_FRAME_PLUGIN 6
+#define XML_TEXT_FRAME_FLOATING_FRAME 7
+
+typedef ::std::map < const OUString, OUString > ParamMap;
+
+class XMLTextFrameContextHyperlink_Impl
+{
+ OUString sHRef;
+ OUString sName;
+ OUString sTargetFrameName;
+ bool bMap;
+
+public:
+
+ inline XMLTextFrameContextHyperlink_Impl( OUString aHRef,
+ OUString aName,
+ OUString aTargetFrameName,
+ bool bMap );
+
+ const OUString& GetHRef() const { return sHRef; }
+ const OUString& GetName() const { return sName; }
+ const OUString& GetTargetFrameName() const { return sTargetFrameName; }
+ bool GetMap() const { return bMap; }
+};
+
+inline XMLTextFrameContextHyperlink_Impl::XMLTextFrameContextHyperlink_Impl(
+ OUString aHRef, OUString aName,
+ OUString aTargetFrameName, bool bM ) :
+ sHRef(std::move( aHRef )),
+ sName(std::move( aName )),
+ sTargetFrameName(std::move( aTargetFrameName )),
+ bMap( bM )
+{
+}
+
+namespace {
+
+// Implement Title/Description Elements UI (#i73249#)
+class XMLTextFrameTitleOrDescContext_Impl : public SvXMLImportContext
+{
+ OUString& mrTitleOrDesc;
+
+public:
+
+
+ XMLTextFrameTitleOrDescContext_Impl( SvXMLImport& rImport,
+ OUString& rTitleOrDesc );
+
+ virtual void SAL_CALL characters( const OUString& rText ) override;
+};
+
+}
+
+XMLTextFrameTitleOrDescContext_Impl::XMLTextFrameTitleOrDescContext_Impl(
+ SvXMLImport& rImport,
+ OUString& rTitleOrDesc )
+ : SvXMLImportContext( rImport )
+ , mrTitleOrDesc( rTitleOrDesc )
+{
+}
+
+void XMLTextFrameTitleOrDescContext_Impl::characters( const OUString& rText )
+{
+ mrTitleOrDesc += rText;
+}
+
+namespace {
+
+class XMLTextFrameParam_Impl : public SvXMLImportContext
+{
+public:
+ XMLTextFrameParam_Impl( SvXMLImport& rImport,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList,
+ ParamMap &rParamMap);
+};
+
+}
+
+XMLTextFrameParam_Impl::XMLTextFrameParam_Impl(
+ SvXMLImport& rImport,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList,
+ ParamMap &rParamMap):
+ SvXMLImportContext( rImport )
+{
+ OUString sName, sValue;
+ bool bFoundValue = false; // to allow empty values
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
+ {
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(DRAW, XML_VALUE):
+ {
+ sValue = aIter.toString();
+ bFoundValue = true;
+ break;
+ }
+ case XML_ELEMENT(DRAW, XML_NAME):
+ sName = aIter.toString();
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+ if (!sName.isEmpty() && bFoundValue )
+ rParamMap[sName] = sValue;
+}
+
+namespace {
+
+class XMLTextFrameContourContext_Impl : public SvXMLImportContext
+{
+ Reference < XPropertySet > xPropSet;
+
+public:
+
+
+ XMLTextFrameContourContext_Impl( SvXMLImport& rImport, sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList,
+ const Reference < XPropertySet >& rPropSet,
+ bool bPath );
+};
+
+}
+
+XMLTextFrameContourContext_Impl::XMLTextFrameContourContext_Impl(
+ SvXMLImport& rImport,
+ sal_Int32 /*nElement*/,
+ const Reference< XFastAttributeList > & xAttrList,
+ const Reference < XPropertySet >& rPropSet,
+ bool bPath ) :
+ SvXMLImportContext( rImport ),
+ xPropSet( rPropSet )
+{
+ OUString sD, sPoints, sViewBox;
+ bool bPixelWidth = false, bPixelHeight = false;
+ bool bAuto = false;
+ sal_Int32 nWidth = 0;
+ sal_Int32 nHeight = 0;
+
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ switch( aIter.getToken() )
+ {
+ case XML_ELEMENT(SVG, XML_VIEWBOX):
+ case XML_ELEMENT(SVG_COMPAT, XML_VIEWBOX):
+ sViewBox = aIter.toString();
+ break;
+ case XML_ELEMENT(SVG, XML_D):
+ case XML_ELEMENT(SVG_COMPAT, XML_D):
+ if( bPath )
+ sD = aIter.toString();
+ break;
+ case XML_ELEMENT(DRAW,XML_POINTS):
+ if( !bPath )
+ sPoints = aIter.toString();
+ break;
+ case XML_ELEMENT(SVG, XML_WIDTH):
+ case XML_ELEMENT(SVG_COMPAT, XML_WIDTH):
+ if (::sax::Converter::convertMeasurePx(nWidth, aIter.toView()))
+ bPixelWidth = true;
+ else
+ GetImport().GetMM100UnitConverter().convertMeasureToCore(
+ nWidth, aIter.toView());
+ break;
+ case XML_ELEMENT(SVG, XML_HEIGHT):
+ case XML_ELEMENT(SVG_COMPAT, XML_HEIGHT):
+ if (::sax::Converter::convertMeasurePx(nHeight, aIter.toView()))
+ bPixelHeight = true;
+ else
+ GetImport().GetMM100UnitConverter().convertMeasureToCore(
+ nHeight, aIter.toView());
+ break;
+ case XML_ELEMENT(DRAW, XML_RECREATE_ON_EDIT):
+ bAuto = IsXMLToken(aIter, XML_TRUE);
+ break;
+ }
+ }
+
+ OUString sContourPolyPolygon("ContourPolyPolygon");
+ Reference < XPropertySetInfo > xPropSetInfo = rPropSet->getPropertySetInfo();
+
+ if(!xPropSetInfo->hasPropertyByName(sContourPolyPolygon) ||
+ nWidth <= 0 || nHeight <= 0 || bPixelWidth != bPixelHeight ||
+ !(bPath ? sD : sPoints).getLength())
+ return;
+
+ const SdXMLImExViewBox aViewBox( sViewBox, GetImport().GetMM100UnitConverter());
+ basegfx::B2DPolyPolygon aPolyPolygon;
+
+ if( bPath )
+ {
+ basegfx::utils::importFromSvgD(aPolyPolygon, sD, GetImport().needFixPositionAfterZ(), nullptr);
+ }
+ else
+ {
+ basegfx::B2DPolygon aPolygon;
+
+ if(basegfx::utils::importFromSvgPoints(aPolygon, sPoints))
+ {
+ aPolyPolygon = basegfx::B2DPolyPolygon(aPolygon);
+ }
+ }
+
+ if(aPolyPolygon.count())
+ {
+ const basegfx::B2DRange aSourceRange(
+ aViewBox.GetX(), aViewBox.GetY(),
+ aViewBox.GetX() + aViewBox.GetWidth(), aViewBox.GetY() + aViewBox.GetHeight());
+ const basegfx::B2DRange aTargetRange(
+ 0.0, 0.0,
+ nWidth, nHeight);
+
+ if(!aSourceRange.equal(aTargetRange))
+ {
+ aPolyPolygon.transform(
+ basegfx::utils::createSourceRangeTargetRangeTransform(
+ aSourceRange,
+ aTargetRange));
+ }
+
+ css::drawing::PointSequenceSequence aPointSequenceSequence;
+ basegfx::utils::B2DPolyPolygonToUnoPointSequenceSequence(aPolyPolygon, aPointSequenceSequence);
+ xPropSet->setPropertyValue( sContourPolyPolygon, Any(aPointSequenceSequence) );
+ }
+
+ static constexpr OUString sIsPixelContour(u"IsPixelContour"_ustr);
+
+ if( xPropSetInfo->hasPropertyByName( sIsPixelContour ) )
+ {
+ xPropSet->setPropertyValue( sIsPixelContour, Any(bPixelWidth) );
+ }
+
+ static constexpr OUString sIsAutomaticContour(u"IsAutomaticContour"_ustr);
+
+ if( xPropSetInfo->hasPropertyByName( sIsAutomaticContour ) )
+ {
+ xPropSet->setPropertyValue( sIsAutomaticContour, Any(bAuto) );
+ }
+}
+
+namespace {
+
+class XMLTextFrameContext_Impl : public SvXMLImportContext
+{
+ css::uno::Reference < css::text::XTextCursor > xOldTextCursor;
+ css::uno::Reference < css::beans::XPropertySet > xPropSet;
+ css::uno::Reference < css::io::XOutputStream > xBase64Stream;
+
+ /// old list item and block (#89891#)
+ bool mbListContextPushed;
+
+ OUString m_sOrigName;
+ OUString sName;
+ OUString sStyleName;
+ OUString sNextName;
+ OUString sHRef;
+ OUString sCode;
+ OUString sMimeType;
+ OUString sFrameName;
+ OUString sAppletName;
+ OUString sFilterService;
+ OUString sBase64CharsLeft;
+ OUString sTblName;
+ OUStringBuffer maUrlBuffer;
+
+ ParamMap aParamMap;
+
+ sal_Int32 nX;
+ sal_Int32 nY;
+ sal_Int32 nWidth;
+ sal_Int32 nHeight;
+ sal_Int32 nZIndex;
+ sal_Int16 nPage;
+ sal_Int16 nRotation;
+ sal_Int16 nRelWidth;
+ sal_Int16 nRelHeight;
+
+ sal_uInt16 nType;
+ css::text::TextContentAnchorType eAnchorType;
+
+ bool bMayScript : 1;
+ bool bMinWidth : 1;
+ bool bMinHeight : 1;
+ bool bSyncWidth : 1;
+ bool bSyncHeight : 1;
+ bool bCreateFailed : 1;
+ bool bOwnBase64Stream : 1;
+ bool mbMultipleContent : 1; // This context is created based on a multiple content (image)
+ bool m_isDecorative = false;
+ bool m_isSplitAllowed = false;
+
+ void Create();
+
+public:
+
+
+ bool CreateIfNotThere();
+ const OUString& GetHRef() const { return sHRef; }
+
+ XMLTextFrameContext_Impl( SvXMLImport& rImport,
+ sal_Int32 nElement,
+ const css::uno::Reference<css::xml::sax::XFastAttributeList > & rAttrList,
+ css::text::TextContentAnchorType eAnchorType,
+ sal_uInt16 nType,
+ const css::uno::Reference<css::xml::sax::XFastAttributeList > & rFrameAttrList,
+ bool bMultipleContent = false );
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual void SAL_CALL characters( const OUString& rChars ) override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+
+ void SetHyperlink( const OUString& rHRef,
+ const OUString& rName,
+ const OUString& rTargetFrameName,
+ bool bMap );
+
+ // Implement Title/Description Elements UI (#i73249#)
+ void SetTitle( const OUString& rTitle );
+
+ void SetDesc( const OUString& rDesc );
+
+ void SetName();
+
+ const OUString& GetOrigName() const { return m_sOrigName; }
+
+ css::text::TextContentAnchorType GetAnchorType() const { return eAnchorType; }
+ OUString GetMimeType() const { return sMimeType; }
+
+ const css::uno::Reference < css::beans::XPropertySet >& GetPropSet() const { return xPropSet; }
+};
+
+}
+
+void XMLTextFrameContext_Impl::Create()
+{
+ rtl::Reference < XMLTextImportHelper > xTextImportHelper =
+ GetImport().GetTextImport();
+
+ switch ( nType)
+ {
+ case XML_TEXT_FRAME_OBJECT:
+ case XML_TEXT_FRAME_OBJECT_OLE:
+ if( xBase64Stream.is() )
+ {
+ OUString sURL( GetImport().ResolveEmbeddedObjectURLFromBase64() );
+ if( !sURL.isEmpty() )
+ xPropSet = GetImport().GetTextImport()
+ ->createAndInsertOLEObject( GetImport(), sURL,
+ sStyleName,
+ sTblName,
+ nWidth, nHeight );
+ }
+ else if( !sHRef.isEmpty() )
+ {
+ OUString sURL( GetImport().ResolveEmbeddedObjectURL( sHRef,
+ std::u16string_view() ) );
+
+ if( GetImport().IsPackageURL( sHRef ) )
+ {
+ xPropSet = GetImport().GetTextImport()
+ ->createAndInsertOLEObject( GetImport(), sURL,
+ sStyleName,
+ sTblName,
+ nWidth, nHeight );
+ }
+ else
+ {
+ // it should be an own OOo link that has no storage persistence
+ xPropSet = GetImport().GetTextImport()
+ ->createAndInsertOOoLink( GetImport(),
+ sURL,
+ sStyleName,
+ sTblName,
+ nWidth, nHeight );
+ }
+ }
+ else
+ {
+ OUString sURL = "vnd.sun.star.ServiceName:" + sFilterService;
+ xPropSet = GetImport().GetTextImport()
+ ->createAndInsertOLEObject( GetImport(), sURL,
+ sStyleName,
+ sTblName,
+ nWidth, nHeight );
+
+ }
+ break;
+ case XML_TEXT_FRAME_APPLET:
+ {
+ xPropSet = GetImport().GetTextImport()
+ ->createAndInsertApplet( sAppletName, sCode,
+ bMayScript, sHRef,
+ nWidth, nHeight);
+ break;
+ }
+ case XML_TEXT_FRAME_PLUGIN:
+ {
+ if(!sHRef.isEmpty())
+ GetImport().GetAbsoluteReference(sHRef);
+ xPropSet = GetImport().GetTextImport()
+ ->createAndInsertPlugin( sMimeType, sHRef,
+ nWidth, nHeight);
+
+ break;
+ }
+ case XML_TEXT_FRAME_FLOATING_FRAME:
+ {
+ xPropSet = GetImport().GetTextImport()
+ ->createAndInsertFloatingFrame( sFrameName, sHRef,
+ sStyleName,
+ nWidth, nHeight);
+ break;
+ }
+ default:
+ {
+ Reference<XMultiServiceFactory> xFactory( GetImport().GetModel(),
+ UNO_QUERY );
+ if( xFactory.is() )
+ {
+ OUString sServiceName;
+ switch( nType )
+ {
+ case XML_TEXT_FRAME_TEXTBOX: sServiceName = "com.sun.star.text.TextFrame"; break;
+ case XML_TEXT_FRAME_GRAPHIC: sServiceName = "com.sun.star.text.GraphicObject"; break;
+ }
+ Reference<XInterface> xIfc = xFactory->createInstance( sServiceName );
+ SAL_WARN_IF( !xIfc.is(), "xmloff.text", "couldn't create frame" );
+ if( xIfc.is() )
+ xPropSet.set( xIfc, UNO_QUERY );
+ }
+ }
+ }
+
+ if( !xPropSet.is() )
+ {
+ bCreateFailed = true;
+ return;
+ }
+
+ Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
+
+ // Skip duplicated frames
+ if(!mbMultipleContent && // It's allowed to have multiple image for the same frame
+ !sName.isEmpty() &&
+ xTextImportHelper->IsDuplicateFrame(sName, nX, nY, nWidth, nHeight))
+ {
+ bCreateFailed = true;
+ return;
+ }
+
+ // set name
+ Reference < XNamed > xNamed( xPropSet, UNO_QUERY );
+ if( xNamed.is() )
+ {
+ OUString sOrigName( xNamed->getName() );
+ if( sOrigName.isEmpty() ||
+ (!sName.isEmpty() && sOrigName != sName) )
+ {
+ OUString sOldName( sName );
+
+ sal_Int32 i = 0;
+ while( xTextImportHelper->HasFrameByName( sName ) )
+ {
+ sName = sOldName + OUString::number( ++i );
+ }
+ xNamed->setName( sName );
+ if( sName != sOldName )
+ {
+ xTextImportHelper->GetRenameMap().Add( XML_TEXT_RENAME_TYPE_FRAME,
+ sOldName, sName );
+
+ }
+ }
+ }
+
+ // frame style
+ XMLPropStyleContext *pStyle = nullptr;
+ if( !sStyleName.isEmpty() )
+ {
+ pStyle = xTextImportHelper->FindAutoFrameStyle( sStyleName );
+ if( pStyle )
+ sStyleName = pStyle->GetParentName();
+ }
+
+ Any aAny;
+ if( !sStyleName.isEmpty() )
+ {
+ OUString sDisplayStyleName( GetImport().GetStyleDisplayName(
+ XmlStyleFamily::SD_GRAPHICS_ID, sStyleName ) );
+ const Reference < XNameContainer > & rStyles =
+ xTextImportHelper->GetFrameStyles();
+ if( rStyles.is() &&
+ rStyles->hasByName( sDisplayStyleName ) )
+ {
+ xPropSet->setPropertyValue( "FrameStyleName", Any(sDisplayStyleName) );
+ }
+ }
+
+ // anchor type (must be set before any other properties, because
+ // otherwise some orientations cannot be set or will be changed
+ // afterwards)
+ xPropSet->setPropertyValue( "AnchorType", Any(eAnchorType) );
+
+ // hard properties
+ if( pStyle )
+ pStyle->FillPropertySet( xPropSet );
+
+ // x and y
+ sal_Int16 nHoriOrient = HoriOrientation::NONE;
+ aAny = xPropSet->getPropertyValue( "HoriOrient" );
+ aAny >>= nHoriOrient;
+ if( HoriOrientation::NONE == nHoriOrient )
+ {
+ xPropSet->setPropertyValue( "HoriOrientPosition", Any(nX) );
+ }
+
+ sal_Int16 nVertOrient = VertOrientation::NONE;
+ aAny = xPropSet->getPropertyValue( "VertOrient" );
+ aAny >>= nVertOrient;
+ if( VertOrientation::NONE == nVertOrient )
+ {
+ xPropSet->setPropertyValue( "VertOrientPosition", Any(nY) );
+ }
+
+ // width
+ if( nWidth > 0 )
+ {
+ xPropSet->setPropertyValue( "Width", Any(nWidth) );
+ }
+ if( nRelWidth > 0 || nWidth > 0 )
+ {
+ xPropSet->setPropertyValue( "RelativeWidth", Any(nRelWidth) );
+ }
+ if( bSyncWidth || nWidth > 0 )
+ {
+ xPropSet->setPropertyValue( "IsSyncWidthToHeight", Any(bSyncWidth) );
+ }
+ if( xPropSetInfo->hasPropertyByName( "WidthType" ) &&
+ (bMinWidth || nWidth > 0 || nRelWidth > 0 ) )
+ {
+ sal_Int16 nSizeType =
+ (bMinWidth && XML_TEXT_FRAME_TEXTBOX == nType) ? SizeType::MIN
+ : SizeType::FIX;
+ xPropSet->setPropertyValue( "WidthType", Any(nSizeType) );
+ }
+
+ if( nHeight > 0 )
+ {
+ xPropSet->setPropertyValue( "Height", Any(nHeight) );
+ }
+ if( nRelHeight > 0 || nHeight > 0 )
+ {
+ xPropSet->setPropertyValue( "RelativeHeight", Any(nRelHeight) );
+ }
+ if( bSyncHeight || nHeight > 0 )
+ {
+ xPropSet->setPropertyValue( "IsSyncHeightToWidth", Any(bSyncHeight) );
+ }
+ if( xPropSetInfo->hasPropertyByName( "SizeType" ) &&
+ (bMinHeight || nHeight > 0 || nRelHeight > 0 ) )
+ {
+ sal_Int16 nSizeType =
+ (bMinHeight && XML_TEXT_FRAME_TEXTBOX == nType) ? SizeType::MIN
+ : SizeType::FIX;
+ xPropSet->setPropertyValue( "SizeType", Any(nSizeType) );
+ }
+
+ if( XML_TEXT_FRAME_GRAPHIC == nType )
+ {
+ // URL
+ OSL_ENSURE( !sHRef.isEmpty() || xBase64Stream.is(),
+ "neither URL nor base64 image data given" );
+ uno::Reference<graphic::XGraphic> xGraphic;
+ if (!sHRef.isEmpty())
+ {
+ xGraphic = GetImport().loadGraphicByURL(sHRef);
+ }
+ else if (xBase64Stream.is())
+ {
+ xGraphic = GetImport().loadGraphicFromBase64(xBase64Stream);
+ xBase64Stream = nullptr;
+ }
+
+ if (xGraphic.is())
+ xPropSet->setPropertyValue("Graphic", Any(xGraphic));
+
+ // filter name
+ xPropSet->setPropertyValue( "GraphicFilter", Any(OUString()) );
+
+ // rotation
+ xPropSet->setPropertyValue( "GraphicRotation", Any(nRotation) );
+ }
+
+ // page number (must be set after the frame is inserted, because it
+ // will be overwritten then inserting the frame.
+ if( TextContentAnchorType_AT_PAGE == eAnchorType && nPage > 0 )
+ {
+ xPropSet->setPropertyValue( "AnchorPageNo", Any(nPage) );
+ }
+
+ if (m_isDecorative && xPropSetInfo->hasPropertyByName("Decorative"))
+ {
+ xPropSet->setPropertyValue("Decorative", uno::Any(true));
+ }
+
+ if (m_isSplitAllowed && xPropSetInfo->hasPropertyByName("IsSplitAllowed"))
+ {
+ xPropSet->setPropertyValue("IsSplitAllowed", uno::Any(true));
+ }
+
+ if( XML_TEXT_FRAME_OBJECT != nType &&
+ XML_TEXT_FRAME_OBJECT_OLE != nType &&
+ XML_TEXT_FRAME_APPLET != nType &&
+ XML_TEXT_FRAME_PLUGIN!= nType &&
+ XML_TEXT_FRAME_FLOATING_FRAME != nType)
+ {
+ Reference < XTextContent > xTxtCntnt( xPropSet, UNO_QUERY );
+ try
+ {
+ xTextImportHelper->InsertTextContent(xTxtCntnt);
+ }
+ catch (lang::IllegalArgumentException const&)
+ {
+ TOOLS_WARN_EXCEPTION("xmloff.text", "Cannot import part of the text - probably an image in the text frame?");
+ return;
+ }
+ }
+
+ // Make adding the shape to Z-Ordering dependent from if we are
+ // inside an inside_deleted_section (redlining). That is necessary
+ // since the shape will be removed again later. It would lead to
+ // errors if it would stay inside the Z-Ordering. Thus, the
+ // easiest way to solve that conflict is to not add it here.
+ if(!GetImport().HasTextImport()
+ || !GetImport().GetTextImport()->IsInsideDeleteContext())
+ {
+ Reference < XShape > xShape( xPropSet, UNO_QUERY );
+
+ GetImport().GetShapeImport()->shapeWithZIndexAdded( xShape, nZIndex );
+ }
+
+ if( XML_TEXT_FRAME_TEXTBOX != nType )
+ return;
+
+ xTextImportHelper->ConnectFrameChains( sName, sNextName, xPropSet );
+ Reference < XTextFrame > xTxtFrame( xPropSet, UNO_QUERY );
+ Reference < XText > xTxt = xTxtFrame->getText();
+ xOldTextCursor = xTextImportHelper->GetCursor();
+ xTextImportHelper->SetCursor( xTxt->createTextCursor() );
+
+ // remember old list item and block (#89892#) and reset them
+ // for the text frame
+ xTextImportHelper->PushListContext();
+ mbListContextPushed = true;
+}
+
+void XMLTextFrameContext::removeGraphicFromImportContext(const SvXMLImportContext& rContext)
+{
+ const XMLTextFrameContext_Impl* pXMLTextFrameContext_Impl = dynamic_cast< const XMLTextFrameContext_Impl* >(&rContext);
+
+ if(!pXMLTextFrameContext_Impl)
+ return;
+
+ try
+ {
+ // just dispose to delete
+ uno::Reference< lang::XComponent > xComp(pXMLTextFrameContext_Impl->GetPropSet(), UNO_QUERY);
+
+ // Inform shape importer about the removal so it can adjust
+ // z-indexes.
+ uno::Reference<drawing::XShape> xShape(xComp, uno::UNO_QUERY);
+ GetImport().GetShapeImport()->shapeRemoved(xShape);
+
+ if(xComp.is())
+ {
+ xComp->dispose();
+ }
+ }
+ catch( uno::Exception& )
+ {
+ OSL_FAIL( "Error in cleanup of multiple graphic object import (!)" );
+ }
+}
+
+OUString XMLTextFrameContext::getMimeTypeFromImportContext(const SvXMLImportContext& rContext) const
+{
+ const XMLTextFrameContext_Impl* pXMLTextFrameContext_Impl = dynamic_cast<const XMLTextFrameContext_Impl*>(&rContext);
+
+ if (pXMLTextFrameContext_Impl)
+ return pXMLTextFrameContext_Impl->GetMimeType();
+
+ return OUString();
+}
+
+OUString XMLTextFrameContext::getGraphicPackageURLFromImportContext(const SvXMLImportContext& rContext) const
+{
+ const XMLTextFrameContext_Impl* pXMLTextFrameContext_Impl = dynamic_cast< const XMLTextFrameContext_Impl* >(&rContext);
+
+ if(pXMLTextFrameContext_Impl)
+ {
+ return "vnd.sun.star.Package:" + pXMLTextFrameContext_Impl->GetHRef();
+ }
+
+ return OUString();
+}
+
+css::uno::Reference<css::graphic::XGraphic> XMLTextFrameContext::getGraphicFromImportContext(const SvXMLImportContext& rContext) const
+{
+ uno::Reference<graphic::XGraphic> xGraphic;
+
+ const XMLTextFrameContext_Impl* pXMLTextFrameContext_Impl = dynamic_cast<const XMLTextFrameContext_Impl*>(&rContext);
+
+ if (pXMLTextFrameContext_Impl)
+ {
+ try
+ {
+ const uno::Reference<beans::XPropertySet>& xPropertySet = pXMLTextFrameContext_Impl->GetPropSet();
+
+ if (xPropertySet.is())
+ {
+ xPropertySet->getPropertyValue("Graphic") >>= xGraphic;
+ }
+ }
+ catch (uno::Exception&)
+ {}
+ }
+ return xGraphic;
+}
+
+bool XMLTextFrameContext_Impl::CreateIfNotThere()
+{
+ if( !xPropSet.is() &&
+ ( XML_TEXT_FRAME_OBJECT_OLE == nType ||
+ XML_TEXT_FRAME_GRAPHIC == nType ) &&
+ xBase64Stream.is() && !bCreateFailed )
+ {
+ if( bOwnBase64Stream )
+ xBase64Stream->closeOutput();
+ Create();
+ }
+
+ return xPropSet.is();
+}
+
+XMLTextFrameContext_Impl::XMLTextFrameContext_Impl(
+ SvXMLImport& rImport,
+ sal_Int32 /*nElement*/,
+ const Reference< XFastAttributeList > & rAttrList,
+ TextContentAnchorType eATyp,
+ sal_uInt16 nNewType,
+ const Reference< XFastAttributeList > & rFrameAttrList,
+ bool bMultipleContent )
+: SvXMLImportContext( rImport )
+, mbListContextPushed( false )
+, nType( nNewType )
+, eAnchorType( eATyp )
+{
+ nX = 0;
+ nY = 0;
+ nWidth = 0;
+ nHeight = 0;
+ nZIndex = -1;
+ nPage = 0;
+ nRotation = 0;
+ nRelWidth = 0;
+ nRelHeight = 0;
+ bMayScript = false;
+
+ bMinHeight = false;
+ bMinWidth = false;
+ bSyncWidth = false;
+ bSyncHeight = false;
+ bCreateFailed = false;
+ bOwnBase64Stream = false;
+ mbMultipleContent = bMultipleContent;
+
+ auto processAttr = [&](sal_Int32 nElement, const sax_fastparser::FastAttributeList::FastAttributeIter& aIter) -> void
+ {
+ switch( nElement )
+ {
+ case XML_ELEMENT(DRAW, XML_STYLE_NAME):
+ sStyleName = aIter.toString();
+ break;
+ case XML_ELEMENT(DRAW, XML_NAME):
+ m_sOrigName = aIter.toString();
+ sName = m_sOrigName;
+ break;
+ case XML_ELEMENT(DRAW, XML_FRAME_NAME):
+ sFrameName = aIter.toString();
+ break;
+ case XML_ELEMENT(DRAW, XML_APPLET_NAME):
+ sAppletName = aIter.toString();
+ break;
+ case XML_ELEMENT(TEXT, XML_ANCHOR_TYPE):
+ if( TextContentAnchorType_AT_PARAGRAPH == eAnchorType ||
+ TextContentAnchorType_AT_CHARACTER == eAnchorType ||
+ TextContentAnchorType_AS_CHARACTER == eAnchorType )
+ {
+
+ TextContentAnchorType eNew;
+ if( XMLAnchorTypePropHdl::convert( aIter.toView(), eNew ) &&
+ ( TextContentAnchorType_AT_PARAGRAPH == eNew ||
+ TextContentAnchorType_AT_CHARACTER == eNew ||
+ TextContentAnchorType_AS_CHARACTER == eNew ||
+ TextContentAnchorType_AT_PAGE == eNew) )
+ eAnchorType = eNew;
+ }
+ break;
+ case XML_ELEMENT(TEXT, XML_ANCHOR_PAGE_NUMBER):
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertNumber(nTmp, aIter.toView(), 1, SHRT_MAX))
+ nPage = static_cast<sal_Int16>(nTmp);
+ }
+ break;
+ case XML_ELEMENT(SVG, XML_X):
+ case XML_ELEMENT(SVG_COMPAT, XML_X):
+ GetImport().GetMM100UnitConverter().convertMeasureToCore(
+ nX, aIter.toView());
+ break;
+ case XML_ELEMENT(SVG, XML_Y):
+ case XML_ELEMENT(SVG_COMPAT, XML_Y):
+ GetImport().GetMM100UnitConverter().convertMeasureToCore(
+ nY, aIter.toView() );
+ break;
+ case XML_ELEMENT(SVG, XML_WIDTH):
+ case XML_ELEMENT(SVG_COMPAT, XML_WIDTH):
+ // relative widths are obsolete since SRC617. Remove them some day!
+ if( aIter.toView().find( '%' ) != std::string_view::npos )
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertPercent(nTmp, aIter.toView()))
+ nRelWidth = static_cast<sal_Int16>(nTmp);
+ }
+ else
+ {
+ GetImport().GetMM100UnitConverter().convertMeasureToCore(
+ nWidth, aIter.toView(), 0 );
+ }
+ break;
+ case XML_ELEMENT(STYLE, XML_REL_WIDTH):
+ if( IsXMLToken(aIter, XML_SCALE) )
+ {
+ bSyncWidth = true;
+ }
+ else
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertPercent( nTmp, aIter.toView() ))
+ nRelWidth = static_cast<sal_Int16>(nTmp);
+ }
+ break;
+ case XML_ELEMENT(FO, XML_MIN_WIDTH):
+ case XML_ELEMENT(FO_COMPAT, XML_MIN_WIDTH):
+ if( aIter.toView().find( '%' ) != std::string_view::npos )
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertPercent(nTmp, aIter.toView()))
+ nRelWidth = static_cast<sal_Int16>(nTmp);
+ }
+ else
+ {
+ GetImport().GetMM100UnitConverter().convertMeasureToCore(
+ nWidth, aIter.toView(), 0 );
+ }
+ bMinWidth = true;
+ break;
+ case XML_ELEMENT(SVG, XML_HEIGHT):
+ case XML_ELEMENT(SVG_COMPAT, XML_HEIGHT):
+ // relative heights are obsolete since SRC617. Remove them some day!
+ if( aIter.toView().find( '%' ) != std::string_view::npos )
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertPercent(nTmp, aIter.toView()))
+ nRelHeight = static_cast<sal_Int16>(nTmp);
+ }
+ else
+ {
+ GetImport().GetMM100UnitConverter().convertMeasureToCore(
+ nHeight, aIter.toView(), 0 );
+ }
+ break;
+ case XML_ELEMENT(STYLE, XML_REL_HEIGHT):
+ if( IsXMLToken( aIter, XML_SCALE ) )
+ {
+ bSyncHeight = true;
+ }
+ else if( IsXMLToken( aIter, XML_SCALE_MIN ) )
+ {
+ bSyncHeight = true;
+ bMinHeight = true;
+ }
+ else
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertPercent( nTmp, aIter.toView() ))
+ nRelHeight = static_cast<sal_Int16>(nTmp);
+ }
+ break;
+ case XML_ELEMENT(FO, XML_MIN_HEIGHT):
+ case XML_ELEMENT(FO_COMPAT, XML_MIN_HEIGHT):
+ if( aIter.toView().find( '%' ) != std::string_view::npos )
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertPercent(nTmp, aIter.toView()))
+ nRelHeight = static_cast<sal_Int16>(nTmp);
+ }
+ else
+ {
+ GetImport().GetMM100UnitConverter().convertMeasureToCore(
+ nHeight, aIter.toView(), 0 );
+ }
+ bMinHeight = true;
+ break;
+ case XML_ELEMENT(DRAW, XML_ZINDEX):
+ ::sax::Converter::convertNumber( nZIndex, aIter.toView(), -1 );
+ break;
+ case XML_ELEMENT(DRAW, XML_CHAIN_NEXT_NAME):
+ sNextName = aIter.toString();
+ break;
+ case XML_ELEMENT(XLINK, XML_HREF):
+ sHRef = aIter.toString();
+ break;
+ case XML_ELEMENT(DRAW, XML_TRANSFORM):
+ {
+ // RotateFlyFrameFix: im/export full 'draw:transform' using existing tooling
+ // Currently only rotation is used, but combinations with 'draw:transform'
+ // may be necessary in the future, so that svg:x/svg:y/svg:width/svg:height
+ // may be extended/replaced with 'draw:transform' (see draw objects)
+ SdXMLImExTransform2D aSdXMLImExTransform2D;
+ basegfx::B2DHomMatrix aFullTransform;
+
+ // Use SdXMLImExTransform2D to convert to transformation
+ // Note: using GetTwipUnitConverter instead of GetMM100UnitConverter may be needed,
+ // but is not generally available (as it should be, a 'current' UnitConverter should
+ // be available at GetExport() - and maybe was once). May have to be addressed as soon
+ // as translate transformations are used here.
+ aSdXMLImExTransform2D.SetString(aIter.toString(), GetImport().GetMM100UnitConverter());
+ aSdXMLImExTransform2D.GetFullTransform(aFullTransform);
+
+ if(!aFullTransform.isIdentity())
+ {
+ const basegfx::utils::B2DHomMatrixBufferedDecompose aDecomposedTransform(aFullTransform);
+
+ // currently we *only* use rotation (and translation indirectly), so warn if *any*
+ // of the other transform parts is used
+ SAL_WARN_IF(!basegfx::fTools::equal(1.0, aDecomposedTransform.getScale().getX()), "xmloff.text", "draw:transform uses scaleX" );
+ SAL_WARN_IF(!basegfx::fTools::equal(1.0, aDecomposedTransform.getScale().getY()), "xmloff.text", "draw:transform uses scaleY" );
+ SAL_WARN_IF(!basegfx::fTools::equalZero(aDecomposedTransform.getShearX()), "xmloff.text", "draw:transform uses shearX" );
+
+ // Translation comes from the translate to RotCenter, rot and BackTranslate.
+ // This means that it represents the translation between unrotated TopLeft
+ // and rotated TopLeft. This may be checked here now, but currently we only
+ // use rotation around center and assume that this *was* a rotation around
+ // center. The check would compare the object's center with the RotCenter
+ // that can be extracted from the transformation in aFullTransform.
+ // The definition contains implicitly the RotationCenter absolute
+ // to the scaled and translated object, so this may be used if needed (see
+ // _exportTextGraphic how the -trans/rot/trans is composed)
+
+ if(!basegfx::fTools::equalZero(aDecomposedTransform.getRotate()))
+ {
+ // rotation is used, set it. Convert from deg to 10th degree integer
+ // CAUTION: due to #i78696# (rotation mirrored using API) the rotate
+ // value is already mirrored, so do not do it again here (to be in sync
+ // with XMLTextParagraphExport::_exportTextGraphic normally it would need
+ // to me mirrored using * -1.0, see conversion there)
+ // CAUTION-II: due to tdf#115782 it is better for current ODF to indeed use it
+ // with the wrong orientation as in all other cases - ARGH! We will need to
+ // correct this in future ODF ASAP! For now, mirror the rotation here AGAIN
+ const double fRotate(-basegfx::rad2deg<10>(aDecomposedTransform.getRotate()));
+ nRotation = static_cast< sal_Int16 >(basegfx::fround(fRotate) % 3600);
+
+ // tdf#115529 may be negative, with the above modulo maximal -3599, so
+ // no loop needed here. nRotation is used in setPropertyValue("GraphicRotation")
+ // and *has* to be in the range [0 .. 3600[
+ if(nRotation < 0)
+ {
+ nRotation += 3600;
+ }
+ }
+ }
+ }
+ break;
+ case XML_ELEMENT(DRAW, XML_CODE):
+ sCode = aIter.toString();
+ break;
+ case XML_ELEMENT(DRAW, XML_OBJECT):
+ break;
+ case XML_ELEMENT(DRAW, XML_ARCHIVE):
+ break;
+ case XML_ELEMENT(DRAW, XML_MAY_SCRIPT):
+ bMayScript = IsXMLToken( aIter, XML_TRUE );
+ break;
+ case XML_ELEMENT(DRAW, XML_MIME_TYPE):
+ case XML_ELEMENT(LO_EXT, XML_MIME_TYPE):
+ sMimeType = aIter.toString();
+ break;
+ case XML_ELEMENT(DRAW, XML_NOTIFY_ON_UPDATE_OF_RANGES):
+ case XML_ELEMENT(DRAW, XML_NOTIFY_ON_UPDATE_OF_TABLE):
+ sTblName = aIter.toString();
+ break;
+ case XML_ELEMENT(LO_EXT, XML_DECORATIVE):
+ case XML_ELEMENT(DRAW, XML_DECORATIVE):
+ ::sax::Converter::convertBool(m_isDecorative, aIter.toString());
+ break;
+ case XML_ELEMENT(LO_EXT, XML_MAY_BREAK_BETWEEN_PAGES):
+ case XML_ELEMENT(DRAW, XML_MAY_BREAK_BETWEEN_PAGES):
+ sax::Converter::convertBool(m_isSplitAllowed, aIter.toString());
+ break;
+ default:
+ SAL_INFO("xmloff", "unknown attribute " << SvXMLImport::getPrefixAndNameFromToken(aIter.getToken()) << " value=" << aIter.toString());
+ }
+ };
+
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(rAttrList) )
+ processAttr(aIter.getToken(), aIter);
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(rFrameAttrList) )
+ processAttr(aIter.getToken(), aIter);
+
+ if( ( (XML_TEXT_FRAME_GRAPHIC == nType ||
+ XML_TEXT_FRAME_OBJECT == nType ||
+ XML_TEXT_FRAME_OBJECT_OLE == nType) &&
+ sHRef.isEmpty() ) ||
+ ( XML_TEXT_FRAME_APPLET == nType && sCode.isEmpty() ) ||
+ ( XML_TEXT_FRAME_PLUGIN == nType &&
+ sHRef.isEmpty() && sMimeType.isEmpty() ) )
+ return; // no URL: no image or OLE object
+
+ Create();
+}
+
+void XMLTextFrameContext_Impl::endFastElement(sal_Int32 )
+{
+ if( ( XML_TEXT_FRAME_OBJECT_OLE == nType ||
+ XML_TEXT_FRAME_GRAPHIC == nType) &&
+ !xPropSet.is() && !bCreateFailed )
+ {
+ std::u16string_view sTrimmedChars = o3tl::trim(maUrlBuffer);
+ if( !sTrimmedChars.empty() )
+ {
+ if( !xBase64Stream.is() )
+ {
+ if( XML_TEXT_FRAME_GRAPHIC == nType )
+ {
+ xBase64Stream =
+ GetImport().GetStreamForGraphicObjectURLFromBase64();
+ }
+ else
+ {
+ xBase64Stream =
+ GetImport().GetStreamForEmbeddedObjectURLFromBase64();
+ }
+ if( xBase64Stream.is() )
+ bOwnBase64Stream = true;
+ }
+ if( bOwnBase64Stream && xBase64Stream.is() )
+ {
+ OUString sChars;
+ if( !sBase64CharsLeft.isEmpty() )
+ {
+ sChars = sBase64CharsLeft + sTrimmedChars;
+ sBase64CharsLeft.clear();
+ }
+ else
+ {
+ sChars = sTrimmedChars;
+ }
+ Sequence< sal_Int8 > aBuffer( (sChars.getLength() / 4) * 3 );
+ sal_Int32 nCharsDecoded =
+ ::comphelper::Base64::decodeSomeChars( aBuffer, sChars );
+ xBase64Stream->writeBytes( aBuffer );
+ if( nCharsDecoded != sChars.getLength() )
+ sBase64CharsLeft = sChars.copy( nCharsDecoded );
+ }
+ }
+ maUrlBuffer.setLength(0);
+ }
+
+ CreateIfNotThere();
+
+ if( xOldTextCursor.is() )
+ {
+ GetImport().GetTextImport()->DeleteParagraph();
+ GetImport().GetTextImport()->SetCursor( xOldTextCursor );
+ }
+
+ // reinstall old list item (if necessary) #89892#
+ if (mbListContextPushed) {
+ GetImport().GetTextImport()->PopListContext();
+ }
+
+ if (( nType == XML_TEXT_FRAME_APPLET || nType == XML_TEXT_FRAME_PLUGIN ) && xPropSet.is())
+ GetImport().GetTextImport()->endAppletOrPlugin( xPropSet, aParamMap);
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTextFrameContext_Impl::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ if( nElement == XML_ELEMENT(DRAW, XML_PARAM) )
+ {
+ if ( nType == XML_TEXT_FRAME_APPLET || nType == XML_TEXT_FRAME_PLUGIN )
+ return new XMLTextFrameParam_Impl( GetImport(),
+ xAttrList, aParamMap );
+ }
+ else if( nElement == XML_ELEMENT(OFFICE, XML_BINARY_DATA) )
+ {
+ if( !xPropSet.is() && !xBase64Stream.is() && !bCreateFailed )
+ {
+ switch( nType )
+ {
+ case XML_TEXT_FRAME_GRAPHIC:
+ xBase64Stream =
+ GetImport().GetStreamForGraphicObjectURLFromBase64();
+ break;
+ case XML_TEXT_FRAME_OBJECT_OLE:
+ xBase64Stream =
+ GetImport().GetStreamForEmbeddedObjectURLFromBase64();
+ break;
+ }
+ if( xBase64Stream.is() )
+ return new XMLBase64ImportContext( GetImport(), xBase64Stream );
+ }
+ }
+ // Correction of condition which also avoids warnings. (#i100480#)
+ if( XML_TEXT_FRAME_OBJECT == nType &&
+ ( nElement == XML_ELEMENT(OFFICE, XML_DOCUMENT) ||
+ nElement == XML_ELEMENT(MATH, XML_MATH) ) )
+ {
+ if( !xPropSet.is() && !bCreateFailed )
+ {
+ XMLEmbeddedObjectImportContext *pEContext =
+ new XMLEmbeddedObjectImportContext( GetImport(), nElement, xAttrList );
+ sFilterService = pEContext->GetFilterServiceName();
+ if( !sFilterService.isEmpty() )
+ {
+ Create();
+ if( xPropSet.is() )
+ {
+ Reference < XEmbeddedObjectSupplier > xEOS( xPropSet,
+ UNO_QUERY );
+ OSL_ENSURE( xEOS.is(),
+ "no embedded object supplier for own object" );
+ Reference<css::lang::XComponent> aXComponent(xEOS->getEmbeddedObject());
+ pEContext->SetComponent( aXComponent );
+ }
+ }
+ return pEContext;
+ }
+ }
+
+ if( xOldTextCursor.is() ) // text-box
+ {
+ auto p = GetImport().GetTextImport()->CreateTextChildContext(
+ GetImport(), nElement, xAttrList,
+ XMLTextType::TextBox );
+ if (p)
+ return p;
+ }
+
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+
+ return nullptr;
+}
+
+void XMLTextFrameContext_Impl::characters( const OUString& rChars )
+{
+ maUrlBuffer.append(rChars);
+}
+
+void XMLTextFrameContext_Impl::SetHyperlink( const OUString& rHRef,
+ const OUString& rName,
+ const OUString& rTargetFrameName,
+ bool bMap )
+{
+ static constexpr OUString s_HyperLinkURL = u"HyperLinkURL"_ustr;
+ static constexpr OUString s_HyperLinkName = u"HyperLinkName"_ustr;
+ static constexpr OUString s_HyperLinkTarget = u"HyperLinkTarget"_ustr;
+ static constexpr OUString s_ServerMap = u"ServerMap"_ustr;
+ if( !xPropSet.is() )
+ return;
+
+ Reference < XPropertySetInfo > xPropSetInfo =
+ xPropSet->getPropertySetInfo();
+ if( !xPropSetInfo.is() ||
+ !xPropSetInfo->hasPropertyByName(s_HyperLinkURL))
+ return;
+
+ xPropSet->setPropertyValue( s_HyperLinkURL, Any(rHRef) );
+
+ if (xPropSetInfo->hasPropertyByName(s_HyperLinkName))
+ {
+ xPropSet->setPropertyValue(s_HyperLinkName, Any(rName));
+ }
+
+ if (xPropSetInfo->hasPropertyByName(s_HyperLinkTarget))
+ {
+ xPropSet->setPropertyValue( s_HyperLinkTarget, Any(rTargetFrameName) );
+ }
+
+ if (xPropSetInfo->hasPropertyByName(s_ServerMap))
+ {
+ xPropSet->setPropertyValue(s_ServerMap, Any(bMap));
+ }
+}
+
+void XMLTextFrameContext_Impl::SetName()
+{
+ Reference<XNamed> xNamed(xPropSet, UNO_QUERY);
+ if (m_sOrigName.isEmpty() || !xNamed.is())
+ return;
+
+ OUString const name(xNamed->getName());
+ if (name != m_sOrigName)
+ {
+ try
+ {
+ xNamed->setName(m_sOrigName);
+ }
+ catch (uno::Exception const&)
+ { // fdo#71698 document contains 2 frames with same draw:name
+ TOOLS_INFO_EXCEPTION("xmloff.text", "SetName(): exception setting \""
+ << m_sOrigName << "\"");
+ }
+ }
+}
+
+// Implement Title/Description Elements UI (#i73249#)
+void XMLTextFrameContext_Impl::SetTitle( const OUString& rTitle )
+{
+ if ( xPropSet.is() )
+ {
+ Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
+ if( xPropSetInfo->hasPropertyByName( "Title" ) )
+ {
+ xPropSet->setPropertyValue( "Title", Any( rTitle ) );
+ }
+ }
+}
+
+void XMLTextFrameContext_Impl::SetDesc( const OUString& rDesc )
+{
+ if ( xPropSet.is() )
+ {
+ Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
+ if( xPropSetInfo->hasPropertyByName( "Description" ) )
+ {
+ xPropSet->setPropertyValue( "Description", Any( rDesc ) );
+ }
+ }
+}
+
+
+bool XMLTextFrameContext::CreateIfNotThere( css::uno::Reference < css::beans::XPropertySet >& rPropSet )
+{
+ SvXMLImportContext *pContext = m_xImplContext.get();
+ XMLTextFrameContext_Impl *pImpl = dynamic_cast< XMLTextFrameContext_Impl*>( pContext );
+ if( pImpl && pImpl->CreateIfNotThere() )
+ rPropSet = pImpl->GetPropSet();
+
+ return rPropSet.is();
+}
+
+XMLTextFrameContext::XMLTextFrameContext(
+ SvXMLImport& rImport,
+ const Reference< XFastAttributeList > & xAttrList,
+ TextContentAnchorType eATyp )
+: SvXMLImportContext( rImport )
+, m_xAttrList( new sax_fastparser::FastAttributeList( xAttrList ) )
+ // Implement Title/Description Elements UI (#i73249#)
+, m_eDefaultAnchorType( eATyp )
+ // Shapes in Writer cannot be named via context menu (#i51726#)
+, m_HasAutomaticStyleWithoutParentStyle( false )
+, m_bSupportsReplacement( false )
+{
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ // New distinguish attribute between Writer objects and Draw objects is:
+ // Draw objects have an automatic style without a parent style (#i51726#)
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(DRAW, XML_STYLE_NAME):
+ {
+ OUString aStyleName = aIter.toString();
+ if( !aStyleName.isEmpty() )
+ {
+ rtl::Reference < XMLTextImportHelper > xTxtImport =
+ GetImport().GetTextImport();
+ XMLPropStyleContext* pStyle = xTxtImport->FindAutoFrameStyle( aStyleName );
+ if ( pStyle && pStyle->GetParentName().isEmpty() )
+ {
+ m_HasAutomaticStyleWithoutParentStyle = true;
+ }
+ }
+ break;
+ }
+ case XML_ELEMENT(TEXT, XML_ANCHOR_TYPE):
+ {
+ TextContentAnchorType eNew;
+ if( XMLAnchorTypePropHdl::convert( aIter.toView(), eNew ) &&
+ ( TextContentAnchorType_AT_PARAGRAPH == eNew ||
+ TextContentAnchorType_AT_CHARACTER == eNew ||
+ TextContentAnchorType_AS_CHARACTER == eNew ||
+ TextContentAnchorType_AT_PAGE == eNew) )
+ m_eDefaultAnchorType = eNew;
+ break;
+ }
+ }
+ }
+}
+
+void XMLTextFrameContext::endFastElement(sal_Int32 )
+{
+ /// solve if multiple image child contexts were imported
+ SvXMLImportContextRef const pMultiContext(solveMultipleImages());
+
+ SvXMLImportContext const*const pContext =
+ (pMultiContext.is()) ? pMultiContext.get() : m_xImplContext.get();
+ XMLTextFrameContext_Impl *pImpl = const_cast<XMLTextFrameContext_Impl*>(dynamic_cast< const XMLTextFrameContext_Impl*>( pContext ));
+ assert(!pMultiContext.is() || pImpl);
+
+ // When we are dealing with a textbox, pImpl will be null;
+ // we need to set the hyperlink to the shape instead
+ Reference<XShape> xShape = GetShape();
+ if (xShape.is() && m_pHyperlink)
+ {
+ Reference<XPropertySet> xProps(xShape, UNO_QUERY);
+ if (xProps.is())
+ xProps->setPropertyValue("Hyperlink", Any(m_pHyperlink->GetHRef()));
+ }
+
+ if( !pImpl )
+ return;
+
+ pImpl->CreateIfNotThere();
+
+ // fdo#68839: in case the surviving image was not the first one,
+ // it will have a counter added to its name - set the original name
+ if (pMultiContext.is()) // do this only when necessary; esp. not for text
+ { // frames that may have entries in GetRenameMap()!
+ pImpl->SetName();
+ }
+
+ if( !m_sTitle.isEmpty() )
+ {
+ pImpl->SetTitle( m_sTitle );
+ }
+ if( !m_sDesc.isEmpty() )
+ {
+ pImpl->SetDesc( m_sDesc );
+ }
+
+ if( m_pHyperlink )
+ {
+ pImpl->SetHyperlink( m_pHyperlink->GetHRef(), m_pHyperlink->GetName(),
+ m_pHyperlink->GetTargetFrameName(), m_pHyperlink->GetMap() );
+ m_pHyperlink.reset();
+ }
+
+ GetImport().GetTextImport()->StoreLastImportedFrameName(pImpl->GetOrigName());
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTextFrameContext::createFastChildContext(
+ sal_Int32 nElement,
+ const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
+{
+ SvXMLImportContextRef xContext;
+
+ if( !m_xImplContext.is() )
+ {
+ // no child exists
+ if( IsTokenInNamespace(nElement, XML_NAMESPACE_DRAW) )
+ {
+ sal_uInt16 nFrameType = USHRT_MAX;
+ switch (nElement & TOKEN_MASK)
+ {
+ case XML_TEXT_BOX:
+ nFrameType = XML_TEXT_FRAME_TEXTBOX;
+ break;
+ case XML_IMAGE:
+ nFrameType = XML_TEXT_FRAME_GRAPHIC;
+ break;
+ case XML_OBJECT:
+ nFrameType = XML_TEXT_FRAME_OBJECT;
+ break;
+ case XML_OBJECT_OLE:
+ nFrameType = XML_TEXT_FRAME_OBJECT_OLE;
+ break;
+ case XML_APPLET:
+ nFrameType = XML_TEXT_FRAME_APPLET;
+ break;
+ case XML_PLUGIN:
+ nFrameType = XML_TEXT_FRAME_PLUGIN;
+ break;
+ case XML_FLOATING_FRAME:
+ nFrameType = XML_TEXT_FRAME_FLOATING_FRAME;
+ break;
+ }
+
+ if( USHRT_MAX != nFrameType )
+ {
+ // Shapes in Writer cannot be named via context menu (#i51726#)
+ if ( ( XML_TEXT_FRAME_TEXTBOX == nFrameType ||
+ XML_TEXT_FRAME_GRAPHIC == nFrameType ) &&
+ m_HasAutomaticStyleWithoutParentStyle )
+ {
+ Reference < XShapes > xShapes;
+ xContext = XMLShapeImportHelper::CreateFrameChildContext(
+ GetImport(), nElement, xAttrList, xShapes, m_xAttrList );
+ }
+ else if( XML_TEXT_FRAME_PLUGIN == nFrameType )
+ {
+ bool bMedia = false;
+
+ // check, if we have a media object
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ if( aIter.getToken() == XML_ELEMENT(DRAW, XML_MIME_TYPE) )
+ {
+ if (::comphelper::IsMediaMimeType(aIter.toView()))
+ bMedia = true;
+
+ // leave this loop
+ break;
+ }
+ }
+
+ if( bMedia )
+ {
+ Reference < XShapes > xShapes;
+ xContext = XMLShapeImportHelper::CreateFrameChildContext(
+ GetImport(), nElement, xAttrList, xShapes, m_xAttrList );
+ }
+ }
+ else if( XML_TEXT_FRAME_OBJECT == nFrameType ||
+ XML_TEXT_FRAME_OBJECT_OLE == nFrameType )
+ {
+ m_bSupportsReplacement = true;
+ }
+ else if(XML_TEXT_FRAME_GRAPHIC == nFrameType)
+ {
+ setSupportsMultipleContents( (nElement & TOKEN_MASK) == XML_IMAGE );
+ }
+
+ if (!xContext)
+ {
+ xContext = new XMLTextFrameContext_Impl( GetImport(), nElement,
+ xAttrList,
+ m_eDefaultAnchorType,
+ nFrameType,
+ m_xAttrList );
+ }
+
+ m_xImplContext = xContext;
+
+ if(getSupportsMultipleContents() && XML_TEXT_FRAME_GRAPHIC == nFrameType)
+ {
+ addContent(*m_xImplContext);
+ }
+ }
+ }
+ }
+ else if(getSupportsMultipleContents() && nElement == XML_ELEMENT(DRAW, XML_IMAGE))
+ {
+ // read another image
+ xContext = new XMLTextFrameContext_Impl(
+ GetImport(), nElement, xAttrList,
+ m_eDefaultAnchorType, XML_TEXT_FRAME_GRAPHIC, m_xAttrList, true);
+
+ m_xImplContext = xContext;
+ addContent(*m_xImplContext);
+ }
+ else if( m_bSupportsReplacement && !m_xReplImplContext.is() &&
+ nElement == XML_ELEMENT(DRAW, XML_IMAGE) )
+ {
+ // read replacement image
+ Reference < XPropertySet > xPropSet;
+ if( CreateIfNotThere( xPropSet ) )
+ {
+ xContext = new XMLReplacementImageContext( GetImport(),
+ nElement, xAttrList, xPropSet );
+ m_xReplImplContext = xContext;
+ }
+ }
+ else if( nullptr != dynamic_cast< const XMLTextFrameContext_Impl*>( m_xImplContext.get() ))
+ {
+ // the child is a writer frame
+ if( IsTokenInNamespace(nElement, XML_NAMESPACE_SVG) ||
+ IsTokenInNamespace(nElement, XML_NAMESPACE_SVG_COMPAT) )
+ {
+ // Implement Title/Description Elements UI (#i73249#)
+ const bool bOld = SvXMLImport::OOo_2x >= GetImport().getGeneratorVersion();
+ if ( bOld )
+ {
+ if ( (nElement & TOKEN_MASK) == XML_DESC )
+ {
+ xContext = new XMLTextFrameTitleOrDescContext_Impl( GetImport(),
+ m_sTitle );
+ }
+ }
+ else
+ {
+ if( (nElement & TOKEN_MASK) == XML_TITLE )
+ {
+ if (getSupportsMultipleContents())
+ { // tdf#103567 ensure props are set on surviving shape
+ m_xImplContext = solveMultipleImages();
+ }
+ xContext = new XMLTextFrameTitleOrDescContext_Impl( GetImport(),
+ m_sTitle );
+ }
+ else if ( (nElement & TOKEN_MASK) == XML_DESC )
+ {
+ if (getSupportsMultipleContents())
+ { // tdf#103567 ensure props are set on surviving shape
+ m_xImplContext = solveMultipleImages();
+ }
+ xContext = new XMLTextFrameTitleOrDescContext_Impl( GetImport(),
+ m_sDesc );
+ }
+ }
+ }
+ else if( IsTokenInNamespace(nElement, XML_NAMESPACE_DRAW) )
+ {
+ Reference < XPropertySet > xPropSet;
+ if( (nElement & TOKEN_MASK) == XML_CONTOUR_POLYGON )
+ {
+ if (getSupportsMultipleContents())
+ { // tdf#103567 ensure props are set on surviving shape
+ m_xImplContext = solveMultipleImages();
+ }
+ if( CreateIfNotThere( xPropSet ) )
+ xContext = new XMLTextFrameContourContext_Impl( GetImport(), nElement,
+ xAttrList, xPropSet, false );
+ }
+ else if( (nElement & TOKEN_MASK) == XML_CONTOUR_PATH )
+ {
+ if (getSupportsMultipleContents())
+ { // tdf#103567 ensure props are set on surviving shape
+ m_xImplContext = solveMultipleImages();
+ }
+ if( CreateIfNotThere( xPropSet ) )
+ xContext = new XMLTextFrameContourContext_Impl( GetImport(), nElement,
+ xAttrList, xPropSet, true );
+ }
+ else if( (nElement & TOKEN_MASK) == XML_IMAGE_MAP )
+ {
+ if (getSupportsMultipleContents())
+ { // tdf#103567 ensure props are set on surviving shape
+ m_xImplContext = solveMultipleImages();
+ }
+ if( CreateIfNotThere( xPropSet ) )
+ xContext = new XMLImageMapContext( GetImport(), xPropSet );
+ }
+ }
+ else if( nElement == XML_ELEMENT(OFFICE, XML_EVENT_LISTENERS) )
+ {
+ if (getSupportsMultipleContents())
+ { // tdf#103567 ensure props are set on surviving shape
+ m_xImplContext = solveMultipleImages();
+ }
+ // do we still have the frame object?
+ Reference < XPropertySet > xPropSet;
+ if( CreateIfNotThere( xPropSet ) )
+ {
+ // is it an event supplier?
+ Reference<XEventsSupplier> xEventsSupplier(xPropSet, UNO_QUERY);
+ if (xEventsSupplier.is())
+ {
+ // OK, we have the events, so create the context
+ xContext = new XMLEventsImportContext(GetImport(), xEventsSupplier);
+ }
+ }
+ }
+ }
+ // #i68101#
+ else if( nElement == XML_ELEMENT(SVG, XML_TITLE) || nElement == XML_ELEMENT(SVG, XML_DESC ) ||
+ nElement == XML_ELEMENT(SVG_COMPAT, XML_TITLE) || nElement == XML_ELEMENT(SVG_COMPAT, XML_DESC ) )
+ {
+ if (getSupportsMultipleContents())
+ { // tdf#103567 ensure props are set on surviving shape
+ // note: no more draw:image can be added once we get here
+ m_xImplContext = solveMultipleImages();
+ }
+ xContext = static_cast<SvXMLImportContext*>(m_xImplContext->createFastChildContext( nElement, xAttrList ).get());
+ }
+ else if (nElement == XML_ELEMENT(LO_EXT, XML_SIGNATURELINE))
+ {
+ if (getSupportsMultipleContents())
+ { // tdf#103567 ensure props are set on surviving shape
+ // note: no more draw:image can be added once we get here
+ m_xImplContext = solveMultipleImages();
+ }
+ xContext = static_cast<SvXMLImportContext*>(m_xImplContext->createFastChildContext(nElement, xAttrList).get());
+ }
+ else if (nElement == XML_ELEMENT(LO_EXT, XML_QRCODE))
+ {
+ if (getSupportsMultipleContents())
+ { // tdf#103567 ensure props are set on surviving shape
+ // note: no more draw:image can be added once we get here
+ m_xImplContext = solveMultipleImages();
+ }
+ xContext = static_cast<SvXMLImportContext*>(m_xImplContext->createFastChildContext(nElement, xAttrList).get());
+ }
+ else if (nElement == XML_ELEMENT(DRAW, XML_A))
+ {
+ xContext = static_cast<SvXMLImportContext*>(m_xImplContext->createFastChildContext(nElement, xAttrList).get());
+ }
+ else
+ {
+ // the child is a drawing shape
+ return XMLShapeImportHelper::CreateFrameChildContext(
+ m_xImplContext.get(), nElement, xAttrList );
+ }
+
+ return xContext;
+}
+
+void XMLTextFrameContext::SetHyperlink( const OUString& rHRef,
+ const OUString& rName,
+ const OUString& rTargetFrameName,
+ bool bMap )
+{
+ OSL_ENSURE( !m_pHyperlink, "recursive SetHyperlink call" );
+ m_pHyperlink = std::make_unique<XMLTextFrameContextHyperlink_Impl>(
+ rHRef, rName, rTargetFrameName, bMap );
+}
+
+TextContentAnchorType XMLTextFrameContext::GetAnchorType() const
+{
+ SvXMLImportContext *pContext = m_xImplContext.get();
+ XMLTextFrameContext_Impl *pImpl = dynamic_cast< XMLTextFrameContext_Impl*>( pContext );
+ if( pImpl )
+ return pImpl->GetAnchorType();
+ else
+ return m_eDefaultAnchorType;
+}
+
+Reference < XTextContent > XMLTextFrameContext::GetTextContent() const
+{
+ Reference < XTextContent > xTxtCntnt;
+ SvXMLImportContext *pContext = m_xImplContext.get();
+ XMLTextFrameContext_Impl *pImpl = dynamic_cast< XMLTextFrameContext_Impl* >( pContext );
+ if( pImpl )
+ xTxtCntnt.set( pImpl->GetPropSet(), UNO_QUERY );
+
+ return xTxtCntnt;
+}
+
+Reference < XShape > XMLTextFrameContext::GetShape() const
+{
+ Reference < XShape > xShape;
+ SvXMLImportContext* pContext = m_xImplContext.get();
+ SvXMLShapeContext* pImpl = dynamic_cast<SvXMLShapeContext*>( pContext );
+ if ( pImpl )
+ {
+ xShape = pImpl->getShape();
+ }
+
+ return xShape;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTextFrameContext.hxx b/xmloff/source/text/XMLTextFrameContext.hxx
new file mode 100644
index 0000000000..4f7e01118b
--- /dev/null
+++ b/xmloff/source/text/XMLTextFrameContext.hxx
@@ -0,0 +1,93 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <memory>
+
+#include <com/sun/star/text/TextContentAnchorType.hpp>
+#include <xmloff/xmlictxt.hxx>
+#include <xmlmultiimagehelper.hxx>
+
+namespace com::sun::star {
+ namespace text { class XTextCursor; class XTextContent; }
+}
+
+class XMLTextFrameContextHyperlink_Impl;
+
+class XMLTextFrameContext : public SvXMLImportContext, public MultiImageImportHelper
+{
+ rtl::Reference< sax_fastparser::FastAttributeList > m_xAttrList;
+
+ SvXMLImportContextRef m_xImplContext;
+ SvXMLImportContextRef m_xReplImplContext;
+
+ std::unique_ptr<XMLTextFrameContextHyperlink_Impl> m_pHyperlink;
+ // Implement Title/Description Elements UI (#i73249#)
+ OUString m_sTitle;
+ OUString m_sDesc;
+
+ css::text::TextContentAnchorType m_eDefaultAnchorType;
+
+ /* The <draw:name> can longer be used to distinguish Writer graphic/text box
+ objects and Draw graphic/text box objects.
+ The new distinguish attribute is the parent style of the automatic style
+ of the object. All Draw objects have an automatic style without a parent style.
+ (#i51726#)
+ */
+ bool m_HasAutomaticStyleWithoutParentStyle;
+ bool m_bSupportsReplacement;
+
+ bool CreateIfNotThere( css::uno::Reference < css::beans::XPropertySet >& rPropSet );
+
+protected:
+ /// helper to get the created xShape instance, needs to be overridden
+ void removeGraphicFromImportContext(const SvXMLImportContext& rContext) override;
+ OUString getGraphicPackageURLFromImportContext(const SvXMLImportContext& rContext) const override;
+ OUString getMimeTypeFromImportContext(const SvXMLImportContext& rContext) const override;
+ css::uno::Reference<css::graphic::XGraphic> getGraphicFromImportContext(const SvXMLImportContext& rContext) const override;
+
+public:
+
+
+ XMLTextFrameContext( SvXMLImport& rImport,
+ const css::uno::Reference<
+ css::xml::sax::XFastAttributeList > & xAttrList,
+ css::text::TextContentAnchorType eDfltAnchorType );
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+
+ void SetHyperlink( const OUString& rHRef,
+ const OUString& rName,
+ const OUString& rTargetFrameName,
+ bool bMap );
+
+ css::text::TextContentAnchorType GetAnchorType() const;
+
+ css::uno::Reference < css::text::XTextContent > GetTextContent() const;
+
+ // Frame "to character": anchor moves from first to last char after saving (#i33242#)
+ css::uno::Reference < css::drawing::XShape > GetShape() const;
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTextFrameHyperlinkContext.cxx b/xmloff/source/text/XMLTextFrameHyperlinkContext.cxx
new file mode 100644
index 0000000000..64e16f1470
--- /dev/null
+++ b/xmloff/source/text/XMLTextFrameHyperlinkContext.cxx
@@ -0,0 +1,183 @@
+/* -*- 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/log.hxx>
+#include <sax/tools/converter.hxx>
+
+#include <xmloff/shapeimport.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include "XMLTextFrameContext.hxx"
+#include "XMLTextFrameHyperlinkContext.hxx"
+
+#include <com/sun/star/drawing/XShapes.hpp>
+
+using namespace ::com::sun::star::drawing;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::xml::sax;
+using namespace ::com::sun::star::beans;
+using namespace ::xmloff::token;
+
+namespace drawing = com::sun::star::drawing;
+
+
+XMLTextFrameHyperlinkContext::XMLTextFrameHyperlinkContext(
+ SvXMLImport& rImport,
+ sal_Int32 /*nElement*/,
+ const Reference< XFastAttributeList > & xAttrList,
+ TextContentAnchorType eATyp ) :
+ SvXMLImportContext( rImport ),
+ eDefaultAnchorType( eATyp ),
+ bMap( false )
+{
+ OUString sShow;
+
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ switch( aIter.getToken() )
+ {
+ case XML_ELEMENT(XLINK, XML_HREF):
+ sHRef = GetImport().GetAbsoluteReference( aIter.toString() );
+ break;
+ case XML_ELEMENT(OFFICE, XML_NAME):
+ sName = aIter.toString();
+ break;
+ case XML_ELEMENT(OFFICE, XML_TARGET_FRAME_NAME):
+ sTargetFrameName = aIter.toString();
+ break;
+ case XML_ELEMENT(XLINK, XML_SHOW):
+ sShow = aIter.toString();
+ break;
+ case XML_ELEMENT(OFFICE, XML_SERVER_MAP):
+ {
+ bool bTmp(false);
+ if (::sax::Converter::convertBool( bTmp, aIter.toView() ))
+ {
+ bMap = bTmp;
+ }
+ }
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+
+ if( !sShow.isEmpty() && sTargetFrameName.isEmpty() )
+ {
+ if( IsXMLToken( sShow, XML_NEW ) )
+ sTargetFrameName = "_blank";
+ else if( IsXMLToken( sShow, XML_REPLACE ) )
+ sTargetFrameName = "_self";
+ }
+}
+
+XMLTextFrameHyperlinkContext::~XMLTextFrameHyperlinkContext()
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTextFrameHyperlinkContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList )
+{
+ SvXMLImportContext *pContext = nullptr;
+ XMLTextFrameContext *pTextFrameContext = nullptr;
+
+ switch (nElement)
+ {
+ case XML_ELEMENT(DRAW, XML_FRAME):
+ {
+ pTextFrameContext = new XMLTextFrameContext(GetImport(), xAttrList, eDefaultAnchorType);
+ pTextFrameContext->SetHyperlink(sHRef, sName, sTargetFrameName, bMap);
+ pContext = pTextFrameContext;
+ xFrameContext = pContext;
+ }
+ break;
+ case XML_ELEMENT(DRAW, XML_CUSTOM_SHAPE):
+ case XML_ELEMENT(DRAW, XML_PATH):
+ case XML_ELEMENT(DRAW, XML_ELLIPSE):
+ case XML_ELEMENT(DRAW, XML_LINE):
+ case XML_ELEMENT(DRAW, XML_RECT):
+ case XML_ELEMENT(DRAW, XML_CAPTION):
+ case XML_ELEMENT(DRAW, XML_POLYGON):
+ case XML_ELEMENT(DRAW, XML_POLYLINE):
+ case XML_ELEMENT(DRAW, XML_MEASURE):
+ case XML_ELEMENT(DRAW, XML_CIRCLE):
+ case XML_ELEMENT(DRAW, XML_CONNECTOR):
+ case XML_ELEMENT(DRAW, XML_CONTROL):
+ case XML_ELEMENT(DRAW, XML_PAGE_THUMBNAIL):
+ case XML_ELEMENT(DRAW, XML_G):
+ case XML_ELEMENT(DR3D, XML_SCENE):
+ {
+ Reference<XShapes> xShapes;
+ SvXMLShapeContext* pShapeContext = XMLShapeImportHelper::CreateGroupChildContext(
+ GetImport(), nElement, xAttrList, xShapes);
+ pShapeContext->setHyperlink(sHRef);
+ pContext = pShapeContext;
+ }
+ break;
+ }
+
+ if (!pContext)
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+
+ return pContext;
+}
+
+
+TextContentAnchorType XMLTextFrameHyperlinkContext::GetAnchorType() const
+{
+ if( xFrameContext.is() )
+ {
+ SvXMLImportContext *pContext = xFrameContext.get();
+ return dynamic_cast<XMLTextFrameContext&>(*pContext).GetAnchorType();
+ }
+ else
+ return eDefaultAnchorType;
+
+}
+
+Reference < XTextContent > XMLTextFrameHyperlinkContext::GetTextContent() const
+{
+ Reference <XTextContent > xTxt;
+ if( xFrameContext.is() )
+ {
+ SvXMLImportContext *pContext = xFrameContext.get();
+ xTxt = dynamic_cast<XMLTextFrameContext&>(*pContext).GetTextContent();
+ }
+
+ return xTxt;
+}
+
+// Frame "to character": anchor moves from first to last char after saving (#i33242#)
+Reference < drawing::XShape > XMLTextFrameHyperlinkContext::GetShape() const
+{
+ Reference < drawing::XShape > xShape;
+ if( xFrameContext.is() )
+ {
+ SvXMLImportContext *pContext = xFrameContext.get();
+ xShape = dynamic_cast<XMLTextFrameContext&>(*pContext).GetShape();
+ }
+
+ return xShape;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTextFrameHyperlinkContext.hxx b/xmloff/source/text/XMLTextFrameHyperlinkContext.hxx
new file mode 100644
index 0000000000..a76081632a
--- /dev/null
+++ b/xmloff/source/text/XMLTextFrameHyperlinkContext.hxx
@@ -0,0 +1,62 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/text/XTextContent.hpp>
+#include <com/sun/star/text/TextContentAnchorType.hpp>
+#include <xmloff/xmlictxt.hxx>
+
+namespace com::sun::star {
+ namespace text { class XTextCursor; class XTextFrame; }
+ namespace beans { class XPropertySet; }
+}
+
+/// Used for hyperlinks attached to objects (drawing objects, text boxes, Writer frames)
+class XMLTextFrameHyperlinkContext : public SvXMLImportContext
+{
+ OUString sHRef;
+ OUString sName;
+ OUString sTargetFrameName;
+ css::text::TextContentAnchorType eDefaultAnchorType;
+ SvXMLImportContextRef xFrameContext;
+ bool bMap;
+
+public:
+
+ XMLTextFrameHyperlinkContext( SvXMLImport& rImport,
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList,
+ css::text::TextContentAnchorType eDefaultAnchorType );
+ virtual ~XMLTextFrameHyperlinkContext() override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+
+ css::text::TextContentAnchorType GetAnchorType() const;
+
+ css::uno::Reference < css::text::XTextContent > GetTextContent() const;
+
+ // Frame "to character": anchor moves from first to last char after saving (#i33242#)
+ css::uno::Reference < css::drawing::XShape > GetShape() const;
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTextHeaderFooterContext.cxx b/xmloff/source/text/XMLTextHeaderFooterContext.cxx
new file mode 100644
index 0000000000..786528201d
--- /dev/null
+++ b/xmloff/source/text/XMLTextHeaderFooterContext.cxx
@@ -0,0 +1,190 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/text/XText.hpp>
+#include <com/sun/star/text/XParagraphAppend.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <o3tl/any.hxx>
+#include <XMLTextHeaderFooterContext.hxx>
+#include <xmloff/xmlimp.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::xml::sax;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::beans;
+
+
+XMLTextHeaderFooterContext::XMLTextHeaderFooterContext( SvXMLImport& rImport,
+ const Reference < XPropertySet > & rPageStylePropSet,
+ bool bFooter, bool bLft, bool bFrst ) :
+ SvXMLImportContext( rImport ),
+ xPropSet( rPageStylePropSet ),
+ sOn( bFooter ? OUString("FooterIsOn") : OUString("HeaderIsOn") ),
+ sShareContent( bFooter ? OUString("FooterIsShared") : OUString("HeaderIsShared") ),
+ sText( bFooter ? OUString("FooterText") : OUString("HeaderText") ),
+ sTextFirst(bFooter ? OUString("FooterTextFirst") : OUString("HeaderTextFirst")),
+ sTextLeft( bFooter ? OUString("FooterTextLeft") : OUString("HeaderTextLeft") ),
+ bInsertContent( true ),
+ bLeft( bLft ),
+ bFirst( bFrst )
+{
+ // NOTE: if this ever handles XML_DISPLAY attr then beware of fdo#72850 !
+ if( !(bLeft || bFirst) )
+ return;
+
+ Any aAny = xPropSet->getPropertyValue( sOn );
+ bool bOn = *o3tl::doAccess<bool>(aAny);
+
+ if( bOn )
+ {
+ if (bLeft)
+ {
+ aAny = xPropSet->getPropertyValue( sShareContent );
+ bool bShared = bool();
+ if (!(aAny >>= bShared))
+ assert(false); // should return a value!
+ if( bShared )
+ {
+ // Don't share headers any longer
+ xPropSet->setPropertyValue( sShareContent, Any(false) );
+ }
+ }
+ if (bFirst)
+ {
+ static constexpr OUString sShareContentFirst( u"FirstIsShared"_ustr );
+ aAny = xPropSet->getPropertyValue( sShareContentFirst );
+ bool bSharedFirst = bool();
+ if (!(aAny >>= bSharedFirst))
+ assert(false); // should return a value!
+ if( bSharedFirst )
+ {
+ // Don't share first/right headers any longer
+ xPropSet->setPropertyValue( sShareContentFirst, Any(false) );
+ }
+ }
+ }
+ else
+ {
+ // If headers or footers are switched off, no content must be
+ // inserted.
+ bInsertContent = false;
+ }
+}
+
+XMLTextHeaderFooterContext::~XMLTextHeaderFooterContext()
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTextHeaderFooterContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ SvXMLImportContext *pContext = nullptr;
+ if( bInsertContent )
+ {
+ if( !xOldTextCursor.is() )
+ {
+ bool bRemoveContent = true;
+ Any aAny;
+ if( bLeft || bFirst )
+ {
+ // Headers and footers are switched on already,
+ // and they aren't shared.
+ if (bLeft)
+ aAny = xPropSet->getPropertyValue( sTextLeft );
+ else
+ aAny = xPropSet->getPropertyValue( sTextFirst );
+ }
+ else
+ {
+ aAny = xPropSet->getPropertyValue( sOn );
+ bool bOn = *o3tl::doAccess<bool>(aAny);
+
+ if( !bOn )
+ {
+ // Switch header on
+ xPropSet->setPropertyValue( sOn, Any(true) );
+
+ // The content has not to be removed, because the header
+ // or footer is empty already.
+ bRemoveContent = false;
+ }
+
+ // If a header or footer is not shared, share it now.
+ aAny = xPropSet->getPropertyValue( sShareContent );
+ bool bShared = *o3tl::doAccess<bool>(aAny);
+ if( !bShared )
+ {
+ xPropSet->setPropertyValue( sShareContent, Any(true) );
+ }
+
+ aAny = xPropSet->getPropertyValue( sText );
+ }
+
+ Reference < XText > xText;
+ aAny >>= xText;
+
+ if( bRemoveContent )
+ {
+ xText->setString(OUString());
+ // fdo#82165 shapes anchored at the beginning or end survive
+ // setString("") - kill them the hard way: SwDoc::DelFullPara()
+ uno::Reference<text::XParagraphAppend> const xAppend(
+ xText, uno::UNO_QUERY_THROW);
+ uno::Reference<lang::XComponent> const xPara(
+ xAppend->finishParagraph(
+ uno::Sequence<beans::PropertyValue>()),
+ uno::UNO_QUERY_THROW);
+ xPara->dispose();
+ }
+
+ rtl::Reference < XMLTextImportHelper > xTxtImport =
+ GetImport().GetTextImport();
+
+ xOldTextCursor = xTxtImport->GetCursor();
+ xTxtImport->SetCursor( xText->createTextCursor() );
+ }
+
+ pContext =
+ GetImport().GetTextImport()->CreateTextChildContext(
+ GetImport(), nElement, xAttrList,
+ XMLTextType::HeaderFooter );
+ }
+
+ return pContext;
+}
+
+void XMLTextHeaderFooterContext::endFastElement(sal_Int32 )
+{
+ if( xOldTextCursor.is() )
+ {
+ GetImport().GetTextImport()->DeleteParagraph();
+ GetImport().GetTextImport()->SetCursor( xOldTextCursor );
+ }
+ else if( !bLeft )
+ {
+ // If no content has been inserted into the header or footer,
+ // switch it off.
+ xPropSet->setPropertyValue( sOn, Any(false) );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTextListAutoStylePool.cxx b/xmloff/source/text/XMLTextListAutoStylePool.cxx
new file mode 100644
index 0000000000..affca2cc98
--- /dev/null
+++ b/xmloff/source/text/XMLTextListAutoStylePool.cxx
@@ -0,0 +1,294 @@
+/* -*- 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 <utility>
+#include <vector>
+
+#include <tools/solar.h>
+#include <o3tl/sorted_vector.hxx>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/style/XStyle.hpp>
+#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
+#include <com/sun/star/ucb/XAnyCompareFactory.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/container/XIndexReplace.hpp>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <xmloff/xmlnume.hxx>
+#include <xmloff/XMLTextListAutoStylePool.hxx>
+#include <xmloff/xmlexp.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::style;
+
+
+class XMLTextListAutoStylePoolEntry_Impl
+{
+ OUString sName;
+ OUString sInternalName;
+ Reference < XIndexReplace > xNumRules;
+ sal_uInt32 nPos;
+ bool bIsNamed;
+
+
+public:
+
+ XMLTextListAutoStylePoolEntry_Impl(
+ sal_uInt32 nPos,
+ const Reference < XIndexReplace > & rNumRules,
+ XMLTextListAutoStylePoolNames_Impl& rNames,
+ std::u16string_view rPrefix,
+ sal_uInt32& rName );
+
+ explicit XMLTextListAutoStylePoolEntry_Impl(
+ const Reference < XIndexReplace > & rNumRules ) :
+ xNumRules( rNumRules ),
+ nPos( 0 ),
+ bIsNamed( false )
+ {
+ Reference < XNamed > xNamed( xNumRules, UNO_QUERY );
+ if( xNamed.is() )
+ {
+ sInternalName = xNamed->getName();
+ bIsNamed = true;
+ }
+ }
+
+ explicit XMLTextListAutoStylePoolEntry_Impl(
+ OUString aInternalName ) :
+ sInternalName(std::move( aInternalName )),
+ nPos( 0 ),
+ bIsNamed( true )
+ {
+ }
+
+ const OUString& GetName() const { return sName; }
+ const OUString& GetInternalName() const { return sInternalName; }
+ const Reference < XIndexReplace > & GetNumRules() const { return xNumRules; }
+ sal_uInt32 GetPos() const { return nPos; }
+ bool IsNamed() const { return bIsNamed; }
+};
+
+XMLTextListAutoStylePoolEntry_Impl::XMLTextListAutoStylePoolEntry_Impl(
+ sal_uInt32 nP,
+ const Reference < XIndexReplace > & rNumRules,
+ XMLTextListAutoStylePoolNames_Impl& rNames,
+ std::u16string_view rPrefix,
+ sal_uInt32& rName ) :
+ xNumRules( rNumRules ),
+ nPos( nP ),
+ bIsNamed( false )
+{
+ Reference < XNamed > xNamed( xNumRules, UNO_QUERY );
+ if( xNamed.is() )
+ {
+ sInternalName = xNamed->getName();
+ bIsNamed = true;
+ }
+
+ // create a name that hasn't been used before. The created name has not
+ // to be added to the array, because it will never tried again
+ do
+ {
+ rName++;
+ sName = rPrefix + OUString::number( static_cast<sal_Int32>(rName) );
+ }
+ while (rNames.find(sName) != rNames.end());
+}
+
+namespace {
+
+struct XMLTextListAutoStylePoolEntryCmp_Impl
+{
+ bool operator()(
+ std::unique_ptr<XMLTextListAutoStylePoolEntry_Impl> const& r1,
+ std::unique_ptr<XMLTextListAutoStylePoolEntry_Impl> const& r2 ) const
+ {
+ if( r1->IsNamed() )
+ {
+ if( r2->IsNamed() )
+ return r1->GetInternalName().compareTo( r2->GetInternalName() ) < 0;
+ else
+ return true;
+ }
+ else
+ {
+ if( r2->IsNamed() )
+ return false;
+ else
+ return r1->GetNumRules().get() < r2->GetNumRules().get();
+ }
+ }
+};
+
+}
+
+class XMLTextListAutoStylePool_Impl : public o3tl::sorted_vector<std::unique_ptr<XMLTextListAutoStylePoolEntry_Impl>, XMLTextListAutoStylePoolEntryCmp_Impl> {};
+
+XMLTextListAutoStylePool::XMLTextListAutoStylePool( SvXMLExport& rExp ) :
+ m_rExport( rExp ),
+ m_sPrefix( "L" ),
+ m_pPool( new XMLTextListAutoStylePool_Impl ),
+ m_nName( 0 )
+{
+ Reference<ucb::XAnyCompareFactory> xCompareFac( rExp.GetModel(), uno::UNO_QUERY );
+ if( xCompareFac.is() )
+ mxNumRuleCompare = xCompareFac->createAnyCompareByName( "NumberingRules" );
+ SvXMLExportFlags nExportFlags = m_rExport.getExportFlags();
+ bool bStylesOnly = (nExportFlags & SvXMLExportFlags::STYLES) && !(nExportFlags & SvXMLExportFlags::CONTENT);
+ if( bStylesOnly )
+ m_sPrefix = "ML";
+
+ Reference<XStyleFamiliesSupplier> xFamiliesSupp(m_rExport.GetModel(), UNO_QUERY);
+ SAL_WARN_IF(!xFamiliesSupp.is(), "xmloff", "getStyleFamilies() from XModel failed for export!");
+ Reference< XNameAccess > xFamilies;
+ if (xFamiliesSupp.is())
+ xFamilies = xFamiliesSupp->getStyleFamilies();
+
+ Reference<XIndexAccess> xStyles;
+ static constexpr OUString aNumberStyleName(u"NumberingStyles"_ustr);
+ if (xFamilies.is() && xFamilies->hasByName(aNumberStyleName))
+ xFamilies->getByName(aNumberStyleName) >>= xStyles;
+
+ const sal_Int32 nStyles = xStyles.is() ? xStyles->getCount() : 0;
+ for (sal_Int32 i = 0; i < nStyles; i++)
+ {
+ Reference<XStyle> xStyle;
+ xStyles->getByIndex(i) >>= xStyle;
+ RegisterName(xStyle->getName());
+ }
+}
+
+XMLTextListAutoStylePool::~XMLTextListAutoStylePool()
+{
+}
+
+void XMLTextListAutoStylePool::RegisterName( const OUString& rName )
+{
+ m_aNames.insert(rName);
+}
+
+sal_uInt32 XMLTextListAutoStylePool::Find( const XMLTextListAutoStylePoolEntry_Impl* pEntry ) const
+{
+ if( !pEntry->IsNamed() && mxNumRuleCompare.is() )
+ {
+ const sal_uInt32 nCount = m_pPool->size();
+
+ uno::Any aAny1, aAny2;
+ aAny1 <<= pEntry->GetNumRules();
+
+ for( sal_uInt32 nPos = 0; nPos < nCount; nPos++ )
+ {
+ aAny2 <<= (*m_pPool)[nPos]->GetNumRules();
+
+ if( mxNumRuleCompare->compare( aAny1, aAny2 ) == 0 )
+ return nPos;
+ }
+ }
+ else
+ {
+ XMLTextListAutoStylePool_Impl::const_iterator it = m_pPool->find( pEntry );
+ if( it != m_pPool->end() )
+ return it - m_pPool->begin();
+ }
+
+ return sal_uInt32(-1);
+}
+
+OUString XMLTextListAutoStylePool::Add(
+ const Reference < XIndexReplace > & rNumRules )
+{
+ OUString sName;
+ XMLTextListAutoStylePoolEntry_Impl aTmp( rNumRules );
+
+ sal_uInt32 nPos = Find( &aTmp );
+ if( nPos != sal_uInt32(-1) )
+ {
+ sName = (*m_pPool)[ nPos ]->GetName();
+ }
+ else
+ {
+ std::unique_ptr<XMLTextListAutoStylePoolEntry_Impl> pEntry(
+ new XMLTextListAutoStylePoolEntry_Impl( m_pPool->size(),
+ rNumRules, m_aNames, m_sPrefix,
+ m_nName ));
+ sName = pEntry->GetName();
+ m_pPool->insert( std::move(pEntry) );
+ }
+
+ return sName;
+}
+
+OUString XMLTextListAutoStylePool::Find(
+ const Reference < XIndexReplace > & rNumRules ) const
+{
+ OUString sName;
+ XMLTextListAutoStylePoolEntry_Impl aTmp( rNumRules );
+
+ sal_uInt32 nPos = Find( &aTmp );
+ if( nPos != sal_uInt32(-1) )
+ sName = (*m_pPool)[ nPos ]->GetName();
+
+ return sName;
+}
+
+OUString XMLTextListAutoStylePool::Find(
+ const OUString& rInternalName ) const
+{
+ OUString sName;
+ XMLTextListAutoStylePoolEntry_Impl aTmp( rInternalName );
+ sal_uInt32 nPos = Find( &aTmp );
+ if( nPos != sal_uInt32(-1) )
+ sName = (*m_pPool)[ nPos ]->GetName();
+
+ return sName;
+}
+
+void XMLTextListAutoStylePool::exportXML() const
+{
+ sal_uInt32 nCount = m_pPool->size();
+ if( !nCount )
+ return;
+
+ std::vector<XMLTextListAutoStylePoolEntry_Impl*> aExpEntries(nCount);
+
+ sal_uInt32 i;
+ for( i=0; i < nCount; i++ )
+ {
+ XMLTextListAutoStylePoolEntry_Impl *pEntry = (*m_pPool)[i].get();
+ SAL_WARN_IF( pEntry->GetPos() >= nCount, "xmloff", "Illegal pos" );
+ aExpEntries[pEntry->GetPos()] = pEntry;
+ }
+
+ SvxXMLNumRuleExport aNumRuleExp( m_rExport );
+
+ for( i=0; i < nCount; i++ )
+ {
+ XMLTextListAutoStylePoolEntry_Impl *pEntry = aExpEntries[i];
+ aNumRuleExp.exportNumberingRule( pEntry->GetName(), false,
+ pEntry->GetNumRules() );
+ }
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTextListBlockContext.cxx b/xmloff/source/text/XMLTextListBlockContext.cxx
new file mode 100644
index 0000000000..ffacadf6cf
--- /dev/null
+++ b/xmloff/source/text/XMLTextListBlockContext.cxx
@@ -0,0 +1,277 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/container/XIndexReplace.hpp>
+#include <com/sun/star/style/XStyle.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include "XMLTextListItemContext.hxx"
+#include "XMLTextListBlockContext.hxx"
+#include <txtlists.hxx>
+#include <sal/log.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::style;
+using namespace ::com::sun::star::beans;
+using namespace ::xmloff::token;
+
+
+// OD 2008-05-07 #refactorlists#
+// add optional parameter <bRestartNumberingAtSubList> and its handling
+XMLTextListBlockContext::XMLTextListBlockContext(
+ SvXMLImport& rImport,
+ XMLTextImportHelper& rTxtImp,
+ const Reference< xml::sax::XFastAttributeList > & xAttrList,
+ const bool bRestartNumberingAtSubList )
+: SvXMLImportContext( rImport )
+, mrTxtImport( rTxtImp )
+, mnLevel( 0 )
+, mbRestartNumbering( false )
+, mbSetDefaults( false )
+{
+ static constexpr OUString s_PropNameDefaultListId = u"DefaultListId"_ustr;
+ {
+ // get the parent list block context (if any); this is a bit ugly...
+ XMLTextListBlockContext * pLB(nullptr);
+ XMLTextListItemContext * pLI(nullptr);
+ XMLNumberedParaContext * pNP(nullptr);
+ rTxtImp.GetTextListHelper().ListContextTop(pLB, pLI, pNP);
+ mxParentListBlock = pLB;
+ }
+ // Inherit style name from parent list, as well as the flags whether
+ // numbering must be restarted and formats have to be created.
+ OUString sParentListStyleName;
+ if( mxParentListBlock.is() )
+ {
+ XMLTextListBlockContext *pParent = mxParentListBlock.get();
+ msListStyleName = pParent->msListStyleName;
+ sParentListStyleName = msListStyleName;
+ mxNumRules = pParent->GetNumRules();
+ mnLevel = pParent->GetLevel() + 1;
+ mbRestartNumbering = pParent->IsRestartNumbering() ||
+ bRestartNumberingAtSubList;
+ mbSetDefaults = pParent->mbSetDefaults;
+ msListId = pParent->GetListId();
+ msContinueListId = pParent->GetContinueListId();
+ }
+
+ bool bIsContinueNumberingAttributePresent( false );
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ switch( aIter.getToken() )
+ {
+ case XML_ELEMENT(XML, XML_ID):
+//FIXME: there is no UNO API for lists
+ // xml:id is also the list ID (#i92221#)
+ if ( mnLevel == 0 ) // root <list> element
+ {
+ msListId = aIter.toString();
+ }
+ break;
+ case XML_ELEMENT(TEXT, XML_CONTINUE_NUMBERING):
+ mbRestartNumbering = !IsXMLToken(aIter, XML_TRUE);
+ bIsContinueNumberingAttributePresent = true;
+ break;
+ case XML_ELEMENT(TEXT, XML_STYLE_NAME):
+ msListStyleName = aIter.toString();
+ break;
+ case XML_ELEMENT(TEXT, XML_CONTINUE_LIST):
+ if ( mnLevel == 0 ) // root <list> element
+ {
+ msContinueListId = aIter.toString();
+ }
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+
+ // Remember this list block.
+ mrTxtImport.GetTextListHelper().PushListContext( this );
+ try
+ {
+ mxNumRules = XMLTextListsHelper::MakeNumRule(GetImport(), mxNumRules,
+ sParentListStyleName, msListStyleName,
+ mnLevel, &mbRestartNumbering, &mbSetDefaults );
+ if( !mxNumRules.is() )
+ return;
+
+ if ( mnLevel != 0 ) // root <list> element
+ return;
+
+ XMLTextListsHelper& rTextListsHelper( mrTxtImport.GetTextListHelper() );
+ // Inconsistent behavior regarding lists (#i92811#)
+ OUString sListStyleDefaultListId;
+ {
+ uno::Reference< beans::XPropertySet > xNumRuleProps( mxNumRules, UNO_QUERY );
+ if ( xNumRuleProps.is() )
+ {
+ uno::Reference< beans::XPropertySetInfo > xNumRulePropSetInfo(
+ xNumRuleProps->getPropertySetInfo());
+ if (xNumRulePropSetInfo.is() &&
+ xNumRulePropSetInfo->hasPropertyByName(
+ s_PropNameDefaultListId))
+ {
+ xNumRuleProps->getPropertyValue(s_PropNameDefaultListId)
+ >>= sListStyleDefaultListId;
+ SAL_WARN_IF( sListStyleDefaultListId.isEmpty(), "xmloff",
+ "no default list id found at numbering rules instance. Serious defect." );
+ }
+ }
+ }
+ if ( msListId.isEmpty() ) // no text:id property found
+ {
+ sal_Int32 nUPD( 0 );
+ sal_Int32 nBuild( 0 );
+ const bool bBuildIdFound = GetImport().getBuildIds( nUPD, nBuild );
+ if ( rImport.IsTextDocInOOoFileFormat() ||
+ ( bBuildIdFound && nUPD == 680 ) )
+ {
+ /* handling former documents written by OpenOffice.org:
+ use default list id of numbering rules instance, if existing
+ (#i92811#)
+ */
+ if ( !sListStyleDefaultListId.isEmpty() )
+ {
+ msListId = sListStyleDefaultListId;
+ if ( !bIsContinueNumberingAttributePresent &&
+ !mbRestartNumbering &&
+ rTextListsHelper.IsListProcessed( msListId ) )
+ {
+ mbRestartNumbering = true;
+ }
+ }
+ }
+ if ( msListId.isEmpty() )
+ {
+ // generate a new list id for the list
+ msListId = rTextListsHelper.GenerateNewListId();
+ }
+ }
+
+ if ( bIsContinueNumberingAttributePresent && !mbRestartNumbering &&
+ msContinueListId.isEmpty() )
+ {
+ const OUString& Last( rTextListsHelper.GetLastProcessedListId() );
+ if ( rTextListsHelper.GetListStyleOfLastProcessedList() == msListStyleName
+ && Last != msListId )
+ {
+ msContinueListId = Last;
+ }
+ }
+
+ bool bContinueNumbering = bIsContinueNumberingAttributePresent && !mbRestartNumbering;
+ if (msContinueListId.isEmpty() && bContinueNumbering && GetImport().IsMSO())
+ {
+ // No "continue list" id, but continue numbering was requested. Connect to the last list of
+ // the same list style in the Word case, even if there was a different list in the meantime.
+ msContinueListId = rTextListsHelper.GetLastIdOfStyleName(msListStyleName);
+ }
+
+ if ( !msContinueListId.isEmpty() )
+ {
+ if ( !rTextListsHelper.IsListProcessed( msContinueListId ) )
+ {
+ msContinueListId.clear();
+ }
+ else
+ {
+ // search continue list chain for master list and
+ // continue the master list.
+ OUString sTmpStr =
+ rTextListsHelper.GetContinueListIdOfProcessedList( msContinueListId );
+ while ( !sTmpStr.isEmpty() )
+ {
+ msContinueListId = sTmpStr;
+
+ sTmpStr =
+ rTextListsHelper.GetContinueListIdOfProcessedList( msContinueListId );
+ }
+ }
+ }
+
+ if ( !rTextListsHelper.IsListProcessed( msListId ) )
+ {
+ // Inconsistent behavior regarding lists (#i92811#)
+ rTextListsHelper.KeepListAsProcessed(
+ msListId, msListStyleName, msContinueListId,
+ sListStyleDefaultListId );
+ }
+ }
+ catch (uno::Exception&)
+ {
+ // pop ourselves if anything goes wrong to avoid use-after-free
+ rTxtImp.GetTextListHelper().PopListContext();
+ throw;
+ }
+}
+
+XMLTextListBlockContext::~XMLTextListBlockContext()
+{
+}
+
+void XMLTextListBlockContext::endFastElement(sal_Int32 )
+{
+ // Numbering has not to be restarted if it has been restarted within
+ // a child list.
+ XMLTextListBlockContext *pParent = mxParentListBlock.get();
+ if( pParent )
+ {
+ pParent->mbRestartNumbering = mbRestartNumbering;
+ }
+
+ // Restore current list block.
+ mrTxtImport.GetTextListHelper().PopListContext();
+
+ // Any paragraph following the list within the same list item must not
+ // be numbered.
+ mrTxtImport.GetTextListHelper().SetListItem( nullptr );
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTextListBlockContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ SvXMLImportContext *pContext = nullptr;
+
+ bool bHeader = false;
+ switch( nElement )
+ {
+ case XML_ELEMENT(TEXT, XML_LIST_HEADER):
+ bHeader = true;
+ [[fallthrough]];
+ case XML_ELEMENT(TEXT, XML_LIST_ITEM):
+ pContext = new XMLTextListItemContext( GetImport(), mrTxtImport,
+ xAttrList, bHeader );
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ }
+
+ return pContext;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTextListBlockContext.hxx b/xmloff/source/text/XMLTextListBlockContext.hxx
new file mode 100644
index 0000000000..4b18d625cc
--- /dev/null
+++ b/xmloff/source/text/XMLTextListBlockContext.hxx
@@ -0,0 +1,78 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/container/XIndexReplace.hpp>
+#include <xmloff/xmlictxt.hxx>
+
+class XMLTextImportHelper;
+
+class XMLTextListBlockContext : public SvXMLImportContext
+{
+ XMLTextImportHelper& mrTxtImport;
+
+ css::uno::Reference< css::container::XIndexReplace > mxNumRules;
+
+ // text:style-name property of <list> element
+ OUString msListStyleName;
+
+ rtl::Reference<XMLTextListBlockContext> mxParentListBlock;
+
+ sal_Int16 mnLevel;
+ bool mbRestartNumbering;
+ bool mbSetDefaults;
+
+ // text:id property of <list> element, only valid for root <list> element
+ OUString msListId;
+ // text:continue-list property of <list> element, only valid for root <list> element
+ OUString msContinueListId;
+
+public:
+
+
+ // add optional parameter <bRestartNumberingAtSubList>
+ XMLTextListBlockContext(
+ SvXMLImport& rImport,
+ XMLTextImportHelper& rTxtImp,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList,
+ const bool bRestartNumberingAtSubList = false );
+ virtual ~XMLTextListBlockContext() override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+
+ sal_Int16 GetLevel() const { return mnLevel; }
+ bool IsRestartNumbering() const { return mbRestartNumbering; }
+ void ResetRestartNumbering() { mbRestartNumbering = false; }
+
+ /// does this list have (possibly inherited from parent) list-style-name?
+ bool HasListStyleName() { return !msListStyleName.isEmpty(); }
+ const css::uno::Reference < css::container::XIndexReplace >& GetNumRules() const
+ { return mxNumRules; }
+
+ const OUString& GetListId() const { return msListId;}
+ const OUString& GetContinueListId() const { return msContinueListId;}
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTextListItemContext.cxx b/xmloff/source/text/XMLTextListItemContext.cxx
new file mode 100644
index 0000000000..1ef6736fa8
--- /dev/null
+++ b/xmloff/source/text/XMLTextListItemContext.cxx
@@ -0,0 +1,152 @@
+/* -*- 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 <xmloff/xmlimp.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include "txtparai.hxx"
+#include <txtlists.hxx>
+#include "XMLTextListBlockContext.hxx"
+#include <xmloff/txtimp.hxx>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/style/XStyle.hpp>
+#include <xmloff/xmlnumi.hxx>
+#include <xmloff/ProgressBarHelper.hxx>
+#include "XMLTextListItemContext.hxx"
+#include <sal/log.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::xmloff::token;
+
+
+XMLTextListItemContext::XMLTextListItemContext(
+ SvXMLImport& rImport,
+ XMLTextImportHelper& rTxtImp,
+ const Reference< xml::sax::XFastAttributeList > & xAttrList,
+ const bool bIsHeader )
+ : SvXMLImportContext( rImport ),
+ rTxtImport( rTxtImp ),
+ nStartValue( -1 ),
+ mnSubListCount( 0 )
+{
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ if( !bIsHeader && aIter.getToken() == XML_ELEMENT(TEXT, XML_START_VALUE) )
+ {
+ sal_Int32 nTmp = aIter.toInt32();
+ if( nTmp >= 0 && nTmp <= SHRT_MAX )
+ nStartValue = static_cast<sal_Int16>(nTmp);
+ }
+ else if ( aIter.getToken() == XML_ELEMENT(TEXT, XML_STYLE_OVERRIDE) )
+ {
+ OUString sListStyleOverrideName = aIter.toString();
+ if ( !sListStyleOverrideName.isEmpty() )
+ {
+ OUString sDisplayStyleName(
+ GetImport().GetStyleDisplayName( XmlStyleFamily::TEXT_LIST,
+ sListStyleOverrideName ) );
+ const Reference < container::XNameContainer >& rNumStyles =
+ rTxtImp.GetNumberingStyles();
+ if( rNumStyles.is() && rNumStyles->hasByName( sDisplayStyleName ) )
+ {
+ Reference < style::XStyle > xStyle;
+ Any aAny = rNumStyles->getByName( sDisplayStyleName );
+ aAny >>= xStyle;
+
+ uno::Reference< beans::XPropertySet > xPropSet( xStyle, UNO_QUERY );
+ aAny = xPropSet->getPropertyValue("NumberingRules");
+ aAny >>= mxNumRulesOverride;
+ }
+ else
+ {
+ const SvxXMLListStyleContext* pListStyle =
+ rTxtImp.FindAutoListStyle( sListStyleOverrideName );
+ if( pListStyle )
+ {
+ mxNumRulesOverride = pListStyle->GetNumRules();
+ if( !mxNumRulesOverride.is() )
+ {
+ pListStyle->CreateAndInsertAuto();
+ mxNumRulesOverride = pListStyle->GetNumRules();
+ }
+ }
+ }
+ }
+ }
+ else if ( aIter.getToken() == XML_ELEMENT(XML, XML_ID) )
+ {
+//FIXME: there is no UNO API for list items
+ }
+ else
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+
+ // If this is a <text:list-item> element, then remember it as a sign
+ // that a bullet has to be generated.
+ if( !bIsHeader ) {
+ rTxtImport.GetTextListHelper().SetListItem( this );
+ }
+
+}
+
+XMLTextListItemContext::~XMLTextListItemContext()
+{
+}
+
+void XMLTextListItemContext::endFastElement(sal_Int32 )
+{
+ // finish current list item
+ rTxtImport.GetTextListHelper().SetListItem( nullptr );
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTextListItemContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ SvXMLImportContext *pContext = nullptr;
+
+ switch( nElement )
+ {
+ case XML_ELEMENT(TEXT, XML_H):
+ case XML_ELEMENT(TEXT, XML_P):
+ case XML_ELEMENT(LO_EXT, XML_P):
+ pContext = new XMLParaContext( GetImport(), nElement,
+ xAttrList );
+ if (rTxtImport.IsProgress())
+ GetImport().GetProgressBarHelper()->Increment();
+
+ break;
+ case XML_ELEMENT(TEXT, XML_LIST):
+ ++mnSubListCount;
+ pContext = new XMLTextListBlockContext( GetImport(), rTxtImport,
+ xAttrList,
+ (mnSubListCount > 1) );
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ }
+
+ return pContext;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTextListItemContext.hxx b/xmloff/source/text/XMLTextListItemContext.hxx
new file mode 100644
index 0000000000..de43d90f9b
--- /dev/null
+++ b/xmloff/source/text/XMLTextListItemContext.hxx
@@ -0,0 +1,69 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/container/XIndexReplace.hpp>
+
+#include <xmloff/xmlictxt.hxx>
+
+class XMLTextImportHelper;
+
+class XMLTextListItemContext : public SvXMLImportContext
+{
+ XMLTextImportHelper& rTxtImport;
+
+ sal_Int16 nStartValue;
+
+ // quantity of <text:list> child elements
+ sal_Int16 mnSubListCount;
+ // list style instance for text::style-override property
+ css::uno::Reference< css::container::XIndexReplace > mxNumRulesOverride;
+
+public:
+
+
+ XMLTextListItemContext(
+ SvXMLImport& rImport,
+ XMLTextImportHelper& rTxtImp,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList,
+ const bool bIsHeader );
+ virtual ~XMLTextListItemContext() override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+
+ bool HasStartValue() const { return -1 != nStartValue; }
+ sal_Int16 GetStartValue() const { return nStartValue; }
+
+ bool HasNumRulesOverride() const
+ {
+ return mxNumRulesOverride.is();
+ }
+ const css::uno::Reference < css::container::XIndexReplace >& GetNumRulesOverride() const
+ {
+ return mxNumRulesOverride;
+ }
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTextMarkImportContext.cxx b/xmloff/source/text/XMLTextMarkImportContext.cxx
new file mode 100644
index 0000000000..96a694cf1d
--- /dev/null
+++ b/xmloff/source/text/XMLTextMarkImportContext.cxx
@@ -0,0 +1,585 @@
+/* -*- 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 "XMLTextMarkImportContext.hxx"
+
+
+#include <rtl/ustring.hxx>
+#include <sal/log.hxx>
+#include <osl/diagnose.h>
+#include <sax/tools/converter.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/odffields.hxx>
+#include <xmloff/xmlement.hxx>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/xml/sax/XAttributeList.hpp>
+#include <com/sun/star/text/ControlCharacter.hpp>
+#include <com/sun/star/text/XTextContent.hpp>
+#include <com/sun/star/text/XTextRangeCompare.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/rdf/XMetadatable.hpp>
+
+#include <com/sun/star/text/XFormField.hpp>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <RDFaImportHelper.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::xml::sax;
+using namespace ::xmloff::token;
+
+
+XMLFieldParamImportContext::XMLFieldParamImportContext(
+ SvXMLImport& rImport,
+ XMLTextImportHelper& rHlp ) :
+ SvXMLImportContext(rImport),
+ rHelper(rHlp)
+{
+}
+
+
+void XMLFieldParamImportContext::startFastElement(sal_Int32 /*nElement*/, const css::uno::Reference< css::xml::sax::XFastAttributeList> & xAttrList)
+{
+ OUString sName;
+ OUString sValue;
+
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
+ {
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(FIELD, XML_NAME):
+ sName = aIter.toString();
+ break;
+ case XML_ELEMENT(FIELD, XML_VALUE):
+ sValue = aIter.toString();
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+ if (rHelper.hasCurrentFieldCtx() && !sName.isEmpty()) {
+ rHelper.addFieldParam(sName, sValue);
+ }
+}
+
+
+XMLTextMarkImportContext::XMLTextMarkImportContext(
+ SvXMLImport& rImport,
+ XMLTextImportHelper& rHlp,
+ uno::Reference<uno::XInterface> & io_rxCrossRefHeadingBookmark )
+ : SvXMLImportContext(rImport)
+ , m_rHelper(rHlp)
+ , m_rxCrossRefHeadingBookmark(io_rxCrossRefHeadingBookmark)
+ , m_isHidden(false)
+ , m_bHaveAbout(false)
+{
+}
+
+namespace {
+
+enum lcl_MarkType { TypeReference, TypeReferenceStart, TypeReferenceEnd,
+ TypeBookmark, TypeBookmarkStart, TypeBookmarkEnd,
+ TypeFieldmark, TypeFieldmarkStart, TypeFieldmarkSeparator, TypeFieldmarkEnd
+ };
+
+}
+
+SvXMLEnumMapEntry<lcl_MarkType> const lcl_aMarkTypeMap[] =
+{
+ { XML_REFERENCE_MARK, TypeReference },
+ { XML_REFERENCE_MARK_START, TypeReferenceStart },
+ { XML_REFERENCE_MARK_END, TypeReferenceEnd },
+ { XML_BOOKMARK, TypeBookmark },
+ { XML_BOOKMARK_START, TypeBookmarkStart },
+ { XML_BOOKMARK_END, TypeBookmarkEnd },
+ { XML_FIELDMARK, TypeFieldmark },
+ { XML_FIELDMARK_START, TypeFieldmarkStart },
+ { XML_FIELDMARK_SEPARATOR, TypeFieldmarkSeparator },
+ { XML_FIELDMARK_END, TypeFieldmarkEnd },
+ { XML_TOKEN_INVALID, lcl_MarkType(0) },
+};
+
+
+static OUString lcl_getFormFieldmarkName(std::u16string_view name)
+{
+ if (name == ODF_FORMCHECKBOX ||
+ name == u"msoffice.field.FORMCHECKBOX" ||
+ name == u"ecma.office-open-xml.field.FORMCHECKBOX")
+ return ODF_FORMCHECKBOX;
+ else if (name == ODF_FORMDROPDOWN ||
+ name == u"ecma.office-open-xml.field.FORMDROPDOWN")
+ return ODF_FORMDROPDOWN;
+ else
+ return OUString();
+}
+
+static OUString lcl_getFieldmarkName(OUString const& name)
+{
+ if (name == "msoffice.field.FORMTEXT" ||
+ name == "ecma.office-open-xml.field.FORMTEXT")
+ return ODF_FORMTEXT;
+ else
+ return name;
+}
+
+
+void XMLTextMarkImportContext::startFastElement( sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ if (!FindName(xAttrList))
+ {
+ m_sBookmarkName.clear();
+ }
+
+ if ((nElement & TOKEN_MASK) == XML_FIELDMARK_START ||
+ (nElement & TOKEN_MASK) == XML_FIELDMARK)
+ {
+ if (m_sBookmarkName.isEmpty())
+ {
+ m_sBookmarkName = "Unknown";
+ }
+ m_rHelper.pushFieldCtx( m_sBookmarkName, m_sFieldName );
+ }
+
+ if ((nElement & TOKEN_MASK) == XML_BOOKMARK_START)
+ {
+ m_rHelper.setBookmarkAttributes(m_sBookmarkName, m_isHidden, m_sCondition);
+ }
+}
+
+static auto InsertFieldmark(SvXMLImport & rImport,
+ XMLTextImportHelper & rHelper, bool const isFieldmarkSeparatorMissing) -> void
+{
+ assert(rHelper.hasCurrentFieldCtx()); // was set up in StartElement()
+
+ // fdo#86795 check if it's actually a checkbox first
+ auto const [ name, type ] = rHelper.getCurrentFieldType();
+ OUString const fieldmarkTypeName = lcl_getFieldmarkName(type);
+ if (fieldmarkTypeName == ODF_FORMCHECKBOX ||
+ fieldmarkTypeName == ODF_FORMDROPDOWN)
+ { // sw can't handle checkbox with start+end
+ SAL_INFO("xmloff.text", "invalid fieldmark-start/fieldmark-end ignored");
+ return;
+ }
+
+ uno::Reference<text::XTextRange> const xStartRange(rHelper.getCurrentFieldStart());
+ uno::Reference<text::XTextCursor> const xCursor(
+ rHelper.GetText()->createTextCursorByRange(xStartRange));
+ uno::Reference<text::XTextRangeCompare> const xCompare(rHelper.GetText(), uno::UNO_QUERY);
+ if (xCompare->compareRegionStarts(xStartRange, rHelper.GetCursorAsRange()) < 0)
+ {
+ SAL_WARN("xmloff.text", "invalid field mark positions");
+ assert(false);
+ }
+ xCursor->gotoRange(rHelper.GetCursorAsRange(), true);
+
+ Reference<XTextContent> const xContent = XMLTextMarkImportContext::CreateAndInsertMark(
+ rImport, "com.sun.star.text.Fieldmark", name, xCursor,
+ OUString(), isFieldmarkSeparatorMissing);
+
+ if (!xContent.is())
+ return;
+
+ // setup fieldmark...
+ Reference<text::XFormField> const xFormField(xContent, UNO_QUERY);
+ assert(xFormField.is());
+ try {
+ xFormField->setFieldType(fieldmarkTypeName);
+ } catch (uno::RuntimeException const&) {
+ // tdf#140437 somehow old documents had the field code in the type
+ // attribute instead of field:param
+ SAL_INFO("xmloff.text", "invalid fieldmark type, converting to param");
+ // add without checking: FieldParamImporter::Import() catches ElementExistException
+ rHelper.addFieldParam(ODF_CODE_PARAM, fieldmarkTypeName);
+ xFormField->setFieldType(ODF_UNHANDLED);
+ }
+ rHelper.setCurrentFieldParamsTo(xFormField);
+ // move cursor after setFieldType as that may delete/re-insert
+ rHelper.GetCursor()->gotoRange(xContent->getAnchor()->getEnd(), false);
+ rHelper.GetCursor()->goLeft(1, false); // move before CH_TXT_ATR_FIELDEND
+ // tdf#129520: AppendTextNode() ignores the content index!
+ // plan B: insert a spurious paragraph break now and join
+ // it in PopFieldmark()!
+ rHelper.GetText()->insertControlCharacter(rHelper.GetCursor(),
+ text::ControlCharacter::PARAGRAPH_BREAK, false);
+ rHelper.GetCursor()->goLeft(1, false); // back to previous paragraph
+}
+
+static auto PopFieldmark(XMLTextImportHelper & rHelper) -> void
+{
+ // can't verify name because it's not written as an attribute...
+ uno::Reference<text::XTextContent> const xField(rHelper.popFieldCtx(),
+ uno::UNO_QUERY);
+ if (!xField.is())
+ return;
+
+ if (rHelper.GetText() == xField->getAnchor()->getText())
+ {
+ try
+ { // skip CH_TXT_ATR_FIELDEND
+ rHelper.GetCursor()->goRight(1, true);
+ rHelper.GetCursor()->setString(OUString()); // undo AppendTextNode from InsertFieldmark
+ rHelper.GetCursor()->gotoRange(xField->getAnchor()->getEnd(), false);
+ }
+ catch (uno::Exception const&)
+ {
+ assert(false); // must succeed
+ }
+ }
+ else
+ {
+ SAL_INFO("xmloff.text", "fieldmark has invalid positions");
+ // could either dispose it or leave it to end at the end of the document?
+ xField->dispose();
+ }
+}
+
+void XMLTextMarkImportContext::endFastElement(sal_Int32 nElement)
+{
+ static constexpr OUString sAPI_bookmark = u"com.sun.star.text.Bookmark"_ustr;
+
+ lcl_MarkType nTmp{};
+ if (!SvXMLUnitConverter::convertEnum(nTmp, SvXMLImport::getNameFromToken(nElement), lcl_aMarkTypeMap))
+ return;
+
+ if (m_sBookmarkName.isEmpty() && TypeFieldmarkEnd != nTmp && TypeFieldmarkSeparator != nTmp)
+ return;
+
+ switch (nTmp)
+ {
+ case TypeReference:
+ // export point reference mark
+ CreateAndInsertMark(GetImport(),
+ "com.sun.star.text.ReferenceMark",
+ m_sBookmarkName,
+ m_rHelper.GetCursorAsRange()->getStart());
+ break;
+
+ case TypeBookmark:
+ {
+ // tdf#94804: detect duplicate heading cross reference bookmarks
+ if (m_sBookmarkName.startsWith("__RefHeading__"))
+ {
+ if (m_rxCrossRefHeadingBookmark.is())
+ {
+ uno::Reference<container::XNamed> const xNamed(
+ m_rxCrossRefHeadingBookmark, uno::UNO_QUERY);
+ m_rHelper.AddCrossRefHeadingMapping(
+ m_sBookmarkName, xNamed->getName());
+ break; // don't insert
+ }
+ }
+ }
+ [[fallthrough]];
+ case TypeFieldmark:
+ {
+ const OUString formFieldmarkName=lcl_getFormFieldmarkName(m_sFieldName);
+ bool bImportAsField = (nTmp==TypeFieldmark && !formFieldmarkName.isEmpty()); //@TODO handle abbreviation cases...
+ // export point bookmark
+ const Reference<XInterface> xContent(
+ CreateAndInsertMark(GetImport(),
+ (bImportAsField ? OUString("com.sun.star.text.FormFieldmark") : sAPI_bookmark),
+ m_sBookmarkName,
+ m_rHelper.GetCursorAsRange()->getStart(),
+ m_sXmlId) );
+ if (nTmp==TypeFieldmark) {
+ if (xContent.is() && bImportAsField) {
+ // setup fieldmark...
+ Reference< css::text::XFormField> xFormField(xContent, UNO_QUERY);
+ xFormField->setFieldType(formFieldmarkName);
+ if (xFormField.is() && m_rHelper.hasCurrentFieldCtx()) {
+ m_rHelper.setCurrentFieldParamsTo(xFormField);
+ }
+ }
+ m_rHelper.popFieldCtx();
+ }
+ if (TypeBookmark == nTmp
+ && m_sBookmarkName.startsWith("__RefHeading__"))
+ {
+ assert(xContent.is());
+ m_rxCrossRefHeadingBookmark = xContent;
+ }
+ }
+ break;
+
+ case TypeBookmarkStart:
+ // save XTextRange for later construction of bookmark
+ {
+ std::shared_ptr< ::xmloff::ParsedRDFaAttributes >
+ xRDFaAttributes;
+ if (m_bHaveAbout && TypeBookmarkStart == nTmp)
+ {
+ xRDFaAttributes =
+ GetImport().GetRDFaImportHelper().ParseRDFa(
+ m_sAbout, m_sProperty,
+ m_sContent, m_sDatatype);
+ }
+ m_rHelper.InsertBookmarkStartRange(
+ m_sBookmarkName,
+ m_rHelper.GetCursorAsRange()->getStart(),
+ m_sXmlId, xRDFaAttributes);
+ }
+ break;
+
+ case TypeBookmarkEnd:
+ {
+ // tdf#94804: detect duplicate heading cross reference bookmarks
+ if (m_sBookmarkName.startsWith("__RefHeading__"))
+ {
+ if (m_rxCrossRefHeadingBookmark.is())
+ {
+ uno::Reference<container::XNamed> const xNamed(
+ m_rxCrossRefHeadingBookmark, uno::UNO_QUERY);
+ m_rHelper.AddCrossRefHeadingMapping(
+ m_sBookmarkName, xNamed->getName());
+ break; // don't insert
+ }
+ }
+
+ // get old range, and construct
+ Reference<XTextRange> xStartRange;
+ std::shared_ptr< ::xmloff::ParsedRDFaAttributes >
+ xRDFaAttributes;
+ if (m_rHelper.FindAndRemoveBookmarkStartRange(
+ m_sBookmarkName, xStartRange,
+ m_sXmlId, xRDFaAttributes))
+ {
+ Reference<XTextRange> xEndRange(
+ m_rHelper.GetCursorAsRange()->getStart());
+
+ // check if beginning and end are in same XText
+ if (xStartRange.is() && xEndRange.is() && xStartRange->getText() == xEndRange->getText())
+ {
+ // create range for insertion
+ Reference<XTextCursor> xInsertionCursor =
+ m_rHelper.GetText()->createTextCursorByRange(
+ xEndRange);
+ try {
+ xInsertionCursor->gotoRange(xStartRange, true);
+ } catch (uno::Exception&) {
+ TOOLS_WARN_EXCEPTION("xmloff.text",
+ "cannot go to end position of bookmark");
+ }
+
+ //DBG_ASSERT(! xInsertionCursor->isCollapsed(),
+ // "we want no point mark");
+ // can't assert, because someone could
+ // create a file with subsequence
+ // start/end elements
+
+ Reference<XInterface> xContent;
+ // insert reference
+ xContent = CreateAndInsertMark(GetImport(),
+ sAPI_bookmark,
+ m_sBookmarkName,
+ xInsertionCursor,
+ m_sXmlId);
+ if (xRDFaAttributes)
+ {
+ const Reference<rdf::XMetadatable>
+ xMeta(xContent, UNO_QUERY);
+ GetImport().GetRDFaImportHelper().AddRDFa(
+ xMeta, xRDFaAttributes);
+ }
+ const Reference<XPropertySet> xPropertySet(xContent, UNO_QUERY);
+ if (xPropertySet.is())
+ {
+ xPropertySet->setPropertyValue("BookmarkHidden", uno::Any(m_rHelper.getBookmarkHidden(m_sBookmarkName)));
+ xPropertySet->setPropertyValue("BookmarkCondition", uno::Any(m_rHelper.getBookmarkCondition(m_sBookmarkName)));
+ }
+ if (m_sBookmarkName.startsWith("__RefHeading__"))
+ {
+ assert(xContent.is());
+ m_rxCrossRefHeadingBookmark = xContent;
+ }
+ }
+ // else: beginning/end in different XText -> ignore!
+ }
+ // else: no start found -> ignore!
+ break;
+ }
+ case TypeFieldmarkStart:
+ {
+ break;
+ }
+ case TypeFieldmarkSeparator:
+ {
+ InsertFieldmark(GetImport(), m_rHelper, false);
+ break;
+ }
+ case TypeFieldmarkEnd:
+ {
+ if (m_rHelper.hasCurrentFieldCtx() && !m_rHelper.hasCurrentFieldSeparator())
+ { // backward compat for old files without separator
+ InsertFieldmark(GetImport(), m_rHelper, true);
+ }
+ PopFieldmark(m_rHelper);
+ break;
+ }
+ case TypeReferenceStart:
+ case TypeReferenceEnd:
+ OSL_FAIL("reference start/end are handled in txtparai !");
+ break;
+
+ default:
+ OSL_FAIL("unknown mark type");
+ break;
+ }
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTextMarkImportContext::createFastChildContext(
+ sal_Int32 ,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
+{
+ return new XMLFieldParamImportContext(GetImport(), m_rHelper);
+}
+
+
+Reference<XTextContent> XMLTextMarkImportContext::CreateAndInsertMark(
+ SvXMLImport& rImport,
+ const OUString& sServiceName,
+ const OUString& sMarkName,
+ const Reference<XTextRange> & rRange,
+ const OUString& i_rXmlId,
+ bool const isFieldmarkSeparatorMissing)
+{
+ // create mark
+ const Reference<XMultiServiceFactory> xFactory(rImport.GetModel(),
+ UNO_QUERY);
+ Reference<XInterface> xIfc;
+
+ if (xFactory.is())
+ {
+ xIfc = xFactory->createInstance(sServiceName);
+
+ if (!xIfc.is())
+ {
+ OSL_FAIL("CreateAndInsertMark: cannot create service?");
+ return nullptr;
+ }
+
+ // set name (unless there is no name (text:meta))
+ const Reference<XNamed> xNamed(xIfc, UNO_QUERY);
+ if (xNamed.is())
+ {
+ xNamed->setName(sMarkName);
+ }
+ else
+ {
+ if (!sMarkName.isEmpty())
+ {
+ OSL_FAIL("name given, but XNamed not supported?");
+ return nullptr;
+ }
+ }
+
+ if (isFieldmarkSeparatorMissing)
+ {
+ uno::Reference<beans::XPropertySet> const xProps(xIfc, uno::UNO_QUERY_THROW);
+ xProps->setPropertyValue("PrivateSeparatorAtStart", uno::Any(true));
+ }
+
+ // cast to XTextContent and attach to document
+ const Reference<XTextContent> xTextContent(xIfc, UNO_QUERY);
+ if (xTextContent.is())
+ {
+ try
+ {
+ // if inserting marks, bAbsorb==sal_False will cause
+ // collapsing of the given XTextRange.
+ rImport.GetTextImport()->GetText()->insertTextContent(rRange,
+ xTextContent, true);
+
+ // xml:id for RDF metadata -- after insertion!
+ rImport.SetXmlId(xIfc, i_rXmlId);
+
+ return xTextContent;
+ }
+ catch (css::lang::IllegalArgumentException &)
+ {
+ OSL_FAIL("CreateAndInsertMark: cannot insert?");
+ return nullptr;
+ }
+ }
+ }
+ return nullptr;
+}
+
+bool XMLTextMarkImportContext::FindName(
+ const Reference<XFastAttributeList> & xAttrList)
+{
+ bool bNameOK = false;
+
+ // find name attribute first
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ OUString sValue = aIter.toString();
+ switch(aIter.getToken())
+ {
+ case XML_ELEMENT(TEXT, XML_NAME):
+ m_sBookmarkName = sValue;
+ bNameOK = true;
+ break;
+ case XML_ELEMENT(XML, XML_ID):
+ m_sXmlId = sValue;
+ break;
+ // RDFa
+ case XML_ELEMENT(XHTML, XML_ABOUT):
+ m_sAbout = sValue;
+ m_bHaveAbout = true;
+ break;
+ case XML_ELEMENT(XHTML, XML_PROPERTY):
+ m_sProperty = sValue;
+ break;
+ case XML_ELEMENT(XHTML, XML_CONTENT):
+ m_sContent = sValue;
+ break;
+ case XML_ELEMENT(XHTML, XML_DATATYPE):
+ m_sDatatype = sValue;
+ break;
+ case XML_ELEMENT(FIELD, XML_TYPE):
+ m_sFieldName = sValue;
+ break;
+ case XML_ELEMENT(LO_EXT, XML_HIDDEN):
+ ::sax::Converter::convertBool(m_isHidden, sValue);
+ break;
+ case XML_ELEMENT(LO_EXT, XML_CONDITION):
+ m_sCondition = sValue;
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+
+ return bNameOK;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTextMarkImportContext.hxx b/xmloff/source/text/XMLTextMarkImportContext.hxx
new file mode 100644
index 0000000000..da05f52408
--- /dev/null
+++ b/xmloff/source/text/XMLTextMarkImportContext.hxx
@@ -0,0 +1,106 @@
+/* -*- 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 .
+ */
+
+
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <com/sun/star/uno/Reference.h>
+
+
+namespace com::sun::star {
+ namespace text {
+ class XTextRange;
+ class XTextContent;
+ }
+ namespace xml::sax {
+ class XAttributeList;
+ }
+}
+class XMLTextImportHelper;
+
+class XMLFieldParamImportContext : public SvXMLImportContext
+{
+ XMLTextImportHelper& rHelper;
+public:
+ XMLFieldParamImportContext(
+ SvXMLImport& rImport,
+ XMLTextImportHelper& rHlp );
+
+ virtual void SAL_CALL startFastElement(
+ sal_Int32 nElement,
+ const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList) override;
+};
+
+
+/**
+ * import bookmarks and reference marks
+ * ( <bookmark>, <bookmark-start>, <bookmark-end>,
+ * <reference>, <reference-start>, <reference-end> )
+ *
+ * All elements are handled by the same class due to their similarities.
+ */
+class XMLTextMarkImportContext final : public SvXMLImportContext
+{
+private:
+ XMLTextImportHelper & m_rHelper;
+
+ css::uno::Reference<css::uno::XInterface> & m_rxCrossRefHeadingBookmark;
+
+ OUString m_sBookmarkName;
+ OUString m_sFieldName;
+ bool m_isHidden;
+ OUString m_sCondition;
+ OUString m_sXmlId;
+ // RDFa
+ bool m_bHaveAbout;
+ OUString m_sAbout;
+ OUString m_sProperty;
+ OUString m_sContent;
+ OUString m_sDatatype;
+
+public:
+
+ XMLTextMarkImportContext(
+ SvXMLImport& rImport,
+ XMLTextImportHelper& rHlp,
+ css::uno::Reference<css::uno::XInterface> & io_rxCrossRefHeadingBookmark );
+
+ virtual void SAL_CALL startFastElement( sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+
+public:
+ static css::uno::Reference< css::text::XTextContent > CreateAndInsertMark(
+ SvXMLImport& rImport,
+ const OUString& sServiceName,
+ const OUString& sMarkName,
+ const css::uno::Reference<css::text::XTextRange> & rRange,
+ const OUString& i_rXmlId = OUString(),
+ bool const isFieldmarkSeparatorMissing = false);
+
+ bool FindName(
+ const css::uno::Reference<css::xml::sax::XFastAttributeList> & xAttrList);
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTextMasterPageContext.cxx b/xmloff/source/text/XMLTextMasterPageContext.cxx
new file mode 100644
index 0000000000..71e5f67701
--- /dev/null
+++ b/xmloff/source/text/XMLTextMasterPageContext.cxx
@@ -0,0 +1,301 @@
+/* -*- 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 <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/style/XStyle.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/beans/XMultiPropertyStates.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <o3tl/any.hxx>
+#include <sal/log.hxx>
+#include <osl/diagnose.h>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/prstylei.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/XMLTextMasterPageContext.hxx>
+#include <XMLTextHeaderFooterContext.hxx>
+#include <PageMasterImportContext.hxx>
+#include <xmloff/xmlimp.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::xml::sax;
+using namespace ::com::sun::star::style;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::xmloff::token;
+
+Reference < XStyle > XMLTextMasterPageContext::Create()
+{
+ Reference < XStyle > xNewStyle;
+
+ Reference< XMultiServiceFactory > xFactory( GetImport().GetModel(),
+ UNO_QUERY );
+ if( xFactory.is() )
+ {
+ Reference < XInterface > xIfc =
+ xFactory->createInstance("com.sun.star.style.PageStyle");
+ if( xIfc.is() )
+ xNewStyle.set( xIfc, UNO_QUERY );
+ }
+
+ return xNewStyle;
+}
+
+constexpr OUString gsFollowStyle( u"FollowStyle"_ustr );
+
+XMLTextMasterPageContext::XMLTextMasterPageContext( SvXMLImport& rImport,
+ sal_Int32 /*nElement*/,
+ const Reference< XFastAttributeList > & xAttrList,
+ bool bOverwrite )
+: SvXMLStyleContext( rImport, XmlStyleFamily::MASTER_PAGE )
+, m_bInsertHeader( false )
+, m_bInsertFooter( false )
+, m_bInsertHeaderLeft( false )
+, m_bInsertFooterLeft( false )
+, m_bInsertHeaderFirst( false )
+, m_bInsertFooterFirst( false )
+, m_bHeaderInserted( false )
+, m_bFooterInserted( false )
+{
+ OUString sName, sDisplayName;
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
+ {
+ const OUString aValue = aIter.toString();
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(STYLE, XML_NAME):
+ sName = aValue;
+ break;
+ case XML_ELEMENT(STYLE, XML_DISPLAY_NAME):
+ sDisplayName = aValue;
+ break;
+ case XML_ELEMENT(STYLE, XML_NEXT_STYLE_NAME):
+ m_sFollow = aValue;
+ break;
+ case XML_ELEMENT(STYLE, XML_PAGE_LAYOUT_NAME):
+ m_sPageMasterName = aValue;
+ break;
+ case XML_ELEMENT(DRAW, XML_STYLE_NAME):
+ m_sDrawingPageStyle = aValue;
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+
+ if( !sDisplayName.isEmpty() )
+ {
+ rImport.AddStyleDisplayName( XmlStyleFamily::MASTER_PAGE, sName,
+ sDisplayName );
+ }
+ else
+ {
+ sDisplayName = sName;
+ }
+
+ if( sDisplayName.isEmpty() )
+ return;
+
+ Reference < XNameContainer > xPageStyles =
+ GetImport().GetTextImport()->GetPageStyles();
+ if( !xPageStyles.is() )
+ return;
+
+ Any aAny;
+ bool bNew = false;
+ if( xPageStyles->hasByName( sDisplayName ) )
+ {
+ aAny = xPageStyles->getByName( sDisplayName );
+ aAny >>= m_xStyle;
+ }
+ else
+ {
+ m_xStyle = Create();
+ if( !m_xStyle.is() )
+ return;
+
+ xPageStyles->insertByName( sDisplayName, Any(m_xStyle) );
+ bNew = true;
+ }
+
+ Reference < XPropertySet > xPropSet( m_xStyle, UNO_QUERY );
+ Reference< XPropertySetInfo > xPropSetInfo =
+ xPropSet->getPropertySetInfo();
+ OUString sIsPhysical( "IsPhysical" );
+ if( !bNew && xPropSetInfo->hasPropertyByName( sIsPhysical ) )
+ {
+ aAny = xPropSet->getPropertyValue( sIsPhysical );
+ bNew = !*o3tl::doAccess<bool>(aAny);
+ }
+ SetNew( bNew );
+
+ if( !(bOverwrite || bNew) )
+ return;
+
+ Reference < XMultiPropertyStates > xMultiStates( xPropSet,
+ UNO_QUERY );
+ OSL_ENSURE( xMultiStates.is(),
+ "text page style does not support multi property set" );
+ if( xMultiStates.is() )
+ xMultiStates->setAllPropertiesToDefault();
+
+ if ( xPropSetInfo->hasPropertyByName( "GridDisplay" ) )
+ xPropSet->setPropertyValue( "GridDisplay", Any(false) );
+
+ if ( xPropSetInfo->hasPropertyByName( "GridPrint" ) )
+ xPropSet->setPropertyValue( "GridPrint", Any(false) );
+
+ m_bInsertHeader = m_bInsertFooter = true;
+ m_bInsertHeaderLeft = m_bInsertFooterLeft = true;
+ m_bInsertHeaderFirst = m_bInsertFooterFirst = true;
+}
+
+XMLTextMasterPageContext::~XMLTextMasterPageContext()
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTextMasterPageContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ SvXMLImportContextRef xContext;
+
+ bool bInsert = false, bFooter = false, bLeft = false, bFirst = false;
+ switch( nElement )
+ {
+ case XML_ELEMENT(STYLE, XML_HEADER):
+ if( m_bInsertHeader && !m_bHeaderInserted )
+ {
+ bInsert = true;
+ m_bHeaderInserted = true;
+ }
+ break;
+ case XML_ELEMENT(STYLE, XML_FOOTER):
+ if( m_bInsertFooter && !m_bFooterInserted )
+ {
+ bInsert = bFooter = true;
+ m_bFooterInserted = true;
+ }
+ break;
+ case XML_ELEMENT(STYLE, XML_HEADER_LEFT):
+ if( m_bInsertHeaderLeft && m_bHeaderInserted )
+ bInsert = bLeft = true;
+ break;
+ case XML_ELEMENT(STYLE, XML_FOOTER_LEFT):
+ if( m_bInsertFooterLeft && m_bFooterInserted )
+ bInsert = bFooter = bLeft = true;
+ break;
+ case XML_ELEMENT(LO_EXT, XML_HEADER_FIRST):
+ case XML_ELEMENT(STYLE, XML_HEADER_FIRST):
+ if( m_bInsertHeaderFirst && m_bHeaderInserted )
+ bInsert = bFirst = true;
+ break;
+ case XML_ELEMENT(LO_EXT, XML_FOOTER_FIRST):
+ case XML_ELEMENT(STYLE, XML_FOOTER_FIRST):
+ if( m_bInsertFooterFirst && m_bFooterInserted )
+ bInsert = bFooter = bFirst = true;
+ break;
+ }
+
+ if( bInsert && m_xStyle.is() )
+ {
+ xContext = CreateHeaderFooterContext( nElement, xAttrList,
+ bFooter, bLeft, bFirst );
+ }
+
+ return xContext;
+}
+
+SvXMLImportContext *XMLTextMasterPageContext::CreateHeaderFooterContext(
+ sal_Int32 /*nElement*/,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & /*xAttrList*/,
+ const bool bFooter,
+ const bool bLeft,
+ const bool bFirst )
+{
+ Reference < XPropertySet > xPropSet( m_xStyle, UNO_QUERY );
+ return new XMLTextHeaderFooterContext( GetImport(), xPropSet, bFooter, bLeft, bFirst );
+}
+
+void XMLTextMasterPageContext::Finish( bool bOverwrite )
+{
+ if( !(m_xStyle.is() && (IsNew() || bOverwrite)) )
+ return;
+
+ Reference < XPropertySet > xPropSet( m_xStyle, UNO_QUERY );
+ XMLPropStyleContext * pDrawingPageStyle(nullptr);
+ if (!m_sDrawingPageStyle.isEmpty())
+ {
+ pDrawingPageStyle = GetImport().GetTextImport()->FindDrawingPage(m_sDrawingPageStyle);
+ }
+ PageStyleContext * pPageLayout(nullptr);
+ if( !m_sPageMasterName.isEmpty() )
+ {
+ pPageLayout = static_cast<PageStyleContext *>(GetImport().GetTextImport()->FindPageMaster(m_sPageMasterName));
+ }
+ if (pPageLayout)
+ {
+ pPageLayout->FillPropertySet_PageStyle(xPropSet, pDrawingPageStyle);
+ }
+ else if (pDrawingPageStyle)
+ {
+ // don't need to care about old background attributes in this case
+ pDrawingPageStyle->FillPropertySet(xPropSet);
+ }
+
+ Reference < XNameContainer > xPageStyles =
+ GetImport().GetTextImport()->GetPageStyles();
+ if( !xPageStyles.is() )
+ return;
+
+ Reference< XPropertySetInfo > xPropSetInfo =
+ xPropSet->getPropertySetInfo();
+ if( xPropSetInfo->hasPropertyByName( gsFollowStyle ) )
+ {
+ OUString sDisplayFollow(
+ GetImport().GetStyleDisplayName(
+ XmlStyleFamily::MASTER_PAGE, m_sFollow ) );
+ if( sDisplayFollow.isEmpty() ||
+ !xPageStyles->hasByName( sDisplayFollow ) )
+ sDisplayFollow = m_xStyle->getName();
+
+ Any aAny = xPropSet->getPropertyValue( gsFollowStyle );
+ OUString sCurrFollow;
+ aAny >>= sCurrFollow;
+ if( sCurrFollow != sDisplayFollow )
+ {
+ xPropSet->setPropertyValue( gsFollowStyle, Any(sDisplayFollow) );
+ }
+ }
+
+ if ( xPropSetInfo->hasPropertyByName( "Hidden" ) )
+ {
+ xPropSet->setPropertyValue( "Hidden", uno::Any( IsHidden( ) ) );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTextMasterPageExport.cxx b/xmloff/source/text/XMLTextMasterPageExport.cxx
new file mode 100644
index 0000000000..7be7be7aff
--- /dev/null
+++ b/xmloff/source/text/XMLTextMasterPageExport.cxx
@@ -0,0 +1,237 @@
+/* -*- 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 <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <com/sun/star/text/XText.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/XMLTextMasterPageExport.hxx>
+#include <sal/log.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::beans;
+using namespace ::xmloff::token;
+
+constexpr OUStringLiteral gsHeaderText( u"HeaderText" );
+constexpr OUStringLiteral gsHeaderOn( u"HeaderIsOn" );
+constexpr OUStringLiteral gsHeaderShareContent( u"HeaderIsShared" );
+constexpr OUStringLiteral gsHeaderTextFirst( u"HeaderTextFirst" );
+constexpr OUStringLiteral gsHeaderTextLeft( u"HeaderTextLeft" );
+constexpr OUString gsFirstShareContent( u"FirstIsShared"_ustr );
+constexpr OUStringLiteral gsFooterText( u"FooterText" );
+constexpr OUStringLiteral gsFooterOn( u"FooterIsOn" );
+constexpr OUStringLiteral gsFooterShareContent( u"FooterIsShared" );
+constexpr OUStringLiteral gsFooterTextFirst( u"FooterTextFirst" );
+constexpr OUStringLiteral gsFooterTextLeft( u"FooterTextLeft" );
+
+XMLTextMasterPageExport::XMLTextMasterPageExport( SvXMLExport& rExp ) :
+ XMLPageExport( rExp )
+{
+}
+
+XMLTextMasterPageExport::~XMLTextMasterPageExport()
+{
+}
+
+
+void XMLTextMasterPageExport::exportHeaderFooterContent(
+ const Reference< XText >& rText,
+ bool bAutoStyles, bool bExportParagraph )
+{
+ SAL_WARN_IF( !rText.is(), "xmloff", "There is the text" );
+
+ // tracked changes (autostyles + changes list)
+ GetExport().GetTextParagraphExport()->recordTrackedChangesForXText(rText);
+ GetExport().GetTextParagraphExport()->exportTrackedChanges(rText,
+ bAutoStyles);
+ if( bAutoStyles )
+ GetExport().GetTextParagraphExport()
+ ->collectTextAutoStyles( rText, true, bExportParagraph );
+ else
+ {
+ GetExport().GetTextParagraphExport()->exportTextDeclarations( rText );
+ GetExport().GetTextParagraphExport()->exportText( rText, true, bExportParagraph );
+ }
+
+ // tracked changes (end of XText)
+ GetExport().GetTextParagraphExport()->recordTrackedChangesNoXText();
+}
+
+void XMLTextMasterPageExport::exportMasterPageContent(
+ const Reference < XPropertySet > & rPropSet,
+ bool bAutoStyles )
+{
+ Any aAny;
+
+ Reference < XText > xHeaderText;
+ aAny = rPropSet->getPropertyValue( gsHeaderText );
+ aAny >>= xHeaderText;
+
+ Reference < XText > xHeaderTextFirst;
+ aAny = rPropSet->getPropertyValue( gsHeaderTextFirst );
+ aAny >>= xHeaderTextFirst;
+
+ Reference < XText > xHeaderTextLeft;
+ aAny = rPropSet->getPropertyValue( gsHeaderTextLeft );
+ aAny >>= xHeaderTextLeft;
+
+ Reference < XText > xFooterText;
+ aAny = rPropSet->getPropertyValue( gsFooterText );
+ aAny >>= xFooterText;
+
+ Reference < XText > xFooterTextFirst;
+ aAny = rPropSet->getPropertyValue( gsFooterTextFirst );
+ aAny >>= xFooterTextFirst;
+
+ Reference < XText > xFooterTextLeft;
+ aAny = rPropSet->getPropertyValue( gsFooterTextLeft );
+ aAny >>= xFooterTextLeft;
+
+ if( bAutoStyles )
+ {
+ if( xHeaderText.is() )
+ exportHeaderFooterContent( xHeaderText, true );
+ if( xHeaderTextFirst.is() && xHeaderTextFirst != xHeaderText )
+ exportHeaderFooterContent( xHeaderTextFirst, true );
+ if( xHeaderTextLeft.is() && xHeaderTextLeft != xHeaderText )
+ exportHeaderFooterContent( xHeaderTextLeft, true );
+ if( xFooterText.is() )
+ exportHeaderFooterContent( xFooterText, true );
+ if( xFooterTextFirst.is() && xFooterTextFirst != xFooterText )
+ exportHeaderFooterContent( xFooterTextFirst, true );
+ if( xFooterTextLeft.is() && xFooterTextLeft != xFooterText )
+ exportHeaderFooterContent( xFooterTextLeft, true );
+ }
+ else
+ {
+ auto const nVersion(GetExport().getSaneDefaultVersion());
+
+ aAny = rPropSet->getPropertyValue( gsHeaderOn );
+ bool bHeader = false;
+ aAny >>= bHeader;
+
+ bool bHeaderFirstShared = false;
+ if( bHeader )
+ {
+ aAny = rPropSet->getPropertyValue( gsFirstShareContent );
+ aAny >>= bHeaderFirstShared;
+ }
+
+ bool bHeaderLeftShared = false;
+ if( bHeader )
+ {
+ aAny = rPropSet->getPropertyValue( gsHeaderShareContent );
+ aAny >>= bHeaderLeftShared;
+ }
+
+ if( xHeaderText.is() )
+ {
+ if( !bHeader )
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE,
+ XML_DISPLAY, XML_FALSE );
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_STYLE,
+ XML_HEADER, true, true );
+ exportHeaderFooterContent( xHeaderText, false );
+ }
+
+ if( xHeaderTextLeft.is() && xHeaderTextLeft != xHeaderText )
+ {
+ if (bHeaderLeftShared)
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE,
+ XML_DISPLAY, XML_FALSE );
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_STYLE,
+ XML_HEADER_LEFT, true, true );
+ exportHeaderFooterContent( xHeaderTextLeft, false );
+ }
+
+ if (xHeaderTextFirst.is() && xHeaderTextFirst != xHeaderText
+ && SvtSaveOptions::ODFSVER_012 < nVersion)
+ {
+ if (bHeaderFirstShared)
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE,
+ XML_DISPLAY, XML_FALSE );
+ // ODF 1.3 OFFICE-3789
+ SvXMLElementExport aElem( GetExport(),
+ SvtSaveOptions::ODFSVER_013 <= nVersion
+ ? XML_NAMESPACE_STYLE
+ : XML_NAMESPACE_LO_EXT,
+ XML_HEADER_FIRST, true, true );
+ exportHeaderFooterContent( xHeaderTextFirst, false );
+ }
+
+ aAny = rPropSet->getPropertyValue( gsFooterOn );
+ bool bFooter = false;
+ aAny >>= bFooter;
+
+ bool bFooterFirstShared = false;
+ if( bFooter )
+ {
+ aAny = rPropSet->getPropertyValue( gsFirstShareContent );
+ aAny >>= bFooterFirstShared;
+ }
+
+ bool bFooterLeftShared = false;
+ if( bFooter )
+ {
+ aAny = rPropSet->getPropertyValue( gsFooterShareContent );
+ aAny >>= bFooterLeftShared;
+ }
+
+ if( xFooterText.is() )
+ {
+ if( !bFooter )
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE,
+ XML_DISPLAY, XML_FALSE );
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_STYLE,
+ XML_FOOTER, true, true );
+ exportHeaderFooterContent( xFooterText, false );
+ }
+
+ if( xFooterTextLeft.is() && xFooterTextLeft != xFooterText )
+ {
+ if (bFooterLeftShared)
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE,
+ XML_DISPLAY, XML_FALSE );
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_STYLE,
+ XML_FOOTER_LEFT, true, true );
+ exportHeaderFooterContent( xFooterTextLeft, false );
+ }
+
+ if (xFooterTextFirst.is() && xFooterTextFirst != xFooterText
+ && SvtSaveOptions::ODFSVER_012 < nVersion)
+ {
+ if (bFooterFirstShared)
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE,
+ XML_DISPLAY, XML_FALSE );
+ // ODF 1.3 OFFICE-3789
+ SvXMLElementExport aElem( GetExport(),
+ SvtSaveOptions::ODFSVER_013 <= nVersion
+ ? XML_NAMESPACE_STYLE
+ : XML_NAMESPACE_LO_EXT,
+ XML_FOOTER_FIRST, true, true );
+ exportHeaderFooterContent( xFooterTextFirst, false );
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTextMasterStylesContext.cxx b/xmloff/source/text/XMLTextMasterStylesContext.cxx
new file mode 100644
index 0000000000..608cc63077
--- /dev/null
+++ b/xmloff/source/text/XMLTextMasterStylesContext.cxx
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * 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 <xmloff/xmlimp.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+
+#include <xmloff/XMLTextMasterPageContext.hxx>
+#include <xmloff/XMLTextMasterStylesContext.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::xml::sax;
+
+using ::xmloff::token::XML_MASTER_PAGE;
+
+
+bool XMLTextMasterStylesContext::InsertStyleFamily( XmlStyleFamily ) const
+{
+ return true;
+}
+
+XMLTextMasterStylesContext::XMLTextMasterStylesContext(
+ SvXMLImport& rImport ) :
+ SvXMLStylesContext( rImport )
+{
+}
+
+XMLTextMasterStylesContext::~XMLTextMasterStylesContext()
+{
+}
+
+SvXMLStyleContext *XMLTextMasterStylesContext::CreateStyleChildContext(
+ sal_Int32 nElement,
+ const Reference< XFastAttributeList > & xAttrList )
+{
+ SvXMLStyleContext *pContext = nullptr;
+
+ if( nElement == XML_ELEMENT(STYLE, XML_MASTER_PAGE) &&
+ InsertStyleFamily( XmlStyleFamily::MASTER_PAGE ) )
+ pContext = new XMLTextMasterPageContext(
+ GetImport(), nElement,
+ xAttrList,
+ !GetImport().GetTextImport()->IsInsertMode() );
+
+ // any other style will be ignored here!
+
+ return pContext;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTextNumRuleInfo.cxx b/xmloff/source/text/XMLTextNumRuleInfo.cxx
new file mode 100644
index 0000000000..5f9a5e2b7a
--- /dev/null
+++ b/xmloff/source/text/XMLTextNumRuleInfo.cxx
@@ -0,0 +1,222 @@
+/* -*- 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 <osl/diagnose.h>
+#include <sal/log.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/container/XIndexReplace.hpp>
+#include <com/sun/star/style/NumberingType.hpp>
+#include <com/sun/star/text/XTextContent.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include "XMLTextNumRuleInfo.hxx"
+#include <xmloff/XMLTextListAutoStylePool.hxx>
+
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::style;
+
+// Complete refactoring of the class and enhancement of the class for lists.
+XMLTextNumRuleInfo::XMLTextNumRuleInfo()
+ : mbListIdIsDefault(false)
+ , mnListStartValue( -1 )
+ , mnListLevel( 0 )
+ , mbIsNumbered( false )
+ , mbIsRestart( false )
+ , mnListLevelStartValue( -1 )
+ , mbOutlineStyleAsNormalListStyle( false )
+{
+ Reset();
+}
+
+// Written OpenDocument file format doesn't fit to the created text document (#i69627#)
+void XMLTextNumRuleInfo::Set(
+ const css::uno::Reference < css::text::XTextContent > & xTextContent,
+ const bool bOutlineStyleAsNormalListStyle,
+ const XMLTextListAutoStylePool& rListAutoPool,
+ const bool bExportTextNumberElement,
+ const bool bListIdIsDefault )
+{
+ Reset();
+ // Written OpenDocument file format doesn't fit to the created text document (#i69627#)
+ mbOutlineStyleAsNormalListStyle = bOutlineStyleAsNormalListStyle;
+
+ Reference< XPropertySet > xPropSet( xTextContent, UNO_QUERY );
+ Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
+
+ // check if this paragraph supports a numbering
+ if( !xPropSetInfo->hasPropertyByName( "NumberingLevel" ) )
+ return;
+
+ if( xPropSet->getPropertyValue( "NumberingLevel" ) >>= mnListLevel )
+ {
+ if( xPropSetInfo->hasPropertyByName( "NumberingRules" ) )
+ {
+ xPropSet->getPropertyValue( "NumberingRules" ) >>= mxNumRules;
+ }
+ }
+ else
+ {
+ // in applications using the outliner we always have a numbering rule,
+ // so a void property no numbering
+ mnListLevel = 0;
+ }
+
+ // Assertion saving writer document (#i97312#)
+ if ( mxNumRules.is() && mxNumRules->getCount() < 1 )
+ {
+ SAL_WARN("xmloff",
+ "<XMLTextNumRuleInfo::Set(..)> - numbering rules instance does not contain any numbering rule" );
+ Reset();
+ return;
+ }
+
+ if ( mnListLevel < 0 )
+ {
+ SAL_WARN("xmloff",
+ "<XMLTextNumRuleInfo::Set(..)> - unexpected numbering level" );
+ Reset();
+ return;
+ }
+
+ // Written OpenDocument file format doesn't fit to the created text document (#i69627#)
+ bool bSuppressListStyle( false );
+ if ( mxNumRules.is() )
+ {
+ if ( !mbOutlineStyleAsNormalListStyle )
+ {
+ Reference<XPropertySet> xNumRulesProps(mxNumRules, UNO_QUERY);
+ if ( xNumRulesProps.is() &&
+ xNumRulesProps->getPropertySetInfo()->
+ hasPropertyByName( "NumberingIsOutline" ) )
+ {
+ bool bIsOutline = false;
+ xNumRulesProps->getPropertyValue( "NumberingIsOutline" ) >>= bIsOutline;
+ bSuppressListStyle = bIsOutline;
+ }
+ }
+ }
+
+ if( mxNumRules.is() && !bSuppressListStyle )
+ {
+ // First try to find the numbering rules in the list auto style pool.
+ // If not found, the numbering rules instance has to be named.
+ msNumRulesName = rListAutoPool.Find( mxNumRules );
+ if ( msNumRulesName.isEmpty() )
+ {
+ Reference < XNamed > xNamed( mxNumRules, UNO_QUERY );
+ SAL_WARN_IF( !xNamed.is(), "xmloff",
+ "<XMLTextNumRuleInfo::Set(..)> - numbering rules instance have to be named. Serious defect." );
+ if( xNamed.is() )
+ {
+ msNumRulesName = xNamed->getName();
+ }
+ }
+ SAL_WARN_IF( msNumRulesName.isEmpty(), "xmloff",
+ "<XMLTextNumRuleInfo::Set(..)> - no name found for numbering rules instance. Serious defect." );
+
+ if( xPropSetInfo->hasPropertyByName( "ListId" ) )
+ {
+ xPropSet->getPropertyValue( "ListId" ) >>= msListId;
+ }
+
+ mbListIdIsDefault = bListIdIsDefault;
+
+ mbContinueingPreviousSubTree = false;
+ if( xPropSetInfo->hasPropertyByName( "ContinueingPreviousSubTree" ) )
+ {
+ xPropSet->getPropertyValue( "ContinueingPreviousSubTree" ) >>= mbContinueingPreviousSubTree;
+ }
+
+ mbIsNumbered = true;
+ if( xPropSetInfo->hasPropertyByName( "NumberingIsNumber" ) )
+ {
+ if( !(xPropSet->getPropertyValue( "NumberingIsNumber" ) >>= mbIsNumbered ) )
+ {
+ OSL_FAIL( "numbered paragraph without number info" );
+ mbIsNumbered = false;
+ }
+ }
+
+ if( mbIsNumbered )
+ {
+ if( xPropSetInfo->hasPropertyByName( "ParaIsNumberingRestart" ) )
+ {
+ xPropSet->getPropertyValue( "ParaIsNumberingRestart" ) >>= mbIsRestart;
+ }
+ if( xPropSetInfo->hasPropertyByName( "NumberingStartValue" ) )
+ {
+ xPropSet->getPropertyValue( "NumberingStartValue" ) >>= mnListStartValue;
+ }
+ }
+
+ OSL_ENSURE( mnListLevel < mxNumRules->getCount(), "wrong num rule level" );
+ if( mnListLevel >= mxNumRules->getCount() )
+ {
+ Reset();
+ return;
+ }
+
+ Sequence<PropertyValue> aProps;
+ mxNumRules->getByIndex( mnListLevel ) >>= aProps;
+
+ auto pProp = std::find_if(std::cbegin(aProps), std::cend(aProps),
+ [](const PropertyValue& rProp) { return rProp.Name == "StartWith"; });
+ if (pProp != std::cend(aProps))
+ {
+ pProp->Value >>= mnListLevelStartValue;
+ }
+
+ msListLabelString.clear();
+ if ( bExportTextNumberElement &&
+ xPropSetInfo->hasPropertyByName( "ListLabelString" ) )
+ {
+ xPropSet->getPropertyValue( "ListLabelString" ) >>= msListLabelString;
+ }
+
+ // paragraph's list level range is [0..9] representing list levels [1..10]
+ ++mnListLevel;
+ }
+ else
+ {
+ mnListLevel = 0;
+ }
+}
+
+bool XMLTextNumRuleInfo::BelongsToSameList( const XMLTextNumRuleInfo& rCmp ) const
+{
+ bool bRet( true );
+ // Currently only the text documents support <ListId>.
+ if ( !rCmp.msListId.isEmpty() || !msListId.isEmpty() )
+ {
+ bRet = rCmp.msListId == msListId;
+ }
+ else
+ {
+ bRet = rCmp.msNumRulesName == msNumRulesName;
+ }
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTextNumRuleInfo.hxx b/xmloff/source/text/XMLTextNumRuleInfo.hxx
new file mode 100644
index 0000000000..7cbc3cf8d4
--- /dev/null
+++ b/xmloff/source/text/XMLTextNumRuleInfo.hxx
@@ -0,0 +1,158 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/container/XIndexReplace.hpp>
+#include <sal/types.h>
+
+namespace com::sun::star {
+ namespace text { class XTextContent; }
+}
+
+class XMLTextListAutoStylePool;
+
+/** information about list and list style for a certain paragraph
+
+ OD 2008-04-24 #refactorlists#
+ Complete refactoring of the class and enhancement of the class for lists.
+ These changes are considered by method <XMLTextParagraphExport::exportListChange(..)>
+*/
+class XMLTextNumRuleInfo
+{
+ // numbering rules instance and its name
+ css::uno::Reference < css::container::XIndexReplace > mxNumRules;
+ OUString msNumRulesName;
+
+ // paragraph's list attributes
+ OUString msListId;
+ /// msListId won't be referenced by later lists.
+ bool mbListIdIsDefault;
+ sal_Int16 mnListStartValue;
+ sal_Int16 mnListLevel;
+ bool mbIsNumbered;
+ bool mbIsRestart;
+
+ // numbering rules' attributes
+ sal_Int16 mnListLevelStartValue;
+
+ // Written OpenDocument file format doesn't fit to the created text document (#i69627#)
+ bool mbOutlineStyleAsNormalListStyle;
+
+ bool mbContinueingPreviousSubTree;
+ OUString msListLabelString;
+
+public:
+
+ XMLTextNumRuleInfo();
+
+ inline XMLTextNumRuleInfo& operator=( const XMLTextNumRuleInfo& rInfo );
+
+ void Set( const css::uno::Reference < css::text::XTextContent > & rTextContent,
+ bool bOutlineStyleAsNormalListStyle,
+ const XMLTextListAutoStylePool& rListAutoPool,
+ bool bExportTextNumberElement,
+ bool bListIdIsDefault );
+ inline void Reset();
+
+ const OUString& GetNumRulesName() const
+ {
+ return msNumRulesName;
+ }
+ sal_Int16 GetListLevelStartValue() const
+ {
+ return mnListLevelStartValue;
+ }
+
+ const OUString& GetListId() const
+ {
+ return msListId;
+ }
+
+ bool IsListIdDefault() const { return mbListIdIsDefault; }
+
+ sal_Int16 GetLevel() const
+ {
+ return mnListLevel;
+ }
+
+ bool HasStartValue() const
+ {
+ return mnListStartValue != -1;
+ }
+ sal_uInt32 GetStartValue() const
+ {
+ return mnListStartValue;
+ }
+
+ bool IsNumbered() const
+ {
+ return mbIsNumbered;
+ }
+ bool IsRestart() const
+ {
+ return mbIsRestart;
+ }
+
+ bool BelongsToSameList( const XMLTextNumRuleInfo& rCmp ) const;
+
+ bool IsContinueingPreviousSubTree() const
+ {
+ return mbContinueingPreviousSubTree;
+ }
+ const OUString& ListLabelString() const
+ {
+ return msListLabelString;
+ }
+};
+
+inline XMLTextNumRuleInfo& XMLTextNumRuleInfo::operator=(
+ const XMLTextNumRuleInfo& rInfo )
+{
+ msNumRulesName = rInfo.msNumRulesName;
+ mxNumRules = rInfo.mxNumRules;
+ msListId = rInfo.msListId;
+ mnListStartValue = rInfo.mnListStartValue;
+ mnListLevel = rInfo.mnListLevel;
+ mbIsNumbered = rInfo.mbIsNumbered;
+ mbIsRestart = rInfo.mbIsRestart;
+ // Written OpenDocument file format doesn't fit to the created text document (#i69627#)
+ mbOutlineStyleAsNormalListStyle = rInfo.mbOutlineStyleAsNormalListStyle;
+ mbContinueingPreviousSubTree = rInfo.mbContinueingPreviousSubTree;
+ msListLabelString = rInfo.msListLabelString;
+
+ return *this;
+}
+
+inline void XMLTextNumRuleInfo::Reset()
+{
+ mxNumRules = nullptr;
+ msNumRulesName.clear();
+ msListId.clear();
+ mnListStartValue = -1;
+ mnListLevel = 0;
+ // Written OpenDocument file format doesn't fit to the created text document (#i69627#)
+ mbIsNumbered = mbIsRestart =
+ mbOutlineStyleAsNormalListStyle = false;
+ mbContinueingPreviousSubTree = false;
+ msListLabelString.clear();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTextPropertySetContext.cxx b/xmloff/source/text/XMLTextPropertySetContext.cxx
new file mode 100644
index 0000000000..472001287e
--- /dev/null
+++ b/xmloff/source/text/XMLTextPropertySetContext.cxx
@@ -0,0 +1,135 @@
+/* -*- 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 <tools/debug.hxx>
+#include "XMLTextPropertySetContext.hxx"
+#include <XMLTextColumnsContext.hxx>
+#include <xmloff/XMLComplexColorContext.hxx>
+#include <XMLBackgroundImageContext.hxx>
+#include "XMLSectionFootnoteConfigImport.hxx"
+
+#include <xmloff/xmlimppr.hxx>
+#include <xmloff/txtprmap.hxx>
+#include <xmltabi.hxx>
+#include "txtdropi.hxx"
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+
+XMLTextPropertySetContext::XMLTextPropertySetContext(
+ SvXMLImport& rImport, sal_Int32 nElement,
+ const Reference< xml::sax::XFastAttributeList > & xAttrList,
+ sal_uInt32 nFamily,
+ ::std::vector< XMLPropertyState > &rProps,
+ const rtl::Reference < SvXMLImportPropertyMapper > &rMap,
+ OUString& rDCTextStyleName ) :
+ SvXMLPropertySetContext( rImport, nElement, xAttrList, nFamily,
+ rProps, rMap ),
+ rDropCapTextStyleName( rDCTextStyleName )
+{
+}
+
+XMLTextPropertySetContext::~XMLTextPropertySetContext()
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTextPropertySetContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList,
+ ::std::vector< XMLPropertyState > &rProperties,
+ const XMLPropertyState& rProp )
+{
+ switch( mxMapper->getPropertySetMapper()
+ ->GetEntryContextId( rProp.mnIndex ) )
+ {
+ case CTF_TABSTOP:
+ return new SvxXMLTabStopImportContext( GetImport(), nElement,
+ rProp,
+ rProperties );
+ break;
+ case CTF_TEXTCOLUMNS:
+ return new XMLTextColumnsContext( GetImport(), nElement,
+ xAttrList, rProp,
+ rProperties );
+ break;
+
+ case CTF_COMPLEX_COLOR:
+ return new XMLPropertyComplexColorContext(GetImport(), nElement, xAttrList, rProp, rProperties);
+ break;
+
+ case CTF_DROPCAPFORMAT:
+ {
+ DBG_ASSERT( rProp.mnIndex >= 2 &&
+ CTF_DROPCAPWHOLEWORD == mxMapper->getPropertySetMapper()
+ ->GetEntryContextId( rProp.mnIndex-2 ),
+ "invalid property map!");
+ XMLTextDropCapImportContext *pDCContext =
+ new XMLTextDropCapImportContext( GetImport(), nElement,
+ xAttrList,
+ rProp,
+ rProp.mnIndex-2,
+ rProperties );
+ rDropCapTextStyleName = pDCContext->GetStyleName();
+ return pDCContext;
+ }
+ break;
+
+ case CTF_BACKGROUND_URL:
+ {
+ DBG_ASSERT( rProp.mnIndex >= 2 &&
+ CTF_BACKGROUND_POS == mxMapper->getPropertySetMapper()
+ ->GetEntryContextId( rProp.mnIndex-2 ) &&
+ CTF_BACKGROUND_FILTER == mxMapper->getPropertySetMapper()
+ ->GetEntryContextId( rProp.mnIndex-1 ),
+ "invalid property map!");
+
+ // #99657# Transparency might be there as well... but doesn't have
+ // to. Thus, this is checked with an if, rather than with an assertion.
+ sal_Int32 nTranspIndex = -1;
+ if( (rProp.mnIndex >= 3) &&
+ ( CTF_BACKGROUND_TRANSPARENCY ==
+ mxMapper->getPropertySetMapper()->GetEntryContextId(
+ rProp.mnIndex-3 ) ) )
+ nTranspIndex = rProp.mnIndex-3;
+
+ return
+ new XMLBackgroundImageContext( GetImport(), nElement,
+ xAttrList,
+ rProp,
+ rProp.mnIndex-2,
+ rProp.mnIndex-1,
+ nTranspIndex,
+ -1,
+ rProperties );
+ }
+ break;
+ case CTF_SECTION_FOOTNOTE_END:
+ case CTF_SECTION_ENDNOTE_END:
+ return new XMLSectionFootnoteConfigImport(
+ GetImport(), nElement, rProperties,
+ mxMapper->getPropertySetMapper());
+ break;
+ }
+
+ return SvXMLPropertySetContext::createFastChildContext( nElement,
+ xAttrList,
+ rProperties, rProp );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTextPropertySetContext.hxx b/xmloff/source/text/XMLTextPropertySetContext.hxx
new file mode 100644
index 0000000000..2286e773ff
--- /dev/null
+++ b/xmloff/source/text/XMLTextPropertySetContext.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/.
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <xmloff/xmlprcon.hxx>
+
+
+class XMLTextPropertySetContext : public SvXMLPropertySetContext
+{
+// SvXMLImportContextRef xTabStop;
+// SvXMLImportContextRef xBackground;
+// SvXMLImportContextRef xDropCap;
+ OUString& rDropCapTextStyleName;
+
+public:
+ XMLTextPropertySetContext( SvXMLImport& rImport, sal_Int32 nElement,
+ const css::uno::Reference<css::xml::sax::XFastAttributeList >& xAttrList,
+ sal_uInt32 nFamily,
+ ::std::vector< XMLPropertyState > &rProps,
+ const rtl::Reference < SvXMLImportPropertyMapper > &rMap,
+ OUString& rDopCapTextStyleName );
+
+ virtual ~XMLTextPropertySetContext() override;
+
+ using SvXMLPropertySetContext::createFastChildContext;
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList,
+ ::std::vector< XMLPropertyState > &rProperties,
+ const XMLPropertyState& rProp ) override;
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTextShapeImportHelper.cxx b/xmloff/source/text/XMLTextShapeImportHelper.cxx
new file mode 100644
index 0000000000..aba039095a
--- /dev/null
+++ b/xmloff/source/text/XMLTextShapeImportHelper.cxx
@@ -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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/text/XTextContent.hpp>
+#include <com/sun/star/text/TextContentAnchorType.hpp>
+
+#include <sax/tools/converter.hxx>
+
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/txtimp.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include "XMLAnchorTypePropHdl.hxx"
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <xmloff/XMLTextShapeImportHelper.hxx>
+
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::drawing;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::xml::sax;
+using namespace ::xmloff::token;
+
+constexpr OUStringLiteral gsAnchorType(u"AnchorType");
+constexpr OUStringLiteral gsAnchorPageNo(u"AnchorPageNo");
+constexpr OUStringLiteral gsVertOrientPosition(u"VertOrientPosition");
+
+XMLTextShapeImportHelper::XMLTextShapeImportHelper(
+ SvXMLImport& rImp ) :
+ XMLShapeImportHelper( rImp, rImp.GetModel(),
+ XMLTextImportHelper::CreateShapeExtPropMapper(rImp) ),
+ m_rImport( rImp )
+{
+ Reference < XDrawPageSupplier > xDPS( rImp.GetModel(), UNO_QUERY );
+ if( xDPS.is() )
+ {
+ Reference < XShapes > xShapes = xDPS->getDrawPage();
+ pushGroupForPostProcessing( xShapes );
+ }
+
+}
+
+XMLTextShapeImportHelper::~XMLTextShapeImportHelper()
+{
+ popGroupAndPostProcess();
+}
+
+void XMLTextShapeImportHelper::addShape(
+ Reference< XShape >& rShape,
+ const Reference< XFastAttributeList >& xAttrList,
+ Reference< XShapes >& rShapes )
+{
+ if( rShapes.is() )
+ {
+ // It's a group shape or 3DScene , so we have to call the base class method.
+ XMLShapeImportHelper::addShape( rShape, xAttrList, rShapes );
+ return;
+ }
+
+ TextContentAnchorType eAnchorType = TextContentAnchorType_AT_PARAGRAPH;
+ sal_Int16 nPage = 0;
+ sal_Int32 nY = 0;
+
+ rtl::Reference < XMLTextImportHelper > xTxtImport =
+ m_rImport.GetTextImport();
+
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ switch( aIter.getToken() )
+ {
+ case XML_ELEMENT(TEXT, XML_ANCHOR_TYPE):
+ {
+ TextContentAnchorType eNew;
+ // OD 2004-06-01 #i26791# - allow all anchor types
+ if ( XMLAnchorTypePropHdl::convert( aIter.toView(), eNew ) )
+ {
+ eAnchorType = eNew;
+ }
+ }
+ break;
+ case XML_ELEMENT(TEXT, XML_ANCHOR_PAGE_NUMBER):
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertNumber(nTmp, aIter.toView(), 1, SHRT_MAX))
+ nPage = static_cast<sal_Int16>(nTmp);
+ }
+ break;
+ case XML_ELEMENT(SVG, XML_Y):
+ case XML_ELEMENT(SVG_COMPAT, XML_Y):
+ m_rImport.GetMM100UnitConverter().convertMeasureToCore( nY, aIter.toView() );
+ break;
+ }
+ }
+
+ Reference < XPropertySet > xPropSet( rShape, UNO_QUERY );
+
+ // anchor type
+ xPropSet->setPropertyValue( gsAnchorType, Any(eAnchorType) );
+
+ // page number must be set before the frame is inserted
+ switch( eAnchorType )
+ {
+ case TextContentAnchorType_AT_PAGE:
+ // only set positive page numbers
+ if ( nPage > 0 )
+ {
+ xPropSet->setPropertyValue( gsAnchorPageNo, Any(nPage) );
+ }
+ break;
+ default:
+ break;
+ }
+
+ Reference < XTextContent > xTxtCntnt( rShape, UNO_QUERY );
+ xTxtImport->InsertTextContent( xTxtCntnt );
+
+ switch( eAnchorType )
+ {
+ case TextContentAnchorType_AS_CHARACTER:
+ xPropSet->setPropertyValue( gsVertOrientPosition, Any(nY) );
+ break;
+ default:
+ break;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTextShapeStyleContext.cxx b/xmloff/source/text/XMLTextShapeStyleContext.cxx
new file mode 100644
index 0000000000..5ce5fafe4f
--- /dev/null
+++ b/xmloff/source/text/XMLTextShapeStyleContext.cxx
@@ -0,0 +1,219 @@
+/* -*- 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 <tools/debug.hxx>
+#include <com/sun/star/document/XEventsSupplier.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/style/XStyle.hpp>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/XMLEventsImportContext.hxx>
+#include <XMLShapePropertySetContext.hxx>
+#include <XMLTextColumnsContext.hxx>
+#include <XMLBackgroundImageContext.hxx>
+#include <xmloff/XMLComplexColorContext.hxx>
+#include <xmloff/txtprmap.hxx>
+#include <xmloff/xmltypes.hxx>
+#include <xmloff/maptype.hxx>
+#include <xmloff/xmlimppr.hxx>
+
+#include <xmloff/XMLTextShapeStyleContext.hxx>
+
+using namespace ::com::sun::star::document;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::xml::sax;
+using namespace ::com::sun::star::style;
+using namespace ::com::sun::star::beans;
+using namespace ::xmloff::token;
+
+namespace {
+
+class XMLTextShapePropertySetContext_Impl : public XMLShapePropertySetContext
+{
+public:
+ XMLTextShapePropertySetContext_Impl( SvXMLImport& rImport, sal_Int32 nElement,
+ const Reference< XFastAttributeList >& xAttrList,
+ sal_uInt32 nFamily,
+ ::std::vector< XMLPropertyState > &rProps,
+ const rtl::Reference < SvXMLImportPropertyMapper > &rMap );
+
+ using SvXMLPropertySetContext::createFastChildContext;
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList,
+ ::std::vector< XMLPropertyState > &rProperties,
+ const XMLPropertyState& rProp ) override;
+};
+
+}
+
+XMLTextShapePropertySetContext_Impl::XMLTextShapePropertySetContext_Impl(
+ SvXMLImport& rImport, sal_Int32 nElement,
+ const Reference< XFastAttributeList > & xAttrList,
+ sal_uInt32 nFamily,
+ ::std::vector< XMLPropertyState > &rProps,
+ const rtl::Reference < SvXMLImportPropertyMapper > &rMap ) :
+ XMLShapePropertySetContext( rImport, nElement, xAttrList, nFamily,
+ rProps, rMap )
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTextShapePropertySetContext_Impl::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList,
+ ::std::vector< XMLPropertyState > &rProperties,
+ const XMLPropertyState& rProp )
+{
+ switch( mxMapper->getPropertySetMapper()
+ ->GetEntryContextId( rProp.mnIndex ) )
+ {
+ case CTF_TEXTCOLUMNS:
+ return new XMLTextColumnsContext( GetImport(), nElement,
+ xAttrList, rProp,
+ rProperties );
+ break;
+
+ case CTF_COMPLEX_COLOR:
+ return new XMLPropertyComplexColorContext(GetImport(), nElement, xAttrList, rProp, rProperties);
+
+ case CTF_BACKGROUND_URL:
+ DBG_ASSERT( rProp.mnIndex >= 3 &&
+ CTF_BACKGROUND_TRANSPARENCY ==
+ mxMapper->getPropertySetMapper()
+ ->GetEntryContextId( rProp.mnIndex-3 ) &&
+ CTF_BACKGROUND_POS == mxMapper->getPropertySetMapper()
+ ->GetEntryContextId( rProp.mnIndex-2 ) &&
+ CTF_BACKGROUND_FILTER == mxMapper->getPropertySetMapper()
+ ->GetEntryContextId( rProp.mnIndex-1 ),
+ "invalid property map!");
+ return
+ new XMLBackgroundImageContext( GetImport(), nElement,
+ xAttrList,
+ rProp,
+ rProp.mnIndex-2,
+ rProp.mnIndex-1,
+ rProp.mnIndex-3,
+ -1,
+ rProperties );
+ break;
+ }
+
+ return XMLShapePropertySetContext::createFastChildContext(
+ nElement, xAttrList, rProperties, rProp );
+}
+
+void XMLTextShapeStyleContext::SetAttribute( sal_Int32 nElement,
+ const OUString& rValue )
+{
+ if( nElement == XML_ELEMENT(STYLE, XML_AUTO_UPDATE) )
+ {
+ if( IsXMLToken( rValue, XML_TRUE ) )
+ m_bAutoUpdate = true;
+ }
+ else
+ {
+ XMLShapeStyleContext::SetAttribute( nElement, rValue );
+ }
+}
+
+
+constexpr OUString gsIsAutoUpdate( u"IsAutoUpdate"_ustr );
+
+XMLTextShapeStyleContext::XMLTextShapeStyleContext( SvXMLImport& rImport,
+ SvXMLStylesContext& rStyles, XmlStyleFamily nFamily ) :
+ XMLShapeStyleContext( rImport, rStyles, nFamily ),
+ m_bAutoUpdate( false )
+{
+}
+
+XMLTextShapeStyleContext::~XMLTextShapeStyleContext()
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTextShapeStyleContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ if( IsTokenInNamespace(nElement, XML_NAMESPACE_STYLE) ||
+ IsTokenInNamespace(nElement, XML_NAMESPACE_LO_EXT) )
+ {
+ sal_Int32 nLocalName = nElement & TOKEN_MASK;
+ sal_uInt32 nFamily = 0;
+ if( nLocalName == XML_TEXT_PROPERTIES )
+ nFamily = XML_TYPE_PROP_TEXT;
+ else if( nLocalName == XML_PARAGRAPH_PROPERTIES )
+ nFamily = XML_TYPE_PROP_PARAGRAPH;
+ else if( nLocalName == XML_GRAPHIC_PROPERTIES )
+ nFamily = XML_TYPE_PROP_GRAPHIC;
+ if( nFamily )
+ {
+ rtl::Reference < SvXMLImportPropertyMapper > xImpPrMap =
+ GetStyles()->GetImportPropertyMapper( GetFamily() );
+ if( xImpPrMap.is() )
+ {
+ return new XMLTextShapePropertySetContext_Impl(
+ GetImport(), nElement, xAttrList, nFamily,
+ GetProperties(), xImpPrMap );
+ }
+ }
+ }
+ else if ( nElement == XML_ELEMENT(OFFICE, XML_EVENT_LISTENERS) )
+ {
+ // create and remember events import context
+ // (for delayed processing of events)
+ m_xEventContext = new XMLEventsImportContext( GetImport() );
+ return m_xEventContext;
+ }
+
+ return XMLShapeStyleContext::createFastChildContext( nElement, xAttrList );
+}
+
+void XMLTextShapeStyleContext::CreateAndInsert( bool bOverwrite )
+{
+ XMLShapeStyleContext::CreateAndInsert( bOverwrite );
+ Reference < XStyle > xStyle = GetStyle();
+ if( !xStyle.is() || !(bOverwrite || IsNew()) )
+ return;
+
+ Reference < XPropertySet > xPropSet( xStyle, UNO_QUERY );
+ Reference< XPropertySetInfo > xPropSetInfo =
+ xPropSet->getPropertySetInfo();
+ if( xPropSetInfo->hasPropertyByName( gsIsAutoUpdate ) )
+ {
+ bool bTmp = m_bAutoUpdate;
+ xPropSet->setPropertyValue( gsIsAutoUpdate, Any(bTmp) );
+ }
+
+ // tell the style about it's events (if applicable)
+ if( m_xEventContext.is() )
+ {
+ // set event supplier and release reference to context
+ Reference<XEventsSupplier> xEventsSupplier(xStyle, UNO_QUERY);
+ m_xEventContext->SetEvents(xEventsSupplier);
+ m_xEventContext = nullptr;
+ }
+}
+
+void XMLTextShapeStyleContext::Finish( bool bOverwrite )
+{
+ XMLPropStyleContext::Finish( bOverwrite );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTextTableContext.cxx b/xmloff/source/text/XMLTextTableContext.cxx
new file mode 100644
index 0000000000..2a56c0e60b
--- /dev/null
+++ b/xmloff/source/text/XMLTextTableContext.cxx
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * 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 <xmloff/XMLTextTableContext.hxx>
+
+
+using namespace ::com::sun::star::uno;
+
+
+XMLTextTableContext::XMLTextTableContext( SvXMLImport& rImport ) :
+ SvXMLImportContext( rImport )
+{
+}
+
+XMLTextTableContext::~XMLTextTableContext()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTrackedChangesImportContext.cxx b/xmloff/source/text/XMLTrackedChangesImportContext.cxx
new file mode 100644
index 0000000000..57a71e0dbf
--- /dev/null
+++ b/xmloff/source/text/XMLTrackedChangesImportContext.cxx
@@ -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/.
+ *
+ * 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 "XMLTrackedChangesImportContext.hxx"
+#include "XMLChangedRegionImportContext.hxx"
+#include <com/sun/star/uno/Reference.h>
+#include <sal/log.hxx>
+#include <sax/tools/converter.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmltoken.hxx>
+
+
+using ::com::sun::star::uno::Reference;
+using namespace ::xmloff::token;
+
+
+XMLTrackedChangesImportContext::XMLTrackedChangesImportContext(
+ SvXMLImport& rImport) :
+ SvXMLImportContext(rImport)
+{
+}
+
+XMLTrackedChangesImportContext::~XMLTrackedChangesImportContext()
+{
+}
+
+void XMLTrackedChangesImportContext::startFastElement( sal_Int32 /*nElement*/,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ bool bTrackChanges = true;
+
+ // scan for text:track-changes and text:protection-key attributes
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ if (aIter.getToken() == XML_ELEMENT(TEXT, XML_TRACK_CHANGES) )
+ {
+ bool bTmp(false);
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ {
+ bTrackChanges = bTmp;
+ }
+ break;
+ }
+ else
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+
+ // set tracked changes
+ GetImport().GetTextImport()->SetRecordChanges( bTrackChanges );
+}
+
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTrackedChangesImportContext::createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
+{
+ if ( nElement == XML_ELEMENT(TEXT, XML_CHANGED_REGION) )
+ {
+ return new XMLChangedRegionImportContext(GetImport());
+ }
+ else
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ return nullptr;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/XMLTrackedChangesImportContext.hxx b/xmloff/source/text/XMLTrackedChangesImportContext.hxx
new file mode 100644
index 0000000000..6ae3c4a552
--- /dev/null
+++ b/xmloff/source/text/XMLTrackedChangesImportContext.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * 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 .
+ */
+
+
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+#include <com/sun/star/uno/Reference.h>
+
+namespace com::sun::star {
+ namespace xml::sax {
+ class XAttributeList;
+ }
+}
+
+class XMLTrackedChangesImportContext : public SvXMLImportContext
+{
+public:
+
+ XMLTrackedChangesImportContext(SvXMLImport& rImport);
+
+ virtual ~XMLTrackedChangesImportContext() override;
+
+ virtual void SAL_CALL startFastElement(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/txtdrope.cxx b/xmloff/source/text/txtdrope.cxx
new file mode 100644
index 0000000000..5013d422c2
--- /dev/null
+++ b/xmloff/source/text/txtdrope.cxx
@@ -0,0 +1,87 @@
+/* -*- 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 <rtl/ustrbuf.hxx>
+#include <com/sun/star/style/DropCapFormat.hpp>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include "txtdrope.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::style;
+using namespace ::com::sun::star::uno;
+
+using namespace ::xmloff::token;
+
+
+XMLTextDropCapExport::XMLTextDropCapExport( SvXMLExport& rExp ) :
+ rExport(rExp)
+{
+}
+
+void XMLTextDropCapExport::exportXML( const Any& rAny,
+ bool bWholeWord,
+ const OUString& rStyleName )
+{
+ DropCapFormat aFormat;
+ rAny >>= aFormat;
+ if( aFormat.Lines > 1 )
+ {
+ SvXMLUnitConverter& rUnitConv = rExport.GetMM100UnitConverter();
+
+ // style:lines
+ rExport.AddAttribute( XML_NAMESPACE_STYLE, XML_LINES,
+ OUString::number( aFormat.Lines ) );
+
+ // style:length
+ OUString sValue;
+ if( bWholeWord )
+ {
+ sValue = GetXMLToken(XML_WORD);
+ }
+ else if( aFormat.Count > 1 )
+ {
+ sValue = OUString::number(aFormat.Count);
+ }
+ if( !sValue.isEmpty() )
+ rExport.AddAttribute( XML_NAMESPACE_STYLE, XML_LENGTH, sValue );
+
+ // style:distance
+ if( aFormat.Distance > 0 )
+ {
+ OUStringBuffer sBuffer;
+ rUnitConv.convertMeasureToXML( sBuffer, aFormat.Distance );
+ rExport.AddAttribute( XML_NAMESPACE_STYLE, XML_DISTANCE,
+ sBuffer.makeStringAndClear() );
+ }
+
+ // style:style-name
+ if( !rStyleName.isEmpty() )
+ rExport.AddAttribute( XML_NAMESPACE_STYLE, XML_STYLE_NAME,
+ rExport.EncodeStyleName( rStyleName ) );
+ }
+
+ SvXMLElementExport aElem( rExport, XML_NAMESPACE_STYLE, XML_DROP_CAP,
+ false, false );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/txtdrope.hxx b/xmloff/source/text/txtdrope.hxx
new file mode 100644
index 0000000000..6e6b05a0be
--- /dev/null
+++ b/xmloff/source/text/txtdrope.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 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 .
+ */
+#pragma once
+
+
+#include <rtl/ustring.hxx>
+
+class SvXMLExport;
+namespace com::sun::star::uno { class Any; }
+
+class XMLTextDropCapExport
+{
+ SvXMLExport& rExport;
+
+public:
+
+ explicit XMLTextDropCapExport( SvXMLExport& rExport );
+
+ void exportXML( const css::uno::Any& rAny,
+ bool bWholeWord,
+ const OUString& rStyleName );
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/txtdropi.cxx b/xmloff/source/text/txtdropi.cxx
new file mode 100644
index 0000000000..66b219884b
--- /dev/null
+++ b/xmloff/source/text/txtdropi.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 "txtdropi.hxx"
+
+#include <com/sun/star/style/DropCapFormat.hpp>
+
+#include <sal/log.hxx>
+#include <sax/tools/converter.hxx>
+
+#include <xmloff/xmltkmap.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmltoken.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::style;
+using namespace ::xmloff::token;
+
+void XMLTextDropCapImportContext::ProcessAttrs(
+ const Reference< xml::sax::XFastAttributeList >& xAttrList )
+{
+ DropCapFormat aFormat;
+ bool bWholeWord = false;
+
+ sal_Int32 nTmp;
+ for (auto &aIter : sax_fastparser::castToFastAttributeList(xAttrList))
+ {
+ switch( aIter.getToken() )
+ {
+ case XML_ELEMENT(STYLE, XML_LINES):
+ if (::sax::Converter::convertNumber( nTmp, aIter.toView(), 0, 255 ))
+ {
+ aFormat.Lines = nTmp < 2 ? 0 : static_cast<sal_Int8>(nTmp);
+ }
+ break;
+
+ case XML_ELEMENT(STYLE, XML_LENGTH):
+ if( IsXMLToken( aIter, XML_WORD ) )
+ {
+ bWholeWord = true;
+ }
+ else if (::sax::Converter::convertNumber( nTmp, aIter.toView(), 1, 255 ))
+ {
+ bWholeWord = false;
+ aFormat.Count = static_cast<sal_Int8>(nTmp);
+ }
+ break;
+
+ case XML_ELEMENT(STYLE, XML_DISTANCE):
+ if (GetImport().GetMM100UnitConverter().convertMeasureToCore(
+ nTmp, aIter.toView(), 0 ))
+ {
+ aFormat.Distance = static_cast<sal_uInt16>(nTmp);
+ }
+ break;
+
+ case XML_ELEMENT(STYLE, XML_STYLE_NAME):
+ sStyleName = aIter.toString();
+ break;
+
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+
+ if( aFormat.Lines > 1 && aFormat.Count < 1 )
+ aFormat.Count = 1;
+
+ aProp.maValue <<= aFormat;
+
+ aWholeWordProp.maValue <<= bWholeWord;
+}
+
+XMLTextDropCapImportContext::XMLTextDropCapImportContext(
+ SvXMLImport& rImport, sal_Int32 nElement,
+ const Reference< xml::sax::XFastAttributeList > & xAttrList,
+ const XMLPropertyState& rProp,
+ sal_Int32 nWholeWordIdx,
+ ::std::vector< XMLPropertyState > &rProps ) :
+ XMLElementPropertyContext( rImport, nElement, rProp, rProps ),
+ aWholeWordProp( nWholeWordIdx )
+{
+ ProcessAttrs( xAttrList );
+}
+
+XMLTextDropCapImportContext::~XMLTextDropCapImportContext()
+{
+}
+
+void XMLTextDropCapImportContext::endFastElement(sal_Int32 nElement)
+{
+ SetInsert( true );
+ XMLElementPropertyContext::endFastElement(nElement);
+
+ if( -1 != aWholeWordProp.mnIndex )
+ rProperties.push_back( aWholeWordProp );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/txtdropi.hxx b/xmloff/source/text/txtdropi.hxx
new file mode 100644
index 0000000000..832761c95d
--- /dev/null
+++ b/xmloff/source/text/txtdropi.hxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include <xmloff/XMLElementPropertyContext.hxx>
+
+class XMLTextDropCapImportContext : public XMLElementPropertyContext
+{
+ XMLPropertyState aWholeWordProp;
+ OUString sStyleName;
+
+private:
+ void ProcessAttrs(const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList);
+
+public:
+ XMLTextDropCapImportContext(
+ SvXMLImport& rImport, sal_Int32 nElement,
+ const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList,
+ const XMLPropertyState& rProp, sal_Int32 nWholeWOrdIdx,
+ ::std::vector<XMLPropertyState>& rProps);
+
+ virtual ~XMLTextDropCapImportContext() override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ const OUString& GetStyleName() const { return sStyleName; }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/txtexppr.cxx b/xmloff/source/text/txtexppr.cxx
new file mode 100644
index 0000000000..f49084d9cb
--- /dev/null
+++ b/xmloff/source/text/txtexppr.cxx
@@ -0,0 +1,1206 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/table/BorderLine2.hpp>
+
+#include "txtexppr.hxx"
+
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/text/SizeType.hpp>
+#include <com/sun/star/text/WrapTextMode.hpp>
+#include <com/sun/star/text/TextContentAnchorType.hpp>
+#include <com/sun/star/awt/FontUnderline.hpp>
+#include <com/sun/star/text/XChapterNumberingSupplier.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <o3tl/any.hxx>
+#include <sal/log.hxx>
+#include <tools/color.hxx>
+#include <xmloff/txtprmap.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/maptype.hxx>
+#include <xmloff/namespacemap.hxx>
+#include "XMLSectionFootnoteConfigExport.hxx"
+#include <xmlsdtypes.hxx>
+#include <XMLNumberWithAutoForVoidPropHdl.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::style;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::text;
+
+void XMLTextExportPropertySetMapper::handleElementItem(
+ SvXMLExport& rExp,
+ const XMLPropertyState& rProperty,
+ SvXmlExportFlags nFlags,
+ const ::std::vector< XMLPropertyState > *pProperties,
+ sal_uInt32 nIdx ) const
+{
+ XMLTextExportPropertySetMapper *pThis =
+ const_cast<XMLTextExportPropertySetMapper*>(this);
+
+ switch( getPropertySetMapper()->GetEntryContextId( rProperty.mnIndex ) )
+ {
+ case CTF_DROPCAPFORMAT:
+ pThis->maDropCapExport.exportXML( rProperty.maValue, bDropWholeWord,
+ sDropCharStyle );
+ pThis->bDropWholeWord = false;
+ pThis->sDropCharStyle.clear();
+ break;
+
+ case CTF_TABSTOP:
+ pThis->maTabStopExport.Export( rProperty.maValue );
+ break;
+
+ case CTF_TEXTCOLUMNS:
+ pThis->maTextColumnsExport.exportXML( rProperty.maValue );
+ break;
+
+ case CTF_COMPLEX_COLOR:
+ pThis->maComplexColorExport.exportXML(rProperty.maValue,
+ getPropertySetMapper()->GetEntryNameSpace(rProperty.mnIndex),
+ getPropertySetMapper()->GetEntryXMLName(rProperty.mnIndex));
+ break;
+
+ case CTF_BACKGROUND_URL:
+ {
+ const Any *pPos = nullptr, *pFilter = nullptr, *pTrans = nullptr;
+ sal_uInt32 nPropIndex = rProperty.mnIndex;
+
+ // these are all optional, so have to check them in order
+ // note: this index order dependency is a steaming pile of manure
+ if (nIdx)
+ {
+ const XMLPropertyState& rFilter = (*pProperties)[nIdx - 1];
+ if (CTF_BACKGROUND_FILTER == getPropertySetMapper()
+ ->GetEntryContextId(rFilter.mnIndex))
+ {
+ pFilter = &rFilter.maValue;
+ --nIdx;
+ }
+ }
+
+ if (nIdx)
+ {
+ const XMLPropertyState& rPos = (*pProperties)[nIdx - 1];
+ if (CTF_BACKGROUND_POS == getPropertySetMapper()
+ ->GetEntryContextId(rPos.mnIndex))
+ {
+ pPos = &rPos.maValue;
+ --nIdx;
+ }
+ }
+
+ if (nIdx)
+ {
+ const XMLPropertyState& rTrans = (*pProperties)[nIdx - 1];
+ // #99657# transparency may be there, but doesn't have to be.
+ // If it's there, it must be in the right position.
+ if( CTF_BACKGROUND_TRANSPARENCY == getPropertySetMapper()
+ ->GetEntryContextId( rTrans.mnIndex ) )
+ pTrans = &rTrans.maValue;
+ }
+
+ pThis->maBackgroundImageExport.exportXML(
+ rProperty.maValue, pPos, pFilter, pTrans,
+ getPropertySetMapper()->GetEntryNameSpace( nPropIndex ),
+ getPropertySetMapper()->GetEntryXMLName( nPropIndex ) );
+ }
+ break;
+
+ case CTF_SECTION_FOOTNOTE_END:
+ XMLSectionFootnoteConfigExport::exportXML(rExp, false,
+ pProperties, nIdx,
+ getPropertySetMapper());
+ break;
+
+ case CTF_SECTION_ENDNOTE_END:
+ XMLSectionFootnoteConfigExport::exportXML(rExp, true,
+ pProperties, nIdx,
+ getPropertySetMapper());
+ break;
+
+ default:
+ SvXMLExportPropertyMapper::handleElementItem( rExp, rProperty, nFlags, pProperties, nIdx );
+ break;
+ }
+}
+
+void XMLTextExportPropertySetMapper::handleSpecialItem(
+ comphelper::AttributeList& rAttrList,
+ const XMLPropertyState& rProperty,
+ const SvXMLUnitConverter& rUnitConverter,
+ const SvXMLNamespaceMap& rNamespaceMap,
+ const ::std::vector< XMLPropertyState > *pProperties,
+ sal_uInt32 nIdx ) const
+{
+ XMLTextExportPropertySetMapper *pThis =
+ const_cast<XMLTextExportPropertySetMapper*>(this);
+
+ switch( getPropertySetMapper()->GetEntryContextId( rProperty.mnIndex ) )
+ {
+ case CTF_PAGENUMBEROFFSET:
+ {
+ OUString value;
+ XMLNumberWithAutoForVoidPropHdl const handler;
+ handler.exportXML(value, rProperty.maValue, rUnitConverter);
+ if (GetExport().getSaneDefaultVersion() < SvtSaveOptions::ODFSVER_013
+ && value == "0") // tdf#91306 ODF 1.3 OFFICE-3923
+ {
+ value = "auto";
+ }
+ OUString const name = rNamespaceMap.GetQNameByKey(
+ getPropertySetMapper()->GetEntryNameSpace(rProperty.mnIndex),
+ getPropertySetMapper()->GetEntryXMLName(rProperty.mnIndex));
+ rAttrList.AddAttribute(name, value);
+ }
+ break;
+ case CTF_DROPCAPWHOLEWORD:
+ SAL_WARN_IF( !!bDropWholeWord, "xmloff", "drop whole word is set already!" );
+ pThis->bDropWholeWord = *o3tl::doAccess<bool>(rProperty.maValue);
+ break;
+ case CTF_DROPCAPCHARSTYLE:
+ SAL_WARN_IF( !sDropCharStyle.isEmpty(), "xmloff", "drop char style is set already!" );
+ rProperty.maValue >>= pThis->sDropCharStyle;
+ break;
+ case CTF_NUMBERINGSTYLENAME:
+ case CTF_PAGEDESCNAME:
+ case CTF_OLDTEXTBACKGROUND:
+ case CTF_BACKGROUND_POS:
+ case CTF_BACKGROUND_FILTER:
+ case CTF_BACKGROUND_TRANSPARENCY:
+ case CTF_SECTION_FOOTNOTE_NUM_OWN:
+ case CTF_SECTION_FOOTNOTE_NUM_RESTART:
+ case CTF_SECTION_FOOTNOTE_NUM_RESTART_AT:
+ case CTF_SECTION_FOOTNOTE_NUM_TYPE:
+ case CTF_SECTION_FOOTNOTE_NUM_PREFIX:
+ case CTF_SECTION_FOOTNOTE_NUM_SUFFIX:
+ case CTF_SECTION_ENDNOTE_NUM_OWN:
+ case CTF_SECTION_ENDNOTE_NUM_RESTART:
+ case CTF_SECTION_ENDNOTE_NUM_RESTART_AT:
+ case CTF_SECTION_ENDNOTE_NUM_TYPE:
+ case CTF_SECTION_ENDNOTE_NUM_PREFIX:
+ case CTF_SECTION_ENDNOTE_NUM_SUFFIX:
+ case CTF_DEFAULT_OUTLINE_LEVEL:
+ case CTF_OLD_FLOW_WITH_TEXT:
+ // There's nothing to do here!
+ break;
+ default:
+ SvXMLExportPropertyMapper::handleSpecialItem(rAttrList, rProperty, rUnitConverter, rNamespaceMap, pProperties, nIdx );
+ break;
+ }
+}
+
+XMLTextExportPropertySetMapper::XMLTextExportPropertySetMapper(
+ const rtl::Reference< XMLPropertySetMapper >& rMapper,
+ SvXMLExport& rExp ) :
+ SvXMLExportPropertyMapper( rMapper ),
+ rExport( rExp ),
+ bDropWholeWord( false ),
+ maDropCapExport( rExp ),
+ maTabStopExport( rExp ),
+ maTextColumnsExport( rExp ),
+ maComplexColorExport(rExp),
+ maBackgroundImageExport( rExp )
+{
+}
+
+XMLTextExportPropertySetMapper::~XMLTextExportPropertySetMapper()
+{
+}
+
+void XMLTextExportPropertySetMapper::ContextFontFilter(
+ bool bEnableFoFontFamily,
+ XMLPropertyState *pFontNameState,
+ XMLPropertyState *pFontFamilyNameState,
+ XMLPropertyState *pFontStyleNameState,
+ XMLPropertyState *pFontFamilyState,
+ XMLPropertyState *pFontPitchState,
+ XMLPropertyState *pFontCharsetState ) const
+{
+ OUString sFamilyName;
+ OUString sStyleName;
+ FontFamily nFamily = FAMILY_DONTKNOW;
+ FontPitch nPitch = PITCH_DONTKNOW;
+ rtl_TextEncoding eEnc = RTL_TEXTENCODING_DONTKNOW;
+
+ OUString sTmp;
+ if( pFontFamilyNameState && (pFontFamilyNameState->maValue >>= sTmp ) )
+ sFamilyName = sTmp;
+ if( pFontStyleNameState && (pFontStyleNameState->maValue >>= sTmp ) )
+ sStyleName = sTmp;
+
+ sal_Int16 nTmp = sal_Int16();
+ if( pFontFamilyState && (pFontFamilyState->maValue >>= nTmp ) )
+ nFamily = static_cast< FontFamily >( nTmp );
+ if( pFontPitchState && (pFontPitchState->maValue >>= nTmp ) )
+ nPitch = static_cast< FontPitch >( nTmp );
+ if( pFontCharsetState && (pFontCharsetState->maValue >>= nTmp ) )
+ eEnc = static_cast<rtl_TextEncoding>(nTmp);
+
+ //Resolves: fdo#67665 The purpose here appears to be to replace
+ //FontFamilyName and FontStyleName etc with a single FontName property. The
+ //problem is that repeated calls to here will first set
+ //pFontFamilyNameState->mnIndex to -1 to indicate it is disabled, so the
+ //next time pFontFamilyNameState is not passed here at all, which gives an
+ //empty sFamilyName resulting in disabling pFontNameState->mnIndex to -1.
+ //That doesn't seem right to me.
+
+ //So assuming that the main purpose is just to convert the properties in
+ //the main when we can, and to leave them alone when we can't. And with a
+ //secondary purpose to filter out empty font properties, then is would
+ //appear to make sense to base attempting the conversion if we have
+ //both of the major facts of the font description
+
+ //An alternative solution is to *not* fill the FontAutoStylePool with
+ //every font in the document, but to partition the fonts into the
+ //hard-attribute fonts which go into that pool and the style-attribute
+ //fonts which go into some additional pool which get merged just for
+ //the purposes of writing the embedded fonts but are not queried by
+ //"Find" which restores the original logic.
+ if (pFontFamilyNameState || pFontStyleNameState)
+ {
+ OUString sName( const_cast<SvXMLExport&>(GetExport()).GetFontAutoStylePool()->Find(
+ sFamilyName, sStyleName, nFamily, nPitch, eEnc ) );
+ if (!sName.isEmpty())
+ {
+ pFontNameState->maValue <<= sName;
+ //Resolves: fdo#68431 style:font-name unrecognized by LibreOffice
+ //<= 4.1 in styles (but recognized in autostyles) so add
+ //fo:font-family, etc
+ if (!bEnableFoFontFamily)
+ {
+ if( pFontFamilyNameState )
+ pFontFamilyNameState->mnIndex = -1;
+ if( pFontStyleNameState )
+ pFontStyleNameState->mnIndex = -1;
+ if( pFontFamilyState )
+ pFontFamilyState->mnIndex = -1;
+ if( pFontPitchState )
+ pFontPitchState->mnIndex = -1;
+ if( pFontCharsetState )
+ pFontCharsetState->mnIndex = -1;
+ }
+ }
+ else
+ {
+ pFontNameState->mnIndex = -1;
+ }
+ }
+
+ if( pFontFamilyNameState && sFamilyName.isEmpty() )
+ {
+ pFontFamilyNameState->mnIndex = -1;
+ }
+
+ if( pFontStyleNameState && sStyleName.isEmpty() )
+ {
+ pFontStyleNameState->mnIndex = -1;
+ }
+}
+
+void XMLTextExportPropertySetMapper::ContextFontHeightFilter(
+ XMLPropertyState* pCharHeightState,
+ XMLPropertyState* pCharPropHeightState,
+ XMLPropertyState* pCharDiffHeightState )
+{
+ if( pCharPropHeightState )
+ {
+ sal_Int32 nTemp = 0;
+ pCharPropHeightState->maValue >>= nTemp;
+ if( nTemp == 100 )
+ {
+ pCharPropHeightState->mnIndex = -1;
+ pCharPropHeightState->maValue.clear();
+ }
+ else
+ {
+ pCharHeightState->mnIndex = -1;
+ pCharHeightState->maValue.clear();
+ }
+ }
+ if( !pCharDiffHeightState )
+ return;
+
+ float nTemp = 0;
+ pCharDiffHeightState->maValue >>= nTemp;
+ if( nTemp == 0. )
+ {
+ pCharDiffHeightState->mnIndex = -1;
+ pCharDiffHeightState->maValue.clear();
+ }
+ else
+ {
+ pCharHeightState->mnIndex = -1;
+ pCharHeightState->maValue.clear();
+ }
+
+}
+
+namespace {
+
+// helper method; implementation below
+bool lcl_IsOutlineStyle(const SvXMLExport&, std::u16string_view);
+
+void
+lcl_checkMultiProperty(XMLPropertyState *const pState,
+ XMLPropertyState *const pRelState)
+{
+ if (!(pState && pRelState))
+ return;
+
+ sal_Int32 nTemp = 0;
+ pRelState->maValue >>= nTemp;
+ if (100 == nTemp)
+ {
+ pRelState->mnIndex = -1;
+ pRelState->maValue.clear();
+ }
+ else
+ {
+ pState->mnIndex = -1;
+ pState->maValue.clear();
+ }
+}
+
+/**
+ * Filter context of paragraph and character borders.
+ * Compress border attributes. If one of groupable attributes (border type, border width, padding)
+ * is equal for all four side then just one general attribute will be exported.
+**/
+void lcl_FilterBorders(
+ XMLPropertyState* pAllBorderWidthState, XMLPropertyState* pLeftBorderWidthState,
+ XMLPropertyState* pRightBorderWidthState, XMLPropertyState* pTopBorderWidthState,
+ XMLPropertyState* pBottomBorderWidthState, XMLPropertyState* pAllBorderDistanceState,
+ XMLPropertyState* pLeftBorderDistanceState, XMLPropertyState* pRightBorderDistanceState,
+ XMLPropertyState* pTopBorderDistanceState, XMLPropertyState* pBottomBorderDistanceState,
+ XMLPropertyState* pAllBorderState, XMLPropertyState* pLeftBorderState,
+ XMLPropertyState* pRightBorderState,XMLPropertyState* pTopBorderState,
+ XMLPropertyState* pBottomBorderState )
+{
+ if( pAllBorderWidthState )
+ {
+ if( pLeftBorderWidthState && pRightBorderWidthState && pTopBorderWidthState && pBottomBorderWidthState )
+ {
+ table::BorderLine2 aLeft, aRight, aTop, aBottom;
+
+ pLeftBorderWidthState->maValue >>= aLeft;
+ pRightBorderWidthState->maValue >>= aRight;
+ pTopBorderWidthState->maValue >>= aTop;
+ pBottomBorderWidthState->maValue >>= aBottom;
+ if( aLeft.Color == aRight.Color && aLeft.InnerLineWidth == aRight.InnerLineWidth &&
+ aLeft.OuterLineWidth == aRight.OuterLineWidth && aLeft.LineDistance == aRight.LineDistance &&
+ aLeft.LineStyle == aRight.LineStyle &&
+ aLeft.LineWidth == aRight.LineWidth &&
+ aLeft.Color == aTop.Color && aLeft.InnerLineWidth == aTop.InnerLineWidth &&
+ aLeft.OuterLineWidth == aTop.OuterLineWidth && aLeft.LineDistance == aTop.LineDistance &&
+ aLeft.LineStyle == aTop.LineStyle &&
+ aLeft.LineWidth == aTop.LineWidth &&
+ aLeft.Color == aBottom.Color && aLeft.InnerLineWidth == aBottom.InnerLineWidth &&
+ aLeft.OuterLineWidth == aBottom.OuterLineWidth && aLeft.LineDistance == aBottom.LineDistance &&
+ aLeft.LineStyle == aBottom.LineStyle &&
+ aLeft.LineWidth == aBottom.LineWidth )
+ {
+ pLeftBorderWidthState->mnIndex = -1;
+ pLeftBorderWidthState->maValue.clear();
+ pRightBorderWidthState->mnIndex = -1;
+ pRightBorderWidthState->maValue.clear();
+ pTopBorderWidthState->mnIndex = -1;
+ pTopBorderWidthState->maValue.clear();
+ pBottomBorderWidthState->mnIndex = -1;
+ pBottomBorderWidthState->maValue.clear();
+ }
+ else
+ {
+ pAllBorderWidthState->mnIndex = -1;
+ pAllBorderWidthState->maValue.clear();
+ }
+ }
+ else
+ {
+ pAllBorderWidthState->mnIndex = -1;
+ pAllBorderWidthState->maValue.clear();
+ }
+ }
+
+ if( pAllBorderDistanceState )
+ {
+ if( pLeftBorderDistanceState && pRightBorderDistanceState && pTopBorderDistanceState && pBottomBorderDistanceState )
+ {
+ sal_Int32 aLeft = 0, aRight = 0, aTop = 0, aBottom = 0;
+
+ pLeftBorderDistanceState->maValue >>= aLeft;
+ pRightBorderDistanceState->maValue >>= aRight;
+ pTopBorderDistanceState->maValue >>= aTop;
+ pBottomBorderDistanceState->maValue >>= aBottom;
+ if( aLeft == aRight && aLeft == aTop && aLeft == aBottom )
+ {
+ pLeftBorderDistanceState->mnIndex = -1;
+ pLeftBorderDistanceState->maValue.clear();
+ pRightBorderDistanceState->mnIndex = -1;
+ pRightBorderDistanceState->maValue.clear();
+ pTopBorderDistanceState->mnIndex = -1;
+ pTopBorderDistanceState->maValue.clear();
+ pBottomBorderDistanceState->mnIndex = -1;
+ pBottomBorderDistanceState->maValue.clear();
+ }
+ else
+ {
+ pAllBorderDistanceState->mnIndex = -1;
+ pAllBorderDistanceState->maValue.clear();
+ }
+ }
+ else
+ {
+ pAllBorderDistanceState->mnIndex = -1;
+ pAllBorderDistanceState->maValue.clear();
+ }
+ }
+
+ if( !pAllBorderState )
+ return;
+
+ if( pLeftBorderState && pRightBorderState && pTopBorderState && pBottomBorderState )
+ {
+ table::BorderLine2 aLeft, aRight, aTop, aBottom;
+
+ pLeftBorderState->maValue >>= aLeft;
+ pRightBorderState->maValue >>= aRight;
+ pTopBorderState->maValue >>= aTop;
+ pBottomBorderState->maValue >>= aBottom;
+ if( aLeft.Color == aRight.Color && aLeft.InnerLineWidth == aRight.InnerLineWidth &&
+ aLeft.OuterLineWidth == aRight.OuterLineWidth && aLeft.LineDistance == aRight.LineDistance &&
+ aLeft.LineStyle == aRight.LineStyle &&
+ aLeft.LineWidth == aRight.LineWidth &&
+ aLeft.Color == aTop.Color && aLeft.InnerLineWidth == aTop.InnerLineWidth &&
+ aLeft.OuterLineWidth == aTop.OuterLineWidth && aLeft.LineDistance == aTop.LineDistance &&
+ aLeft.LineStyle == aTop.LineStyle &&
+ aLeft.LineWidth == aTop.LineWidth &&
+ aLeft.Color == aBottom.Color && aLeft.InnerLineWidth == aBottom.InnerLineWidth &&
+ aLeft.OuterLineWidth == aBottom.OuterLineWidth && aLeft.LineDistance == aBottom.LineDistance &&
+ aLeft.LineWidth == aBottom.LineWidth &&
+ aLeft.LineStyle == aBottom.LineStyle )
+ {
+ pLeftBorderState->mnIndex = -1;
+ pLeftBorderState->maValue.clear();
+ pRightBorderState->mnIndex = -1;
+ pRightBorderState->maValue.clear();
+ pTopBorderState->mnIndex = -1;
+ pTopBorderState->maValue.clear();
+ pBottomBorderState->mnIndex = -1;
+ pBottomBorderState->maValue.clear();
+ }
+ else
+ {
+ pAllBorderState->mnIndex = -1;
+ pAllBorderState->maValue.clear();
+ }
+ }
+ else
+ {
+ pAllBorderState->mnIndex = -1;
+ pAllBorderState->maValue.clear();
+ }
+}
+
+}
+
+void XMLTextExportPropertySetMapper::ContextFilter(
+ bool bEnableFoFontFamily,
+ ::std::vector< XMLPropertyState >& rProperties,
+ const Reference< XPropertySet >& rPropSet ) const
+{
+ // filter font
+ XMLPropertyState *pFontNameState = nullptr;
+ XMLPropertyState *pFontFamilyNameState = nullptr;
+ XMLPropertyState *pFontStyleNameState = nullptr;
+ XMLPropertyState *pFontFamilyState = nullptr;
+ XMLPropertyState *pFontPitchState = nullptr;
+ XMLPropertyState *pFontCharsetState = nullptr;
+ XMLPropertyState *pFontNameCJKState = nullptr;
+ XMLPropertyState *pFontFamilyNameCJKState = nullptr;
+ XMLPropertyState *pFontStyleNameCJKState = nullptr;
+ XMLPropertyState *pFontFamilyCJKState = nullptr;
+ XMLPropertyState *pFontPitchCJKState = nullptr;
+ XMLPropertyState *pFontCharsetCJKState = nullptr;
+ XMLPropertyState *pFontNameCTLState = nullptr;
+ XMLPropertyState *pFontFamilyNameCTLState = nullptr;
+ XMLPropertyState *pFontStyleNameCTLState = nullptr;
+ XMLPropertyState *pFontFamilyCTLState = nullptr;
+ XMLPropertyState *pFontPitchCTLState = nullptr;
+ XMLPropertyState *pFontCharsetCTLState = nullptr;
+
+ // filter char height point/percent
+ XMLPropertyState* pCharHeightState = nullptr;
+ XMLPropertyState* pCharPropHeightState = nullptr;
+ XMLPropertyState* pCharDiffHeightState = nullptr;
+ XMLPropertyState* pCharHeightCJKState = nullptr;
+ XMLPropertyState* pCharPropHeightCJKState = nullptr;
+ XMLPropertyState* pCharDiffHeightCJKState = nullptr;
+ XMLPropertyState* pCharHeightCTLState = nullptr;
+ XMLPropertyState* pCharPropHeightCTLState = nullptr;
+ XMLPropertyState* pCharDiffHeightCTLState = nullptr;
+
+ // filter left margin measure/percent
+ XMLPropertyState* pParaLeftMarginState = nullptr;
+ XMLPropertyState* pParaLeftMarginRelState = nullptr;
+
+ // filter right margin measure/percent
+ XMLPropertyState* pParaRightMarginState = nullptr;
+ XMLPropertyState* pParaRightMarginRelState = nullptr;
+
+ // filter first line indent measure/percent
+ XMLPropertyState* pParaFirstLineState = nullptr;
+ XMLPropertyState* pParaFirstLineRelState = nullptr;
+
+ // filter ParaTopMargin/Relative
+ XMLPropertyState* pParaTopMarginState = nullptr;
+ XMLPropertyState* pParaTopMarginRelState = nullptr;
+
+ // filter ParaTopMargin/Relative
+ XMLPropertyState* pParaBottomMarginState = nullptr;
+ XMLPropertyState* pParaBottomMarginRelState = nullptr;
+
+ // filter (Left|Right|Top|Bottom|)BorderWidth
+ XMLPropertyState* pAllBorderWidthState = nullptr;
+ XMLPropertyState* pLeftBorderWidthState = nullptr;
+ XMLPropertyState* pRightBorderWidthState = nullptr;
+ XMLPropertyState* pTopBorderWidthState = nullptr;
+ XMLPropertyState* pBottomBorderWidthState = nullptr;
+
+ // filter (Left|Right|Top|)BorderDistance
+ XMLPropertyState* pAllBorderDistanceState = nullptr;
+ XMLPropertyState* pLeftBorderDistanceState = nullptr;
+ XMLPropertyState* pRightBorderDistanceState = nullptr;
+ XMLPropertyState* pTopBorderDistanceState = nullptr;
+ XMLPropertyState* pBottomBorderDistanceState = nullptr;
+
+ // filter (Left|Right|Top|Bottom|)Border
+ XMLPropertyState* pAllBorderState = nullptr;
+ XMLPropertyState* pLeftBorderState = nullptr;
+ XMLPropertyState* pRightBorderState = nullptr;
+ XMLPropertyState* pTopBorderState = nullptr;
+ XMLPropertyState* pBottomBorderState = nullptr;
+
+ // filter Char(Left|Right|Top|Bottom|)BorderWidth
+ XMLPropertyState* pCharAllBorderWidthState = nullptr;
+ XMLPropertyState* pCharLeftBorderWidthState = nullptr;
+ XMLPropertyState* pCharRightBorderWidthState = nullptr;
+ XMLPropertyState* pCharTopBorderWidthState = nullptr;
+ XMLPropertyState* pCharBottomBorderWidthState = nullptr;
+
+ // filter Char(Left|Right|Top|)BorderDistance
+ XMLPropertyState* pCharAllBorderDistanceState = nullptr;
+ XMLPropertyState* pCharLeftBorderDistanceState = nullptr;
+ XMLPropertyState* pCharRightBorderDistanceState = nullptr;
+ XMLPropertyState* pCharTopBorderDistanceState = nullptr;
+ XMLPropertyState* pCharBottomBorderDistanceState = nullptr;
+
+ // filter Char(Left|Right|Top|Bottom|)Border
+ XMLPropertyState* pCharAllBorderState = nullptr;
+ XMLPropertyState* pCharLeftBorderState = nullptr;
+ XMLPropertyState* pCharRightBorderState = nullptr;
+ XMLPropertyState* pCharTopBorderState = nullptr;
+ XMLPropertyState* pCharBottomBorderState = nullptr;
+
+ // filter height properties
+ XMLPropertyState* pHeightMinAbsState = nullptr;
+ XMLPropertyState* pHeightMinRelState = nullptr;
+ XMLPropertyState* pHeightAbsState = nullptr;
+ XMLPropertyState* pHeightRelState = nullptr;
+ XMLPropertyState* pSizeTypeState = nullptr;
+
+ // filter width properties
+ XMLPropertyState* pWidthMinAbsState = nullptr;
+ XMLPropertyState* pWidthMinRelState = nullptr;
+ XMLPropertyState* pWidthAbsState = nullptr;
+ XMLPropertyState* pWidthRelState = nullptr;
+ XMLPropertyState* pWidthTypeState = nullptr;
+
+ // wrap
+ XMLPropertyState* pWrapState = nullptr;
+ XMLPropertyState* pWrapContourState = nullptr;
+ XMLPropertyState* pWrapContourModeState = nullptr;
+ XMLPropertyState* pWrapParagraphOnlyState = nullptr;
+
+ // anchor
+ XMLPropertyState* pAnchorTypeState = nullptr;
+
+ // horizontal position and relation
+ XMLPropertyState* pHoriOrientState = nullptr;
+ XMLPropertyState* pHoriOrientMirroredState = nullptr;
+ XMLPropertyState* pHoriOrientRelState = nullptr;
+ XMLPropertyState* pHoriOrientRelFrameState = nullptr;
+ XMLPropertyState* pHoriOrientMirrorState = nullptr;
+ // Horizontal position and relation for shapes (#i28749#)
+ XMLPropertyState* pShapeHoriOrientState = nullptr;
+ XMLPropertyState* pShapeHoriOrientMirroredState = nullptr;
+ XMLPropertyState* pShapeHoriOrientRelState = nullptr;
+ XMLPropertyState* pShapeHoriOrientRelFrameState = nullptr;
+ XMLPropertyState* pShapeHoriOrientMirrorState = nullptr;
+
+ // vertical position and relation
+ XMLPropertyState* pVertOrientState = nullptr;
+ XMLPropertyState* pVertOrientAtCharState = nullptr;
+ XMLPropertyState* pVertOrientRelState = nullptr;
+ XMLPropertyState* pVertOrientRelPageState = nullptr;
+ XMLPropertyState* pVertOrientRelFrameState = nullptr;
+ XMLPropertyState* pVertOrientRelAsCharState = nullptr;
+ XMLPropertyState* pRelWidthRel = nullptr;
+ XMLPropertyState* pRelHeightRel = nullptr;
+
+ // Vertical position and relation for shapes (#i28749#)
+ XMLPropertyState* pShapeVertOrientState = nullptr;
+ XMLPropertyState* pShapeVertOrientAtCharState = nullptr;
+ XMLPropertyState* pShapeVertOrientRelState = nullptr;
+ XMLPropertyState* pShapeVertOrientRelPageState = nullptr;
+ XMLPropertyState* pShapeVertOrientRelFrameState = nullptr;
+
+ // filter underline color
+ XMLPropertyState* pUnderlineState = nullptr;
+ XMLPropertyState* pUnderlineColorState = nullptr;
+ XMLPropertyState* pUnderlineHasColorState = nullptr;
+
+ // filter list style name
+ XMLPropertyState* pListStyleName = nullptr;
+
+ // filter fo:clip
+ XMLPropertyState* pClip11State = nullptr;
+ XMLPropertyState* pClipState = nullptr;
+
+ // filter fo:margin
+ XMLPropertyState* pAllParaMarginRel = nullptr;
+ XMLPropertyState* pAllParaMargin = nullptr;
+ XMLPropertyState* pAllMargin = nullptr;
+
+ XMLPropertyState* pRepeatOffsetX = nullptr;
+ XMLPropertyState* pRepeatOffsetY = nullptr;
+
+ // character background and highlight
+ XMLPropertyState* pCharBackground = nullptr;
+ XMLPropertyState* pCharBackgroundTransparency = nullptr;
+ XMLPropertyState* pCharHighlight = nullptr;
+
+ bool bNeedsAnchor = false;
+
+ for( auto& rPropertyState : rProperties )
+ {
+ XMLPropertyState *propertyState = &rPropertyState;
+ if( propertyState->mnIndex == -1 )
+ continue;
+
+ switch( getPropertySetMapper()->GetEntryContextId( propertyState->mnIndex ) )
+ {
+ case CTF_CHARHEIGHT: pCharHeightState = propertyState; break;
+ case CTF_CHARHEIGHT_REL: pCharPropHeightState = propertyState; break;
+ case CTF_CHARHEIGHT_DIFF: pCharDiffHeightState = propertyState; break;
+ case CTF_CHARHEIGHT_CJK: pCharHeightCJKState = propertyState; break;
+ case CTF_CHARHEIGHT_REL_CJK: pCharPropHeightCJKState = propertyState; break;
+ case CTF_CHARHEIGHT_DIFF_CJK: pCharDiffHeightCJKState = propertyState; break;
+ case CTF_CHARHEIGHT_CTL: pCharHeightCTLState = propertyState; break;
+ case CTF_CHARHEIGHT_REL_CTL: pCharPropHeightCTLState = propertyState; break;
+ case CTF_CHARHEIGHT_DIFF_CTL: pCharDiffHeightCTLState = propertyState; break;
+ case CTF_PARALEFTMARGIN: pParaLeftMarginState = propertyState; break;
+ case CTF_PARALEFTMARGIN_REL: pParaLeftMarginRelState = propertyState; break;
+ case CTF_PARARIGHTMARGIN: pParaRightMarginState = propertyState; break;
+ case CTF_PARARIGHTMARGIN_REL: pParaRightMarginRelState = propertyState; break;
+ case CTF_PARAFIRSTLINE: pParaFirstLineState = propertyState; break;
+ case CTF_PARAFIRSTLINE_REL: pParaFirstLineRelState = propertyState; break;
+ case CTF_PARATOPMARGIN: pParaTopMarginState = propertyState; break;
+ case CTF_PARATOPMARGIN_REL: pParaTopMarginRelState = propertyState; break;
+ case CTF_PARABOTTOMMARGIN: pParaBottomMarginState = propertyState; break;
+ case CTF_PARABOTTOMMARGIN_REL: pParaBottomMarginRelState = propertyState; break;
+
+ case CTF_ALLBORDERWIDTH: pAllBorderWidthState = propertyState; break;
+ case CTF_LEFTBORDERWIDTH: pLeftBorderWidthState = propertyState; break;
+ case CTF_RIGHTBORDERWIDTH: pRightBorderWidthState = propertyState; break;
+ case CTF_TOPBORDERWIDTH: pTopBorderWidthState = propertyState; break;
+ case CTF_BOTTOMBORDERWIDTH: pBottomBorderWidthState = propertyState; break;
+ case CTF_ALLBORDERDISTANCE: pAllBorderDistanceState = propertyState; break;
+ case CTF_LEFTBORDERDISTANCE: pLeftBorderDistanceState = propertyState; break;
+ case CTF_RIGHTBORDERDISTANCE: pRightBorderDistanceState = propertyState; break;
+ case CTF_TOPBORDERDISTANCE: pTopBorderDistanceState = propertyState; break;
+ case CTF_BOTTOMBORDERDISTANCE: pBottomBorderDistanceState = propertyState; break;
+ case CTF_ALLBORDER: pAllBorderState = propertyState; break;
+ case CTF_LEFTBORDER: pLeftBorderState = propertyState; break;
+ case CTF_RIGHTBORDER: pRightBorderState = propertyState; break;
+ case CTF_TOPBORDER: pTopBorderState = propertyState; break;
+ case CTF_BOTTOMBORDER: pBottomBorderState = propertyState; break;
+
+ case CTF_CHARALLBORDERWIDTH: pCharAllBorderWidthState = propertyState; break;
+ case CTF_CHARLEFTBORDERWIDTH: pCharLeftBorderWidthState = propertyState; break;
+ case CTF_CHARRIGHTBORDERWIDTH: pCharRightBorderWidthState = propertyState; break;
+ case CTF_CHARTOPBORDERWIDTH: pCharTopBorderWidthState = propertyState; break;
+ case CTF_CHARBOTTOMBORDERWIDTH: pCharBottomBorderWidthState = propertyState; break;
+ case CTF_CHARALLBORDERDISTANCE: pCharAllBorderDistanceState = propertyState; break;
+ case CTF_CHARLEFTBORDERDISTANCE: pCharLeftBorderDistanceState = propertyState; break;
+ case CTF_CHARRIGHTBORDERDISTANCE: pCharRightBorderDistanceState = propertyState; break;
+ case CTF_CHARTOPBORDERDISTANCE: pCharTopBorderDistanceState = propertyState; break;
+ case CTF_CHARBOTTOMBORDERDISTANCE: pCharBottomBorderDistanceState = propertyState; break;
+ case CTF_CHARALLBORDER: pCharAllBorderState = propertyState; break;
+ case CTF_CHARLEFTBORDER: pCharLeftBorderState = propertyState; break;
+ case CTF_CHARRIGHTBORDER: pCharRightBorderState = propertyState; break;
+ case CTF_CHARTOPBORDER: pCharTopBorderState = propertyState; break;
+ case CTF_CHARBOTTOMBORDER: pCharBottomBorderState = propertyState; break;
+
+ case CTF_FRAMEHEIGHT_MIN_ABS: pHeightMinAbsState = propertyState; break;
+ case CTF_FRAMEHEIGHT_MIN_REL: pHeightMinRelState = propertyState; break;
+ case CTF_FRAMEHEIGHT_ABS: pHeightAbsState = propertyState; break;
+ case CTF_FRAMEHEIGHT_REL: pHeightRelState = propertyState; break;
+ case CTF_SIZETYPE: pSizeTypeState = propertyState; break;
+
+ case CTF_FRAMEWIDTH_MIN_ABS: pWidthMinAbsState = propertyState; break;
+ case CTF_FRAMEWIDTH_MIN_REL: pWidthMinRelState = propertyState; break;
+ case CTF_FRAMEWIDTH_ABS: pWidthAbsState = propertyState; break;
+ case CTF_FRAMEWIDTH_REL: pWidthRelState = propertyState; break;
+ case CTF_FRAMEWIDTH_TYPE: pWidthTypeState = propertyState; break;
+
+ case CTF_WRAP: pWrapState = propertyState; break;
+ case CTF_WRAP_CONTOUR: pWrapContourState = propertyState; break;
+ case CTF_WRAP_CONTOUR_MODE: pWrapContourModeState = propertyState; break;
+ case CTF_WRAP_PARAGRAPH_ONLY: pWrapParagraphOnlyState = propertyState; break;
+ case CTF_ANCHORTYPE: pAnchorTypeState = propertyState; break;
+
+ case CTF_HORIZONTALPOS: pHoriOrientState = propertyState; bNeedsAnchor = true; break;
+ case CTF_HORIZONTALPOS_MIRRORED: pHoriOrientMirroredState = propertyState; bNeedsAnchor = true; break;
+ case CTF_HORIZONTALREL: pHoriOrientRelState = propertyState; bNeedsAnchor = true; break;
+ case CTF_HORIZONTALREL_FRAME: pHoriOrientRelFrameState = propertyState; bNeedsAnchor = true; break;
+ case CTF_HORIZONTALMIRROR: pHoriOrientMirrorState = propertyState; bNeedsAnchor = true; break;
+ case CTF_RELWIDTHREL: pRelWidthRel = propertyState; break;
+ case CTF_VERTICALPOS: pVertOrientState = propertyState; bNeedsAnchor = true; break;
+ case CTF_VERTICALPOS_ATCHAR: pVertOrientAtCharState = propertyState; bNeedsAnchor = true; break;
+ case CTF_VERTICALREL: pVertOrientRelState = propertyState; bNeedsAnchor = true; break;
+ case CTF_VERTICALREL_PAGE: pVertOrientRelPageState = propertyState; bNeedsAnchor = true; break;
+ case CTF_VERTICALREL_FRAME: pVertOrientRelFrameState = propertyState; bNeedsAnchor = true; break;
+ case CTF_VERTICALREL_ASCHAR: pVertOrientRelAsCharState = propertyState; bNeedsAnchor = true; break;
+ case CTF_RELHEIGHTREL: pRelHeightRel = propertyState; break;
+
+ // Handle new CTFs for shape positioning properties (#i28749#)
+ case CTF_SHAPE_HORIZONTALPOS: pShapeHoriOrientState = propertyState; bNeedsAnchor = true; break;
+ case CTF_SHAPE_HORIZONTALPOS_MIRRORED: pShapeHoriOrientMirroredState = propertyState; bNeedsAnchor = true; break;
+ case CTF_SHAPE_HORIZONTALREL: pShapeHoriOrientRelState = propertyState; bNeedsAnchor = true; break;
+ case CTF_SHAPE_HORIZONTALREL_FRAME: pShapeHoriOrientRelFrameState = propertyState; bNeedsAnchor = true; break;
+ case CTF_SHAPE_HORIZONTALMIRROR: pShapeHoriOrientMirrorState = propertyState; bNeedsAnchor = true; break;
+ case CTF_SHAPE_VERTICALPOS: pShapeVertOrientState = propertyState; bNeedsAnchor = true; break;
+ case CTF_SHAPE_VERTICALPOS_ATCHAR: pShapeVertOrientAtCharState = propertyState; bNeedsAnchor = true; break;
+ case CTF_SHAPE_VERTICALREL: pShapeVertOrientRelState = propertyState; bNeedsAnchor = true; break;
+ case CTF_SHAPE_VERTICALREL_PAGE: pShapeVertOrientRelPageState = propertyState; bNeedsAnchor = true; break;
+ case CTF_SHAPE_VERTICALREL_FRAME: pShapeVertOrientRelFrameState = propertyState; bNeedsAnchor = true; break;
+ case CTF_FONTNAME: pFontNameState = propertyState; break;
+ case CTF_FONTFAMILYNAME: pFontFamilyNameState = propertyState; break;
+ case CTF_FONTSTYLENAME: pFontStyleNameState = propertyState; break;
+ case CTF_FONTFAMILY: pFontFamilyState = propertyState; break;
+ case CTF_FONTPITCH: pFontPitchState = propertyState; break;
+ case CTF_FONTCHARSET: pFontCharsetState = propertyState; break;
+
+ case CTF_FONTNAME_CJK: pFontNameCJKState = propertyState; break;
+ case CTF_FONTFAMILYNAME_CJK: pFontFamilyNameCJKState = propertyState; break;
+ case CTF_FONTSTYLENAME_CJK: pFontStyleNameCJKState = propertyState; break;
+ case CTF_FONTFAMILY_CJK: pFontFamilyCJKState = propertyState; break;
+ case CTF_FONTPITCH_CJK: pFontPitchCJKState = propertyState; break;
+ case CTF_FONTCHARSET_CJK: pFontCharsetCJKState = propertyState; break;
+
+ case CTF_FONTNAME_CTL: pFontNameCTLState = propertyState; break;
+ case CTF_FONTFAMILYNAME_CTL: pFontFamilyNameCTLState = propertyState; break;
+ case CTF_FONTSTYLENAME_CTL: pFontStyleNameCTLState = propertyState; break;
+ case CTF_FONTFAMILY_CTL: pFontFamilyCTLState = propertyState; break;
+ case CTF_FONTPITCH_CTL: pFontPitchCTLState = propertyState; break;
+ case CTF_FONTCHARSET_CTL: pFontCharsetCTLState = propertyState; break;
+ case CTF_UNDERLINE: pUnderlineState = propertyState; break;
+ case CTF_UNDERLINE_COLOR: pUnderlineColorState = propertyState; break;
+ case CTF_UNDERLINE_HASCOLOR: pUnderlineHasColorState = propertyState; break;
+ case CTF_NUMBERINGSTYLENAME: pListStyleName = propertyState; break;
+ case CTF_TEXT_CLIP11: pClip11State = propertyState; break;
+ case CTF_TEXT_CLIP: pClipState = propertyState; break;
+ case CTF_PARAMARGINALL_REL: pAllParaMarginRel = propertyState; break;
+ case CTF_PARAMARGINALL: pAllParaMargin = propertyState; break;
+ case CTF_MARGINALL: pAllMargin = propertyState; break;
+
+ case CTF_REPEAT_OFFSET_X:
+ pRepeatOffsetX = propertyState;
+ break;
+
+ case CTF_REPEAT_OFFSET_Y:
+ pRepeatOffsetY = propertyState;
+ break;
+
+ case CTF_FILLGRADIENTNAME:
+ case CTF_FILLHATCHNAME:
+ case CTF_FILLBITMAPNAME:
+ case CTF_FILLTRANSNAME:
+ {
+ OUString aStr;
+ if( (propertyState->maValue >>= aStr) && 0 == aStr.getLength() )
+ propertyState->mnIndex = -1;
+ }
+ break;
+
+ case CTF_CHAR_BACKGROUND: pCharBackground = propertyState; break;
+ case CTF_CHAR_BACKGROUND_TRANSPARENCY: pCharBackgroundTransparency = propertyState; break;
+ case CTF_CHAR_HIGHLIGHT: pCharHighlight = propertyState; break;
+ }
+ }
+
+ if( pRepeatOffsetX && pRepeatOffsetY )
+ {
+ sal_Int32 nOffset = 0;
+ if( ( pRepeatOffsetX->maValue >>= nOffset ) && ( nOffset == 0 ) )
+ pRepeatOffsetX->mnIndex = -1;
+ else
+ pRepeatOffsetY->mnIndex = -1;
+ }
+
+ if( pFontNameState )
+ ContextFontFilter( bEnableFoFontFamily, pFontNameState, pFontFamilyNameState,
+ pFontStyleNameState, pFontFamilyState,
+ pFontPitchState, pFontCharsetState );
+ if( pFontNameCJKState )
+ ContextFontFilter( bEnableFoFontFamily, pFontNameCJKState, pFontFamilyNameCJKState,
+ pFontStyleNameCJKState, pFontFamilyCJKState,
+ pFontPitchCJKState, pFontCharsetCJKState );
+ if( pFontNameCTLState )
+ ContextFontFilter( bEnableFoFontFamily, pFontNameCTLState, pFontFamilyNameCTLState,
+ pFontStyleNameCTLState, pFontFamilyCTLState,
+ pFontPitchCTLState, pFontCharsetCTLState );
+
+ if( pCharHeightState && (pCharPropHeightState || pCharDiffHeightState ) )
+ ContextFontHeightFilter( pCharHeightState, pCharPropHeightState,
+ pCharDiffHeightState );
+ if( pCharHeightCJKState &&
+ (pCharPropHeightCJKState || pCharDiffHeightCJKState ) )
+ ContextFontHeightFilter( pCharHeightCJKState, pCharPropHeightCJKState,
+ pCharDiffHeightCJKState );
+ if( pCharHeightCTLState &&
+ (pCharPropHeightCTLState || pCharDiffHeightCTLState ) )
+ ContextFontHeightFilter( pCharHeightCTLState, pCharPropHeightCTLState,
+ pCharDiffHeightCTLState );
+ if( pUnderlineColorState || pUnderlineHasColorState )
+ {
+ bool bClear = !pUnderlineState;
+ if( !bClear )
+ {
+ sal_Int16 nUnderline = 0;
+ pUnderlineState->maValue >>= nUnderline;
+ bClear = awt::FontUnderline::NONE == nUnderline;
+ }
+ if( bClear )
+ {
+ if( pUnderlineColorState )
+ pUnderlineColorState->mnIndex = -1;
+ if( pUnderlineHasColorState )
+ pUnderlineHasColorState->mnIndex = -1;
+ }
+ }
+
+ lcl_checkMultiProperty(pParaLeftMarginState, pParaLeftMarginRelState);
+ lcl_checkMultiProperty(pParaRightMarginState, pParaRightMarginRelState);
+ lcl_checkMultiProperty(pParaTopMarginState, pParaTopMarginRelState);
+ lcl_checkMultiProperty(pParaBottomMarginState, pParaBottomMarginRelState);
+ lcl_checkMultiProperty(pParaFirstLineState, pParaFirstLineRelState);
+
+ if (pAllParaMarginRel)
+ { // because older OOo/LO versions can't read fo:margin:
+ pAllParaMarginRel->mnIndex = -1; // just export individual attributes...
+ pAllParaMarginRel->maValue.clear();
+ }
+ if (pAllParaMargin)
+ {
+ pAllParaMargin->mnIndex = -1; // just export individual attributes...
+ pAllParaMargin->maValue.clear();
+ }
+ if (pAllMargin)
+ {
+ pAllMargin->mnIndex = -1; // just export individual attributes...
+ pAllMargin->maValue.clear();
+ }
+
+ lcl_FilterBorders(
+ pAllBorderWidthState, pLeftBorderWidthState, pRightBorderWidthState,
+ pTopBorderWidthState, pBottomBorderWidthState, pAllBorderDistanceState,
+ pLeftBorderDistanceState, pRightBorderDistanceState, pTopBorderDistanceState,
+ pBottomBorderDistanceState, pAllBorderState, pLeftBorderState,
+ pRightBorderState, pTopBorderState, pBottomBorderState);
+
+ lcl_FilterBorders(
+ pCharAllBorderWidthState, pCharLeftBorderWidthState, pCharRightBorderWidthState,
+ pCharTopBorderWidthState, pCharBottomBorderWidthState, pCharAllBorderDistanceState,
+ pCharLeftBorderDistanceState, pCharRightBorderDistanceState, pCharTopBorderDistanceState,
+ pCharBottomBorderDistanceState, pCharAllBorderState, pCharLeftBorderState,
+ pCharRightBorderState, pCharTopBorderState, pCharBottomBorderState);
+
+ sal_Int16 nSizeType = SizeType::FIX;
+ if( pSizeTypeState )
+ {
+ pSizeTypeState->maValue >>= nSizeType;
+ pSizeTypeState->mnIndex = -1;
+ }
+
+ if( pHeightMinAbsState )
+ {
+ sal_Int16 nRel = sal_Int16();
+ if( (SizeType::FIX == nSizeType) ||
+ ( pHeightMinRelState &&
+ ( !(pHeightMinRelState->maValue >>= nRel) || nRel > 0 ) ) )
+ {
+ pHeightMinAbsState->mnIndex = -1;
+ }
+
+ // export SizeType::VARIABLE as min-width="0"
+ if( SizeType::VARIABLE == nSizeType )
+ pHeightMinAbsState->maValue <<= static_cast<sal_Int32>( 0 );
+ }
+ if( pHeightMinRelState && SizeType::MIN != nSizeType)
+ pHeightMinRelState->mnIndex = -1;
+ if( pHeightAbsState && pHeightMinAbsState &&
+ -1 != pHeightMinAbsState->mnIndex )
+ pHeightAbsState->mnIndex = -1;
+ if( pHeightRelState && SizeType::FIX != nSizeType)
+ pHeightRelState->mnIndex = -1;
+
+ // frame width
+ nSizeType = SizeType::FIX;
+ if( pWidthTypeState )
+ {
+ pWidthTypeState->maValue >>= nSizeType;
+ pWidthTypeState->mnIndex = -1;
+ }
+ if( pWidthMinAbsState )
+ {
+ sal_Int16 nRel = sal_Int16();
+ if( (SizeType::FIX == nSizeType) ||
+ ( pWidthMinRelState &&
+ ( !(pWidthMinRelState->maValue >>= nRel) || nRel > 0 ) ) )
+ {
+ pWidthMinAbsState->mnIndex = -1;
+ }
+
+ // export SizeType::VARIABLE as min-width="0"
+ if( SizeType::VARIABLE == nSizeType )
+ pWidthMinAbsState->maValue <<= static_cast<sal_Int32>( 0 );
+ }
+ if( pWidthMinRelState && SizeType::MIN != nSizeType)
+ pWidthMinRelState->mnIndex = -1;
+ if( pWidthAbsState && pWidthMinAbsState &&
+ -1 != pWidthMinAbsState->mnIndex )
+ pWidthAbsState->mnIndex = -1;
+ if( pWidthRelState && SizeType::FIX != nSizeType)
+ pWidthRelState->mnIndex = -1;
+
+ if( pWrapState )
+ {
+ WrapTextMode eVal;
+ pWrapState->maValue >>= eVal;
+ switch( eVal )
+ {
+ case WrapTextMode_NONE:
+ // no wrapping: disable para-only and contour
+ if( pWrapParagraphOnlyState )
+ pWrapParagraphOnlyState->mnIndex = -1;
+ [[fallthrough]];
+ case WrapTextMode_THROUGH:
+ // wrap through: disable only contour
+ if( pWrapContourState )
+ pWrapContourState->mnIndex = -1;
+ break;
+ default:
+ break;
+ }
+ if( pWrapContourModeState &&
+ (!pWrapContourState ||
+ !*o3tl::doAccess<bool>(pWrapContourState ->maValue) ) )
+ pWrapContourModeState->mnIndex = -1;
+ }
+
+ TextContentAnchorType eAnchor = TextContentAnchorType_AT_PARAGRAPH;
+ if( pAnchorTypeState )
+ pAnchorTypeState->maValue >>= eAnchor;
+ else if( bNeedsAnchor )
+ {
+ Any aAny = rPropSet->getPropertyValue("AnchorType");
+ aAny >>= eAnchor;
+ }
+
+ // states for frame positioning attributes
+ {
+ if( pHoriOrientState && pHoriOrientMirroredState )
+ {
+ if( pHoriOrientMirrorState &&
+ *o3tl::doAccess<bool>(pHoriOrientMirrorState->maValue) )
+ pHoriOrientState->mnIndex = -1;
+ else
+ pHoriOrientMirroredState->mnIndex = -1;
+ }
+ if( pHoriOrientMirrorState )
+ pHoriOrientMirrorState->mnIndex = -1;
+
+ if( pHoriOrientRelState && TextContentAnchorType_AT_FRAME == eAnchor )
+ pHoriOrientRelState->mnIndex = -1;
+ if( pHoriOrientRelFrameState && TextContentAnchorType_AT_FRAME != eAnchor )
+ pHoriOrientRelFrameState->mnIndex = -1;
+ if (pRelWidthRel)
+ {
+ sal_Int16 nRelWidth = 0;
+ rPropSet->getPropertyValue("RelativeWidth") >>= nRelWidth;
+ if (!nRelWidth)
+ pRelWidthRel->mnIndex = -1;
+ }
+
+ if( pVertOrientState && TextContentAnchorType_AT_CHARACTER == eAnchor )
+ pVertOrientState->mnIndex = -1;
+ if( pVertOrientAtCharState && TextContentAnchorType_AT_CHARACTER != eAnchor )
+ pVertOrientAtCharState->mnIndex = -1;
+ if( pVertOrientRelState && TextContentAnchorType_AT_PARAGRAPH != eAnchor &&
+ TextContentAnchorType_AT_CHARACTER != eAnchor )
+ pVertOrientRelState->mnIndex = -1;
+ if( pVertOrientRelPageState && TextContentAnchorType_AT_PAGE != eAnchor )
+ pVertOrientRelPageState->mnIndex = -1;
+ if( pVertOrientRelFrameState && TextContentAnchorType_AT_FRAME != eAnchor )
+ pVertOrientRelFrameState->mnIndex = -1;
+ if( pVertOrientRelAsCharState && TextContentAnchorType_AS_CHARACTER != eAnchor )
+ pVertOrientRelAsCharState->mnIndex = -1;
+ if (pRelHeightRel)
+ {
+ sal_Int16 nRelHeight = 0;
+ rPropSet->getPropertyValue("RelativeHeight") >>= nRelHeight;
+ if (!nRelHeight)
+ pRelHeightRel->mnIndex = -1;
+ }
+ }
+
+ // States for shape positioning properties (#i28749#)
+ if ( eAnchor != TextContentAnchorType_AS_CHARACTER &&
+ !( GetExport().getExportFlags() & SvXMLExportFlags::OASIS ) )
+ {
+ // no export of shape positioning properties,
+ // if shape isn't anchored as-character and
+ // destination file format is OpenOffice.org file format
+ if ( pShapeHoriOrientState )
+ pShapeHoriOrientState->mnIndex = -1;
+ if ( pShapeHoriOrientMirroredState )
+ pShapeHoriOrientMirroredState->mnIndex = -1;
+ if ( pShapeHoriOrientRelState )
+ pShapeHoriOrientRelState->mnIndex = -1;
+ if ( pShapeHoriOrientRelFrameState )
+ pShapeHoriOrientRelFrameState->mnIndex = -1;
+ if ( pShapeHoriOrientMirrorState )
+ pShapeHoriOrientMirrorState->mnIndex = -1;
+ if ( pShapeVertOrientState )
+ pShapeVertOrientState->mnIndex = -1;
+ if ( pShapeVertOrientAtCharState )
+ pShapeVertOrientAtCharState->mnIndex = -1;
+ if ( pShapeVertOrientRelState )
+ pShapeVertOrientRelState->mnIndex = -1;
+ if ( pShapeVertOrientRelPageState )
+ pShapeVertOrientRelPageState->mnIndex = -1;
+ if ( pShapeVertOrientRelFrameState )
+ pShapeVertOrientRelFrameState->mnIndex = -1;
+ }
+ else
+ {
+ // handling of shape positioning property states as for frames - see above
+ if( pShapeHoriOrientState && pShapeHoriOrientMirroredState )
+ {
+ if( pShapeHoriOrientMirrorState &&
+ *o3tl::doAccess<bool>(pShapeHoriOrientMirrorState->maValue) )
+ pShapeHoriOrientState->mnIndex = -1;
+ else
+ pShapeHoriOrientMirroredState->mnIndex = -1;
+ }
+ if( pShapeHoriOrientMirrorState )
+ pShapeHoriOrientMirrorState->mnIndex = -1;
+
+ if( pShapeHoriOrientRelState && TextContentAnchorType_AT_FRAME == eAnchor )
+ pShapeHoriOrientRelState->mnIndex = -1;
+ if( pShapeHoriOrientRelFrameState && TextContentAnchorType_AT_FRAME != eAnchor )
+ pShapeHoriOrientRelFrameState->mnIndex = -1;
+
+ if( pShapeVertOrientState && TextContentAnchorType_AT_CHARACTER == eAnchor )
+ pShapeVertOrientState->mnIndex = -1;
+ if( pShapeVertOrientAtCharState && TextContentAnchorType_AT_CHARACTER != eAnchor )
+ pShapeVertOrientAtCharState->mnIndex = -1;
+ if( pShapeVertOrientRelState && TextContentAnchorType_AT_PARAGRAPH != eAnchor &&
+ TextContentAnchorType_AT_CHARACTER != eAnchor )
+ pShapeVertOrientRelState->mnIndex = -1;
+ if( pShapeVertOrientRelPageState && TextContentAnchorType_AT_PAGE != eAnchor )
+ pShapeVertOrientRelPageState->mnIndex = -1;
+ if( pShapeVertOrientRelFrameState && TextContentAnchorType_AT_FRAME != eAnchor )
+ pShapeVertOrientRelFrameState->mnIndex = -1;
+ }
+
+ // list style name: remove list style if it is the default outline style
+ if( pListStyleName != nullptr )
+ {
+ OUString sListStyleName;
+ pListStyleName->maValue >>= sListStyleName;
+ if( lcl_IsOutlineStyle( GetExport(), sListStyleName ) )
+ pListStyleName->mnIndex = -1;
+ }
+
+ if( pClipState != nullptr && pClip11State != nullptr )
+ pClip11State->mnIndex = -1;
+
+ // When both background attributes are available export the visible one
+ if (pCharHighlight)
+ {
+ Color nColor = COL_TRANSPARENT;
+ pCharHighlight->maValue >>= nColor;
+ if( nColor == COL_TRANSPARENT )
+ {
+ // actually this would not be exported as transparent anyway
+ // and we'd need another property CharHighlightTransparent for that
+ pCharHighlight->mnIndex = -1;
+ }
+ // When both background attributes are available export the visible one
+ else if(pCharBackground)
+ {
+ assert(pCharBackgroundTransparency); // always together
+ pCharBackground->mnIndex = -1;
+ pCharBackgroundTransparency->mnIndex = -1;
+ }
+ }
+
+ SvXMLExportPropertyMapper::ContextFilter(bEnableFoFontFamily, rProperties, rPropSet);
+}
+
+namespace {
+
+bool lcl_IsOutlineStyle(const SvXMLExport &rExport, std::u16string_view rName)
+{
+ Reference< XChapterNumberingSupplier >
+ xCNSupplier(rExport.GetModel(), UNO_QUERY);
+
+ OUString sOutlineName;
+
+ if (xCNSupplier.is())
+ {
+ Reference<XPropertySet> xNumRule(
+ xCNSupplier->getChapterNumberingRules(), UNO_QUERY );
+ SAL_WARN_IF( !xNumRule.is(), "xmloff", "no chapter numbering rules" );
+ if (xNumRule.is())
+ {
+ xNumRule->getPropertyValue("Name") >>= sOutlineName;
+ }
+ }
+
+ return rName == sOutlineName;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/txtexppr.hxx b/xmloff/source/text/txtexppr.hxx
new file mode 100644
index 0000000000..46af0cb2bf
--- /dev/null
+++ b/xmloff/source/text/txtexppr.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/.
+ *
+ * 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 .
+ */
+#pragma once
+
+
+#include <xmloff/xmlexppr.hxx>
+#include "txtdrope.hxx"
+#include <xmltabe.hxx>
+#include <XMLTextColumnsExport.hxx>
+#include <XMLBackgroundImageExport.hxx>
+#include <xmloff/XMLComplexColorExport.hxx>
+
+class SvXMLExport;
+class XMLTextExportPropertySetMapper: public SvXMLExportPropertyMapper
+{
+ SvXMLExport& rExport;
+
+ OUString sDropCharStyle;
+ bool bDropWholeWord;
+
+ void ContextFontFilter(
+ bool bEnableFoFontFamily,
+ XMLPropertyState *pFontNameState,
+ XMLPropertyState *pFontFamilyNameState,
+ XMLPropertyState *pFontStyleNameState,
+ XMLPropertyState *pFontFamilyState,
+ XMLPropertyState *pFontPitchState,
+ XMLPropertyState *pFontCharsetState ) const;
+ static void ContextFontHeightFilter(
+ XMLPropertyState* pCharHeightState,
+ XMLPropertyState* pCharPropHeightState,
+ XMLPropertyState* pCharDiffHeightState );
+
+private:
+// SvXMLUnitConverter& mrUnitConverter;
+// const Reference< xml::sax::XDocumentHandler > & mrHandler;
+ XMLTextDropCapExport maDropCapExport;
+ SvxXMLTabStopExport maTabStopExport;
+ XMLTextColumnsExport maTextColumnsExport;
+ XMLComplexColorExport maComplexColorExport;
+ XMLBackgroundImageExport maBackgroundImageExport;
+
+ /** Application-specific filter. By default do nothing. */
+ virtual void ContextFilter(
+ bool bEnableFoFontFamily,
+ ::std::vector< XMLPropertyState >& rProperties,
+ const css::uno::Reference< css::beans::XPropertySet >& rPropSet ) const override;
+ const SvXMLExport& GetExport() const { return rExport; }
+
+public:
+
+ XMLTextExportPropertySetMapper(
+ const rtl::Reference< XMLPropertySetMapper >& rMapper,
+ SvXMLExport& rExt );
+ virtual ~XMLTextExportPropertySetMapper() override;
+
+ virtual void handleElementItem(
+ SvXMLExport& rExport,
+ const XMLPropertyState& rProperty,
+ SvXmlExportFlags nFlags,
+ const ::std::vector< XMLPropertyState > *pProperties,
+ sal_uInt32 nIdx ) const override;
+
+ virtual void handleSpecialItem(
+ comphelper::AttributeList& rAttrList,
+ const XMLPropertyState& rProperty,
+ const SvXMLUnitConverter& rUnitConverter,
+ const SvXMLNamespaceMap& rNamespaceMap,
+ const ::std::vector< XMLPropertyState > *pProperties,
+ sal_uInt32 nIdx ) const override;
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/txtflde.cxx b/xmloff/source/text/txtflde.cxx
new file mode 100644
index 0000000000..2c054d57e3
--- /dev/null
+++ b/xmloff/source/text/txtflde.cxx
@@ -0,0 +1,3616 @@
+/* -*- 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 .
+ */
+
+
+/** @#file
+ *
+ * export of all text fields
+ */
+#include <comphelper/propertyvalue.hxx>
+#include <txtflde.hxx>
+#include <xmloff/XMLEventExport.hxx>
+#include <xmloff/families.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/numehelp.hxx>
+#include <xmloff/xmlement.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/maptype.hxx>
+
+#include "XMLTextCharStyleNamesElementExport.hxx"
+#include <sax/tools/converter.hxx>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/text/UserDataPart.hpp>
+#include <com/sun/star/text/PageNumberType.hpp>
+#include <com/sun/star/style/NumberingType.hpp>
+#include <com/sun/star/text/ReferenceFieldPart.hpp>
+#include <com/sun/star/text/ReferenceFieldSource.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/text/XTextField.hpp>
+#include <com/sun/star/text/XDependentTextField.hpp>
+#include <com/sun/star/text/XTextFieldsSupplier.hpp>
+
+#include <com/sun/star/text/SetVariableType.hpp>
+#include <com/sun/star/text/PlaceholderType.hpp>
+#include <com/sun/star/text/FilenameDisplayFormat.hpp>
+#include <com/sun/star/text/ChapterFormat.hpp>
+#include <com/sun/star/text/TemplateDisplayFormat.hpp>
+#include <com/sun/star/container/XNameReplace.hpp>
+#include <com/sun/star/uno/Sequence.h>
+#include <com/sun/star/text/BibliographyDataType.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/rdf/XMetadatable.hpp>
+#include <comphelper/sequence.hxx>
+#include <o3tl/any.hxx>
+#include <o3tl/safeint.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <tools/debug.hxx>
+#include <rtl/math.hxx>
+#include <sal/log.hxx>
+
+#include <vector>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::style;
+using namespace ::com::sun::star::document;
+using namespace ::com::sun::star::container;
+using namespace ::xmloff::token;
+
+
+char const FIELD_SERVICE_SENDER[] = "ExtendedUser";
+char const FIELD_SERVICE_AUTHOR[] = "Author";
+char const FIELD_SERVICE_JUMPEDIT[] = "JumpEdit";
+char const FIELD_SERVICE_GETEXP[] = "GetExpression";
+char const FIELD_SERVICE_SETEXP[] = "SetExpression";
+char const FIELD_SERVICE_USER[] = "User";
+char const FIELD_SERVICE_INPUT[] = "Input";
+char const FIELD_SERVICE_USERINPUT[] = "InputUser";
+char const FIELD_SERVICE_DATETIME[] = "DateTime";
+char const FIELD_SERVICE_PAGENUMBER[] = "PageNumber";
+char const FIELD_SERVICE_DB_NEXT[] = "DatabaseNextSet";
+char const FIELD_SERVICE_DB_SELECT[] = "DatabaseNumberOfSet";
+char const FIELD_SERVICE_DB_NUMBER[] = "DatabaseSetNumber";
+char const FIELD_SERVICE_DB_DISPLAY[] = "Database";
+char const FIELD_SERVICE_DB_NAME[] = "DatabaseName";
+char const FIELD_SERVICE_CONDITIONAL_TEXT[] = "ConditionalText";
+char const FIELD_SERVICE_HIDDEN_TEXT[] = "HiddenText";
+char const FIELD_SERVICE_HIDDEN_PARAGRAPH[] = "HiddenParagraph";
+char const FIELD_SERVICE_DOC_INFO_CHANGE_AUTHOR[] = "DocInfo.ChangeAuthor";
+char const FIELD_SERVICE_DOC_INFO_CHANGE_AUTHOR2[] = "docinfo.ChangeAuthor";
+char const FIELD_SERVICE_DOC_INFO_CHANGE_DATE_TIME[] = "DocInfo.ChangeDateTime";
+char const FIELD_SERVICE_DOC_INFO_CHANGE_DATE_TIME2[] = "docinfo.ChangeDateTime";
+char const FIELD_SERVICE_DOC_INFO_EDIT_TIME[] = "DocInfo.EditTime";
+char const FIELD_SERVICE_DOC_INFO_EDIT_TIME2[] = "docinfo.EditTime";
+char const FIELD_SERVICE_DOC_INFO_DESCRIPTION[] = "DocInfo.Description";
+char const FIELD_SERVICE_DOC_INFO_DESCRIPTION2[] = "docinfo.Description";
+char const FIELD_SERVICE_DOC_INFO_CREATE_AUTHOR[] = "DocInfo.CreateAuthor";
+char const FIELD_SERVICE_DOC_INFO_CREATE_AUTHOR2[] = "docinfo.CreateAuthor";
+char const FIELD_SERVICE_DOC_INFO_CREATE_DATE_TIME[] = "DocInfo.CreateDateTime";
+char const FIELD_SERVICE_DOC_INFO_CREATE_DATE_TIME2[] = "docinfo.CreateDateTime";
+char const FIELD_SERVICE_DOC_INFO_CUSTOM[] = "DocInfo.Custom";
+char const FIELD_SERVICE_DOC_INFO_CUSTOM2[] = "docinfo.Custom";
+char const FIELD_SERVICE_DOC_INFO_PRINT_AUTHOR[] = "DocInfo.PrintAuthor";
+char const FIELD_SERVICE_DOC_INFO_PRINT_AUTHOR2[] = "docinfo.PrintAuthor";
+char const FIELD_SERVICE_DOC_INFO_PRINT_DATE_TIME[] = "DocInfo.PrintDateTime";
+char const FIELD_SERVICE_DOC_INFO_PRINT_DATE_TIME2[] = "docinfo.PrintDateTime";
+char const FIELD_SERVICE_DOC_INFO_KEY_WORDS[] = "DocInfo.KeyWords";
+char const FIELD_SERVICE_DOC_INFO_KEY_WORDS2[] = "docinfo.KeyWords";
+char const FIELD_SERVICE_DOC_INFO_SUBJECT[] = "DocInfo.Subject";
+char const FIELD_SERVICE_DOC_INFO_SUBJECT2[] = "docinfo.Subject";
+char const FIELD_SERVICE_DOC_INFO_TITLE[] = "DocInfo.Title";
+char const FIELD_SERVICE_DOC_INFO_TITLE2[] = "docinfo.Title";
+char const FIELD_SERVICE_DOC_INFO_REVISION[] = "DocInfo.Revision";
+char const FIELD_SERVICE_DOC_INFO_REVISION2[] = "docinfo.Revision";
+char const FIELD_SERVICE_FILE_NAME[] = "FileName";
+char const FIELD_SERVICE_CHAPTER[] = "Chapter";
+char const FIELD_SERVICE_TEMPLATE_NAME[] = "TemplateName";
+char const FIELD_SERVICE_PAGE_COUNT[] = "PageCount";
+char const FIELD_SERVICE_PARAGRAPH_COUNT[] = "ParagraphCount";
+char const FIELD_SERVICE_WORD_COUNT[] = "WordCount";
+char const FIELD_SERVICE_CHARACTER_COUNT[] = "CharacterCount";
+char const FIELD_SERVICE_TABLE_COUNT[] = "TableCount";
+char const FIELD_SERVICE_GRAPHIC_COUNT[] = "GraphicObjectCount";
+char const FIELD_SERVICE_OBJECT_COUNT[] = "EmbeddedObjectCount";
+char const FIELD_SERVICE_REFERENCE_PAGE_SET[] = "ReferencePageSet";
+char const FIELD_SERVICE_REFERENCE_PAGE_GET[] = "ReferencePageGet";
+char const FIELD_SERVICE_SHEET_NAME[] = "SheetName";
+char const FIELD_SERVICE_PAGE_NAME[] = "PageName";
+char const FIELD_SERVICE_MACRO[] = "Macro";
+char const FIELD_SERVICE_GET_REFERENCE[] = "GetReference";
+char const FIELD_SERVICE_DDE[] = "DDE";
+char const FIELD_SERVICE_URL[] = "URL";
+char const FIELD_SERVICE_BIBLIOGRAPHY[] = "Bibliography";
+char const FIELD_SERVICE_SCRIPT[] = "Script";
+char const FIELD_SERVICE_ANNOTATION[] = "Annotation";
+char const FIELD_SERVICE_COMBINED_CHARACTERS[] = "CombinedCharacters";
+char const FIELD_SERVICE_META[] = "MetadataField";
+char const FIELD_SERVICE_MEASURE[] = "Measure";
+char const FIELD_SERVICE_TABLE_FORMULA[] = "TableFormula";
+char const FIELD_SERVICE_DROP_DOWN[] = "DropDown";
+
+namespace
+{
+/// Walks up the parent chain of xText and returns the topmost text.
+uno::Reference<text::XText> GetToplevelText(const uno::Reference<text::XText>& xText)
+{
+ uno::Reference<text::XText> xRet = xText;
+ while (true)
+ {
+ uno::Reference<beans::XPropertySet> xPropertySet(xRet, uno::UNO_QUERY);
+ if (!xPropertySet.is())
+ return xRet;
+
+ if (!xPropertySet->getPropertySetInfo()->hasPropertyByName("ParentText"))
+ return xRet;
+
+ uno::Reference<text::XText> xParent;
+ if (xPropertySet->getPropertyValue("ParentText") >>= xParent)
+ xRet = xParent;
+ else
+ return xRet;
+ }
+ return xRet;
+}
+}
+
+SvXMLEnumStringMapEntry<FieldIdEnum> const aFieldServiceNameMapping[] =
+{
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_SENDER, FIELD_ID_SENDER ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_AUTHOR, FIELD_ID_AUTHOR ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_JUMPEDIT, FIELD_ID_PLACEHOLDER ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_GETEXP, FIELD_ID_VARIABLE_GET ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_SETEXP, FIELD_ID_VARIABLE_SET ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_USER, FIELD_ID_USER_GET ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_INPUT, FIELD_ID_TEXT_INPUT ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_USERINPUT, FIELD_ID_USER_INPUT ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DATETIME, FIELD_ID_TIME ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_PAGENUMBER, FIELD_ID_PAGENUMBER ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_REFERENCE_PAGE_SET, FIELD_ID_REFPAGE_SET ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_REFERENCE_PAGE_GET, FIELD_ID_REFPAGE_GET ),
+
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DB_NEXT, FIELD_ID_DATABASE_NEXT ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DB_SELECT, FIELD_ID_DATABASE_SELECT ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DB_NUMBER, FIELD_ID_DATABASE_NUMBER ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DB_DISPLAY, FIELD_ID_DATABASE_DISPLAY ),
+ // workaround for #no-bug#: Database/DataBase
+ ENUM_STRING_MAP_ENTRY( "DataBase", FIELD_ID_DATABASE_DISPLAY ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DB_NAME, FIELD_ID_DATABASE_NAME ),
+
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_CREATE_AUTHOR, FIELD_ID_DOCINFO_CREATION_AUTHOR ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_CREATE_AUTHOR2, FIELD_ID_DOCINFO_CREATION_AUTHOR ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_CREATE_DATE_TIME, FIELD_ID_DOCINFO_CREATION_TIME),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_CREATE_DATE_TIME2, FIELD_ID_DOCINFO_CREATION_TIME),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_CHANGE_AUTHOR, FIELD_ID_DOCINFO_SAVE_AUTHOR ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_CHANGE_AUTHOR2, FIELD_ID_DOCINFO_SAVE_AUTHOR ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_CHANGE_DATE_TIME, FIELD_ID_DOCINFO_SAVE_TIME ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_CHANGE_DATE_TIME2, FIELD_ID_DOCINFO_SAVE_TIME ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_EDIT_TIME, FIELD_ID_DOCINFO_EDIT_DURATION ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_EDIT_TIME2, FIELD_ID_DOCINFO_EDIT_DURATION ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_DESCRIPTION, FIELD_ID_DOCINFO_DESCRIPTION ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_DESCRIPTION2, FIELD_ID_DOCINFO_DESCRIPTION ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_CUSTOM, FIELD_ID_DOCINFO_CUSTOM ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_CUSTOM2, FIELD_ID_DOCINFO_CUSTOM ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_PRINT_AUTHOR, FIELD_ID_DOCINFO_PRINT_AUTHOR ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_PRINT_AUTHOR2, FIELD_ID_DOCINFO_PRINT_AUTHOR ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_PRINT_DATE_TIME, FIELD_ID_DOCINFO_PRINT_TIME ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_PRINT_DATE_TIME2, FIELD_ID_DOCINFO_PRINT_TIME ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_KEY_WORDS, FIELD_ID_DOCINFO_KEYWORDS ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_KEY_WORDS2, FIELD_ID_DOCINFO_KEYWORDS ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_SUBJECT, FIELD_ID_DOCINFO_SUBJECT ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_SUBJECT2, FIELD_ID_DOCINFO_SUBJECT ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_TITLE, FIELD_ID_DOCINFO_TITLE ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_TITLE2, FIELD_ID_DOCINFO_TITLE ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_REVISION, FIELD_ID_DOCINFO_REVISION ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_REVISION2, FIELD_ID_DOCINFO_REVISION ),
+
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_CONDITIONAL_TEXT, FIELD_ID_CONDITIONAL_TEXT ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_HIDDEN_TEXT, FIELD_ID_HIDDEN_TEXT ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_HIDDEN_PARAGRAPH, FIELD_ID_HIDDEN_PARAGRAPH ),
+
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_FILE_NAME, FIELD_ID_FILE_NAME ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_CHAPTER, FIELD_ID_CHAPTER ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_TEMPLATE_NAME, FIELD_ID_TEMPLATE_NAME ),
+
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_PAGE_COUNT, FIELD_ID_COUNT_PAGES ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_PARAGRAPH_COUNT, FIELD_ID_COUNT_PARAGRAPHS ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_WORD_COUNT, FIELD_ID_COUNT_WORDS ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_CHARACTER_COUNT, FIELD_ID_COUNT_CHARACTERS ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_TABLE_COUNT, FIELD_ID_COUNT_TABLES ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_GRAPHIC_COUNT, FIELD_ID_COUNT_GRAPHICS ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_OBJECT_COUNT, FIELD_ID_COUNT_OBJECTS ),
+
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_MACRO, FIELD_ID_MACRO ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_GET_REFERENCE, FIELD_ID_REF_REFERENCE ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DDE, FIELD_ID_DDE ),
+
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_BIBLIOGRAPHY, FIELD_ID_BIBLIOGRAPHY ),
+
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_SCRIPT, FIELD_ID_SCRIPT ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_ANNOTATION, FIELD_ID_ANNOTATION ),
+
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_COMBINED_CHARACTERS, FIELD_ID_COMBINED_CHARACTERS ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_META, FIELD_ID_META ),
+
+ // non-writer fields
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_SHEET_NAME, FIELD_ID_SHEET_NAME ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_PAGE_NAME, FIELD_ID_PAGENAME ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_URL, FIELD_ID_URL ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_MEASURE, FIELD_ID_MEASURE ),
+
+ // deprecated fields
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_TABLE_FORMULA, FIELD_ID_TABLE_FORMULA ),
+ ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DROP_DOWN, FIELD_ID_DROP_DOWN ),
+
+ { nullptr, 0, FieldIdEnum(0) }
+};
+
+
+// property accessor helper functions
+static bool GetBoolProperty(const OUString&,
+ const Reference<XPropertySet> &);
+static bool GetOptionalBoolProperty(const OUString&,
+ const Reference<XPropertySet> &,
+ const Reference<XPropertySetInfo> &,
+ bool bDefault);
+static double GetDoubleProperty(const OUString&,
+ const Reference<XPropertySet> &);
+static OUString GetStringProperty(const OUString&,
+ const Reference<XPropertySet> &);
+static sal_Int32 GetIntProperty(const OUString&,
+ const Reference<XPropertySet> &);
+static sal_Int16 GetInt16Property(const OUString&,
+ const Reference<XPropertySet> &);
+static sal_Int8 GetInt8Property(const OUString&,
+ const Reference<XPropertySet> &);
+static util::DateTime GetDateTimeProperty( const OUString& sPropName,
+ const Reference<XPropertySet> & xPropSet);
+static Sequence<OUString> GetStringSequenceProperty(
+ const OUString& sPropName,
+ const Reference<XPropertySet> & xPropSet);
+
+
+ // service names
+constexpr OUString gsServicePrefix(u"com.sun.star.text.textfield."_ustr);
+constexpr OUStringLiteral gsFieldMasterPrefix(u"com.sun.star.text.FieldMaster.");
+constexpr OUString gsPresentationServicePrefix(u"com.sun.star.presentation.TextField."_ustr);
+
+ // property names
+constexpr OUString gsPropertyAdjust(u"Adjust"_ustr);
+constexpr OUStringLiteral gsPropertyAuthor(u"Author");
+constexpr OUStringLiteral gsPropertyChapterFormat(u"ChapterFormat");
+constexpr OUStringLiteral gsPropertyChapterNumberingLevel(u"ChapterNumberingLevel");
+constexpr OUStringLiteral gsPropertyCharStyleNames(u"CharStyleNames");
+constexpr OUString gsPropertyCondition(u"Condition"_ustr);
+constexpr OUString gsPropertyContent(u"Content"_ustr);
+constexpr OUStringLiteral gsPropertyDataBaseName(u"DataBaseName");
+constexpr OUString gsPropertyDataBaseURL(u"DataBaseURL"_ustr);
+constexpr OUStringLiteral gsPropertyDataColumnName(u"DataColumnName");
+constexpr OUString gsPropertyDataCommandType(u"DataCommandType"_ustr);
+constexpr OUString gsPropertyDataTableName(u"DataTableName"_ustr);
+constexpr OUString gsPropertyDateTime(u"DateTime"_ustr);
+constexpr OUString gsPropertyDateTimeValue(u"DateTimeValue"_ustr);
+constexpr OUStringLiteral gsPropertyDDECommandElement(u"DDECommandElement");
+constexpr OUStringLiteral gsPropertyDDECommandFile(u"DDECommandFile");
+constexpr OUStringLiteral gsPropertyDDECommandType(u"DDECommandType");
+constexpr OUStringLiteral gsPropertyDependentTextFields(u"DependentTextFields");
+constexpr OUStringLiteral gsPropertyFalseContent(u"FalseContent");
+constexpr OUStringLiteral gsPropertyFields(u"Fields");
+constexpr OUStringLiteral gsPropertyFieldSubType(u"UserDataType");
+constexpr OUString gsPropertyFileFormat(u"FileFormat"_ustr);
+constexpr OUStringLiteral gsPropertyFullName(u"FullName");
+constexpr OUString gsPropertyHint(u"Hint"_ustr);
+constexpr OUStringLiteral gsPropertyInitials(u"Initials");
+constexpr OUStringLiteral gsPropertyInstanceName(u"InstanceName");
+constexpr OUStringLiteral gsPropertyIsAutomaticUpdate(u"IsAutomaticUpdate");
+constexpr OUStringLiteral gsPropertyIsConditionTrue(u"IsConditionTrue");
+constexpr OUString gsPropertyIsDataBaseFormat(u"DataBaseFormat"_ustr);
+constexpr OUString gsPropertyIsDate(u"IsDate"_ustr);
+constexpr OUString gsPropertyIsExpression(u"IsExpression"_ustr);
+constexpr OUString gsPropertyIsFixed(u"IsFixed"_ustr);
+constexpr OUString gsPropertyIsFixedLanguage(u"IsFixedLanguage"_ustr);
+constexpr OUString gsPropertyIsHidden(u"IsHidden"_ustr);
+constexpr OUStringLiteral gsPropertyIsInput(u"Input");
+constexpr OUString gsPropertyIsShowFormula(u"IsShowFormula"_ustr);
+constexpr OUString gsPropertyIsVisible(u"IsVisible"_ustr);
+constexpr OUStringLiteral gsPropertyItems(u"Items");
+constexpr OUStringLiteral gsPropertyLevel(u"Level");
+constexpr OUStringLiteral gsPropertyMeasureKind(u"Kind");
+constexpr OUString gsPropertyName(u"Name"_ustr);
+constexpr OUStringLiteral gsPropertyParentName(u"ParentName");
+constexpr OUString gsPropertyNumberFormat(u"NumberFormat"_ustr);
+constexpr OUStringLiteral gsPropertyNumberingSeparator(u"NumberingSeparator");
+constexpr OUString gsPropertyNumberingType(u"NumberingType"_ustr);
+constexpr OUString gsPropertyOffset(u"Offset"_ustr);
+constexpr OUStringLiteral gsPropertyOn(u"On");
+constexpr OUStringLiteral gsPropertyPlaceholderType(u"PlaceHolderType");
+constexpr OUString gsPropertyReferenceFieldFlags(u"ReferenceFieldFlags"_ustr);
+constexpr OUString gsPropertyReferenceFieldPart(u"ReferenceFieldPart"_ustr);
+constexpr OUString gsPropertyReferenceFieldSource(u"ReferenceFieldSource"_ustr);
+constexpr OUString gsPropertyReferenceFieldLanguage(u"ReferenceFieldLanguage"_ustr);
+constexpr OUStringLiteral gsPropertyScriptType(u"ScriptType");
+constexpr OUStringLiteral gsPropertySelectedItem(u"SelectedItem");
+constexpr OUString gsPropertySequenceNumber(u"SequenceNumber"_ustr);
+constexpr OUStringLiteral gsPropertySequenceValue(u"SequenceValue");
+constexpr OUString gsPropertySetNumber(u"SetNumber"_ustr);
+constexpr OUString gsPropertySourceName(u"SourceName"_ustr);
+constexpr OUString gsPropertySubType(u"SubType"_ustr);
+constexpr OUStringLiteral gsPropertyTargetFrame(u"TargetFrame");
+constexpr OUStringLiteral gsPropertyTrueContent(u"TrueContent");
+constexpr OUStringLiteral gsPropertyURL(u"URL");
+constexpr OUStringLiteral gsPropertyURLContent(u"URLContent");
+constexpr OUStringLiteral gsPropertyUserText(u"UserText");
+constexpr OUString gsPropertyValue(u"Value"_ustr);
+constexpr OUString gsPropertyVariableName(u"VariableName"_ustr);
+constexpr OUString gsPropertyHelp(u"Help"_ustr);
+constexpr OUString gsPropertyTooltip(u"Tooltip"_ustr);
+constexpr OUStringLiteral gsPropertyTextRange(u"TextRange");
+
+XMLTextFieldExport::XMLTextFieldExport( SvXMLExport& rExp,
+ std::unique_ptr<XMLPropertyState> pCombinedCharState)
+ : rExport(rExp),
+ pCombinedCharactersPropertyState(std::move(pCombinedCharState))
+{
+ SetExportOnlyUsedFieldDeclarations();
+}
+
+XMLTextFieldExport::~XMLTextFieldExport()
+{
+}
+
+/// get the field ID (as in FieldIDEnum) from XTextField
+enum FieldIdEnum XMLTextFieldExport::GetFieldID(
+ const Reference<XTextField> & rTextField,
+ const Reference<XPropertySet> & xPropSet)
+{
+ // get service names for rTextField (via XServiceInfo service)
+ Reference<XServiceInfo> xService(rTextField, UNO_QUERY);
+ const Sequence<OUString> aServices = xService->getSupportedServiceNames();
+
+ OUString sFieldName; // service name postfix of current field
+
+ // search for TextField service name
+ const OUString* pNames = std::find_if(aServices.begin(), aServices.end(),
+ [](const OUString& rName) { return rName.matchIgnoreAsciiCase(gsServicePrefix); });
+ if (pNames != aServices.end())
+ {
+ // TextField found => postfix is field type!
+ sFieldName = pNames->copy(gsServicePrefix.getLength());
+ }
+
+ // if this is not a normal text field, check if it's a presentation text field
+ if( sFieldName.isEmpty() )
+ {
+ // search for TextField service name
+ pNames = std::find_if(aServices.begin(), aServices.end(),
+ [](const OUString& rName) { return rName.startsWith(gsPresentationServicePrefix); });
+ if (pNames != aServices.end())
+ {
+ // TextField found => postfix is field type!
+ sFieldName = pNames->copy(gsPresentationServicePrefix.getLength());
+ }
+
+ if( !sFieldName.isEmpty() )
+ {
+ if( sFieldName == "Header" )
+ {
+ return FIELD_ID_DRAW_HEADER;
+ }
+ else if( sFieldName == "Footer" )
+ {
+ return FIELD_ID_DRAW_FOOTER;
+ }
+ else if( sFieldName == "DateTime" )
+ {
+ return FIELD_ID_DRAW_DATE_TIME;
+ }
+ }
+ }
+
+ // map postfix of service name to field ID
+ DBG_ASSERT(!sFieldName.isEmpty(), "no TextField service found!");
+ return MapFieldName(sFieldName, xPropSet);
+}
+
+enum FieldIdEnum XMLTextFieldExport::MapFieldName(
+ std::u16string_view sFieldName, // field (master) name
+ const Reference<XPropertySet> & xPropSet) // for subtype
+{
+ // we'll proceed in 2 steps:
+ // a) map service name to preliminary FIELD_ID
+ // b) map those prelim. FIELD_IDs that correspond to several field types
+ // (in our (XML) world) to final FIELD IDs
+
+
+ // a) find prelim. FIELD_ID via aFieldServiceMapping
+
+ // check for non-empty service name
+ DBG_ASSERT(!sFieldName.empty(), "no valid service name!");
+ enum FieldIdEnum nToken = FIELD_ID_UNKNOWN;
+ if (!sFieldName.empty())
+ {
+ // map name to prelim. ID
+ bool bRet = SvXMLUnitConverter::convertEnum(
+ nToken, sFieldName, aFieldServiceNameMapping);
+
+ // check return
+ DBG_ASSERT(bRet, "Unknown field service name encountered!");
+ }
+
+ // b) map prelim. to final FIELD_IDs
+ switch (nToken) {
+ case FIELD_ID_VARIABLE_SET:
+ if (GetBoolProperty(gsPropertyIsInput, xPropSet))
+ {
+ nToken = FIELD_ID_VARIABLE_INPUT;
+ }
+ else
+ {
+ switch (GetIntProperty(gsPropertySubType, xPropSet))
+ {
+ case SetVariableType::STRING: // text field
+ case SetVariableType::VAR: // num field
+ nToken = FIELD_ID_VARIABLE_SET;
+ break;
+ case SetVariableType::SEQUENCE:
+ nToken = FIELD_ID_SEQUENCE;
+ break;
+ case SetVariableType::FORMULA:
+ default:
+ nToken = FIELD_ID_UNKNOWN;
+ break;
+ }
+ }
+ break;
+
+ case FIELD_ID_VARIABLE_GET:
+ switch (GetIntProperty(gsPropertySubType, xPropSet))
+ {
+ case SetVariableType::STRING: // text field
+ case SetVariableType::VAR: // num field
+ nToken = FIELD_ID_VARIABLE_GET;
+ break;
+ case SetVariableType::FORMULA:
+ nToken = FIELD_ID_EXPRESSION;
+ break;
+ case SetVariableType::SEQUENCE:
+ default:
+ nToken = FIELD_ID_UNKNOWN;
+ break;
+ }
+ break;
+
+ case FIELD_ID_TIME:
+ if (GetBoolProperty(gsPropertyIsDate, xPropSet))
+ {
+ nToken = FIELD_ID_DATE;
+ }
+ break;
+
+ case FIELD_ID_PAGENUMBER:
+ // NumberingType not available in non-Writer apps
+ if (xPropSet->getPropertySetInfo()->
+ hasPropertyByName(gsPropertyNumberingType))
+ {
+ if (NumberingType::CHAR_SPECIAL == GetIntProperty(
+ gsPropertyNumberingType, xPropSet))
+ {
+ nToken = FIELD_ID_PAGESTRING;
+ }
+ }
+ break;
+
+ case FIELD_ID_DOCINFO_CREATION_TIME:
+ if (GetBoolProperty(gsPropertyIsDate, xPropSet))
+ {
+ nToken = FIELD_ID_DOCINFO_CREATION_DATE;
+ }
+ break;
+
+ case FIELD_ID_DOCINFO_PRINT_TIME:
+ if (GetBoolProperty(gsPropertyIsDate, xPropSet))
+ {
+ nToken = FIELD_ID_DOCINFO_PRINT_DATE;
+ }
+ break;
+
+ case FIELD_ID_DOCINFO_SAVE_TIME:
+ if (GetBoolProperty(gsPropertyIsDate, xPropSet))
+ {
+ nToken = FIELD_ID_DOCINFO_SAVE_DATE;
+ }
+ break;
+
+ case FIELD_ID_REF_REFERENCE:
+ switch (GetInt16Property(gsPropertyReferenceFieldSource, xPropSet))
+ {
+ case ReferenceFieldSource::REFERENCE_MARK:
+ nToken = FIELD_ID_REF_REFERENCE;
+ break;
+ case ReferenceFieldSource::SEQUENCE_FIELD:
+ nToken = FIELD_ID_REF_SEQUENCE;
+ break;
+ case ReferenceFieldSource::BOOKMARK:
+ nToken = FIELD_ID_REF_BOOKMARK;
+ break;
+ case ReferenceFieldSource::FOOTNOTE:
+ nToken = FIELD_ID_REF_FOOTNOTE;
+ break;
+ case ReferenceFieldSource::ENDNOTE:
+ nToken = FIELD_ID_REF_ENDNOTE;
+ break;
+ case ReferenceFieldSource::STYLE:
+ nToken = FIELD_ID_REF_STYLE;
+ break;
+ default:
+ nToken = FIELD_ID_UNKNOWN;
+ break;
+ }
+ break;
+
+ case FIELD_ID_COMBINED_CHARACTERS:
+ case FIELD_ID_SCRIPT:
+ case FIELD_ID_ANNOTATION:
+ case FIELD_ID_BIBLIOGRAPHY:
+ case FIELD_ID_DDE:
+ case FIELD_ID_MACRO:
+ case FIELD_ID_REFPAGE_SET:
+ case FIELD_ID_REFPAGE_GET:
+ case FIELD_ID_COUNT_PAGES:
+ case FIELD_ID_COUNT_PARAGRAPHS:
+ case FIELD_ID_COUNT_WORDS:
+ case FIELD_ID_COUNT_CHARACTERS:
+ case FIELD_ID_COUNT_TABLES:
+ case FIELD_ID_COUNT_GRAPHICS:
+ case FIELD_ID_COUNT_OBJECTS:
+ case FIELD_ID_CONDITIONAL_TEXT:
+ case FIELD_ID_HIDDEN_TEXT:
+ case FIELD_ID_HIDDEN_PARAGRAPH:
+ case FIELD_ID_DOCINFO_CREATION_AUTHOR:
+ case FIELD_ID_DOCINFO_DESCRIPTION:
+ case FIELD_ID_DOCINFO_CUSTOM:
+ case FIELD_ID_DOCINFO_PRINT_AUTHOR:
+ case FIELD_ID_DOCINFO_TITLE:
+ case FIELD_ID_DOCINFO_SUBJECT:
+ case FIELD_ID_DOCINFO_KEYWORDS:
+ case FIELD_ID_DOCINFO_REVISION:
+ case FIELD_ID_DOCINFO_EDIT_DURATION:
+ case FIELD_ID_DOCINFO_SAVE_AUTHOR:
+ case FIELD_ID_TEXT_INPUT:
+ case FIELD_ID_USER_INPUT:
+ case FIELD_ID_AUTHOR:
+ case FIELD_ID_SENDER:
+ case FIELD_ID_PLACEHOLDER:
+ case FIELD_ID_USER_GET:
+ case FIELD_ID_DATABASE_NEXT:
+ case FIELD_ID_DATABASE_SELECT:
+ case FIELD_ID_DATABASE_DISPLAY:
+ case FIELD_ID_DATABASE_NAME:
+ case FIELD_ID_DATABASE_NUMBER:
+ case FIELD_ID_TEMPLATE_NAME:
+ case FIELD_ID_CHAPTER:
+ case FIELD_ID_FILE_NAME:
+ case FIELD_ID_META:
+ case FIELD_ID_SHEET_NAME:
+ case FIELD_ID_PAGENAME:
+ case FIELD_ID_MEASURE:
+ case FIELD_ID_URL:
+ case FIELD_ID_TABLE_FORMULA:
+ case FIELD_ID_DROP_DOWN:
+ ; // these field IDs are final
+ break;
+
+ default:
+ nToken = FIELD_ID_UNKNOWN;
+ }
+
+ // ... and return final FIELD_ID
+ return nToken;
+}
+
+// is string or numeric field?
+bool XMLTextFieldExport::IsStringField(
+ FieldIdEnum nFieldType,
+ const Reference<XPropertySet> & xPropSet)
+{
+ switch (nFieldType) {
+
+ case FIELD_ID_VARIABLE_GET:
+ case FIELD_ID_VARIABLE_SET:
+ case FIELD_ID_VARIABLE_INPUT:
+ {
+ // depends on field sub type
+ return ( GetIntProperty(gsPropertySubType, xPropSet) ==
+ SetVariableType::STRING );
+ }
+
+ case FIELD_ID_USER_GET:
+ case FIELD_ID_USER_INPUT:
+ {
+ Reference<XTextField> xTextField(xPropSet, UNO_QUERY);
+ DBG_ASSERT(xTextField.is(), "field is no XTextField!");
+ bool bRet = GetBoolProperty(gsPropertyIsExpression,
+ GetMasterPropertySet(xTextField));
+ return !bRet;
+ }
+
+ case FIELD_ID_META:
+ return 0 > GetIntProperty(gsPropertyNumberFormat, xPropSet);
+
+ case FIELD_ID_DATABASE_DISPLAY:
+ // TODO: depends on... ???
+ // workaround #no-bug#: no data type
+ return 5100 == GetIntProperty(gsPropertyNumberFormat, xPropSet);
+
+ case FIELD_ID_TABLE_FORMULA:
+ // legacy field: always a number field (because it always has
+ // a number format)
+ return false;
+
+ case FIELD_ID_COUNT_PAGES:
+ case FIELD_ID_COUNT_PARAGRAPHS:
+ case FIELD_ID_COUNT_WORDS:
+ case FIELD_ID_COUNT_CHARACTERS:
+ case FIELD_ID_COUNT_TABLES:
+ case FIELD_ID_COUNT_GRAPHICS:
+ case FIELD_ID_COUNT_OBJECTS:
+ case FIELD_ID_DOCINFO_SAVE_TIME:
+ case FIELD_ID_DOCINFO_SAVE_DATE:
+ case FIELD_ID_DOCINFO_CREATION_DATE:
+ case FIELD_ID_DOCINFO_CREATION_TIME:
+ case FIELD_ID_DOCINFO_PRINT_TIME:
+ case FIELD_ID_DOCINFO_PRINT_DATE:
+ case FIELD_ID_DOCINFO_EDIT_DURATION:
+ case FIELD_ID_DOCINFO_REVISION:
+ case FIELD_ID_DATABASE_NUMBER:
+ case FIELD_ID_EXPRESSION:
+ case FIELD_ID_SEQUENCE:
+ case FIELD_ID_DATE:
+ case FIELD_ID_TIME:
+ case FIELD_ID_PAGENUMBER:
+ case FIELD_ID_REFPAGE_SET:
+ case FIELD_ID_REFPAGE_GET:
+ case FIELD_ID_DOCINFO_CUSTOM:
+ // always number
+ return false;
+
+ case FIELD_ID_COMBINED_CHARACTERS:
+ case FIELD_ID_BIBLIOGRAPHY:
+ case FIELD_ID_DDE:
+ case FIELD_ID_REF_REFERENCE:
+ case FIELD_ID_REF_SEQUENCE:
+ case FIELD_ID_REF_BOOKMARK:
+ case FIELD_ID_REF_FOOTNOTE:
+ case FIELD_ID_REF_ENDNOTE:
+ case FIELD_ID_REF_STYLE:
+ case FIELD_ID_MACRO:
+ case FIELD_ID_TEMPLATE_NAME:
+ case FIELD_ID_CHAPTER:
+ case FIELD_ID_FILE_NAME:
+ case FIELD_ID_CONDITIONAL_TEXT:
+ case FIELD_ID_HIDDEN_TEXT:
+ case FIELD_ID_HIDDEN_PARAGRAPH:
+ case FIELD_ID_DOCINFO_CREATION_AUTHOR:
+ case FIELD_ID_DOCINFO_DESCRIPTION:
+ case FIELD_ID_DOCINFO_PRINT_AUTHOR:
+ case FIELD_ID_DOCINFO_TITLE:
+ case FIELD_ID_DOCINFO_SUBJECT:
+ case FIELD_ID_DOCINFO_KEYWORDS:
+ case FIELD_ID_DOCINFO_SAVE_AUTHOR:
+ case FIELD_ID_DATABASE_NAME:
+ case FIELD_ID_TEXT_INPUT:
+ case FIELD_ID_SENDER:
+ case FIELD_ID_AUTHOR:
+ case FIELD_ID_PAGENAME:
+ case FIELD_ID_PAGESTRING:
+ case FIELD_ID_SHEET_NAME:
+ case FIELD_ID_MEASURE:
+ case FIELD_ID_URL:
+ case FIELD_ID_DROP_DOWN:
+ // always string:
+ return true;
+
+ case FIELD_ID_SCRIPT:
+ case FIELD_ID_ANNOTATION:
+ case FIELD_ID_DATABASE_NEXT:
+ case FIELD_ID_DATABASE_SELECT:
+ case FIELD_ID_PLACEHOLDER:
+ case FIELD_ID_UNKNOWN:
+ case FIELD_ID_DRAW_HEADER:
+ case FIELD_ID_DRAW_FOOTER:
+ case FIELD_ID_DRAW_DATE_TIME:
+ default:
+ OSL_FAIL("unknown field type/field has no content");
+ return true; // invalid info; string in case of doubt
+ }
+}
+
+/// export the styles needed by the given field. Called on first pass
+/// through document
+void XMLTextFieldExport::ExportFieldAutoStyle(
+ const Reference<XTextField> & rTextField, const bool bProgress,
+ const bool bRecursive )
+{
+ // get property set
+ Reference<XPropertySet> xPropSet(rTextField, UNO_QUERY);
+
+ // add field master to list of used field masters (if desired)
+ if (nullptr != pUsedMasters)
+ {
+ Reference<XDependentTextField> xDepField(rTextField, UNO_QUERY);
+ if (xDepField.is())
+ {
+ // The direct parent may be just the table cell, while we want the topmost parent, e.g.
+ // a header text.
+ Reference<XText> xOurText = GetToplevelText(rTextField->getAnchor()->getText());
+
+ std::map<Reference<XText>, std::set<OUString> >::iterator aMapIter =
+ pUsedMasters->find(xOurText);
+
+ // insert a list for our XText (if necessary)
+ if (aMapIter == pUsedMasters->end())
+ {
+ std::set<OUString> aSet;
+ (*pUsedMasters)[xOurText] = aSet;
+ aMapIter = pUsedMasters->find(xOurText);
+ }
+
+ // insert this text field master
+ OUString sFieldMasterName = GetStringProperty(
+ gsPropertyInstanceName, xDepField->getTextFieldMaster());
+ if (!sFieldMasterName.isEmpty())
+ aMapIter->second.insert( sFieldMasterName );
+ }
+ // else: no dependent field -> no master -> ignore
+ }
+
+ // get Field ID
+ FieldIdEnum nToken = GetFieldID(rTextField, xPropSet);
+
+ // export the character style for all fields
+ // with one exception: combined character fields export their own
+ // text style below
+ Reference <XPropertySet> xRangePropSet(rTextField->getAnchor(), UNO_QUERY);
+ if (FIELD_ID_COMBINED_CHARACTERS != nToken)
+ {
+ GetExport().GetTextParagraphExport()->Add(
+ XmlStyleFamily::TEXT_TEXT, xRangePropSet);
+ }
+
+ // process special styles for each field (e.g. data styles)
+ switch (nToken) {
+
+ case FIELD_ID_DATABASE_DISPLAY:
+ {
+ sal_Int32 nFormat = GetIntProperty(gsPropertyNumberFormat, xPropSet);
+ // workaround: #no-bug#; see IsStringField(...)
+ if ( (5100 != nFormat) &&
+ !GetBoolProperty(gsPropertyIsDataBaseFormat, xPropSet) )
+ {
+ GetExport().addDataStyle(nFormat);
+ }
+ break;
+ }
+
+ case FIELD_ID_DATE:
+ case FIELD_ID_TIME:
+ {
+ // date and time fields are always number fields, but the
+ // NumberFormat property is optional (e.g. Calc doesn't
+ // support it)
+ Reference<XPropertySetInfo> xPropSetInfo(
+ xPropSet->getPropertySetInfo() );
+ if ( xPropSetInfo->hasPropertyByName( gsPropertyNumberFormat ) )
+ {
+ sal_Int32 nFormat =
+ GetIntProperty(gsPropertyNumberFormat, xPropSet);
+
+ // nFormat may be -1 for numeric fields that display their
+ // variable name. (Maybe this should be a field type, then?)
+ if (nFormat != -1)
+ {
+ if( ! GetOptionalBoolProperty(
+ gsPropertyIsFixedLanguage,
+ xPropSet, xPropSetInfo, false ) )
+ {
+ nFormat =
+ GetExport().dataStyleForceSystemLanguage(nFormat);
+ }
+
+ GetExport().addDataStyle( nFormat,
+ nToken == FIELD_ID_TIME );
+ }
+ }
+ }
+ break;
+
+ case FIELD_ID_META:
+ // recurse into content (does not export element, so can be done first)
+ if (bRecursive)
+ {
+ bool dummy_for_autostyles(true);
+ ExportMetaField(xPropSet, true, bProgress, dummy_for_autostyles);
+ }
+ [[fallthrough]];
+ case FIELD_ID_DOCINFO_PRINT_TIME:
+ case FIELD_ID_DOCINFO_PRINT_DATE:
+ case FIELD_ID_DOCINFO_CREATION_DATE:
+ case FIELD_ID_DOCINFO_CREATION_TIME:
+ case FIELD_ID_DOCINFO_SAVE_TIME:
+ case FIELD_ID_DOCINFO_SAVE_DATE:
+ case FIELD_ID_DOCINFO_EDIT_DURATION:
+ case FIELD_ID_VARIABLE_SET:
+ case FIELD_ID_VARIABLE_GET:
+ case FIELD_ID_VARIABLE_INPUT:
+ case FIELD_ID_USER_GET:
+ case FIELD_ID_EXPRESSION:
+ case FIELD_ID_TABLE_FORMULA:
+ case FIELD_ID_DOCINFO_CUSTOM:
+ // register number format, if this is a numeric field
+ if (! IsStringField(nToken, xPropSet)) {
+
+ sal_Int32 nFormat =
+ GetIntProperty(gsPropertyNumberFormat, xPropSet);
+
+ // nFormat may be -1 for numeric fields that display their
+ // variable name. (Maybe this should be a field type, then?)
+ if (nFormat != -1)
+ {
+ // handle formats for fixed language fields
+ // for all these fields (except table formula)
+ if( ( nToken != FIELD_ID_TABLE_FORMULA ) &&
+ ! GetOptionalBoolProperty(
+ gsPropertyIsFixedLanguage,
+ xPropSet, xPropSet->getPropertySetInfo(),
+ false ) )
+ {
+ nFormat =
+ GetExport().dataStyleForceSystemLanguage(nFormat);
+ }
+
+ GetExport().addDataStyle(nFormat);
+ }
+ }
+ break;
+
+ case FIELD_ID_COMBINED_CHARACTERS:
+ {
+ // export text style with the addition of the combined characters
+ DBG_ASSERT(nullptr != pCombinedCharactersPropertyState,
+ "need proper PropertyState for combined characters");
+ std::span<XMLPropertyState> aStates( pCombinedCharactersPropertyState.get(), 1 );
+ GetExport().GetTextParagraphExport()->Add(
+ XmlStyleFamily::TEXT_TEXT, xRangePropSet,
+ aStates);
+ break;
+ }
+
+ case FIELD_ID_SCRIPT:
+ case FIELD_ID_ANNOTATION:
+ case FIELD_ID_BIBLIOGRAPHY:
+ case FIELD_ID_DDE:
+ case FIELD_ID_REF_REFERENCE:
+ case FIELD_ID_REF_SEQUENCE:
+ case FIELD_ID_REF_BOOKMARK:
+ case FIELD_ID_REF_FOOTNOTE:
+ case FIELD_ID_REF_ENDNOTE:
+ case FIELD_ID_REF_STYLE:
+ case FIELD_ID_MACRO:
+ case FIELD_ID_REFPAGE_SET:
+ case FIELD_ID_REFPAGE_GET:
+ case FIELD_ID_COUNT_PAGES:
+ case FIELD_ID_COUNT_PARAGRAPHS:
+ case FIELD_ID_COUNT_WORDS:
+ case FIELD_ID_COUNT_CHARACTERS:
+ case FIELD_ID_COUNT_TABLES:
+ case FIELD_ID_COUNT_GRAPHICS:
+ case FIELD_ID_COUNT_OBJECTS:
+ case FIELD_ID_CONDITIONAL_TEXT:
+ case FIELD_ID_HIDDEN_TEXT:
+ case FIELD_ID_HIDDEN_PARAGRAPH:
+ case FIELD_ID_DOCINFO_CREATION_AUTHOR:
+ case FIELD_ID_DOCINFO_DESCRIPTION:
+ case FIELD_ID_DOCINFO_PRINT_AUTHOR:
+ case FIELD_ID_DOCINFO_TITLE:
+ case FIELD_ID_DOCINFO_SUBJECT:
+ case FIELD_ID_DOCINFO_KEYWORDS:
+ case FIELD_ID_DOCINFO_REVISION:
+ case FIELD_ID_DOCINFO_SAVE_AUTHOR:
+ case FIELD_ID_SEQUENCE:
+ case FIELD_ID_PAGENAME:
+ case FIELD_ID_PAGENUMBER:
+ case FIELD_ID_PAGESTRING:
+ case FIELD_ID_AUTHOR:
+ case FIELD_ID_SENDER:
+ case FIELD_ID_PLACEHOLDER:
+ case FIELD_ID_USER_INPUT:
+ case FIELD_ID_TEXT_INPUT:
+ case FIELD_ID_DATABASE_NEXT:
+ case FIELD_ID_DATABASE_SELECT:
+ case FIELD_ID_DATABASE_NAME:
+ case FIELD_ID_DATABASE_NUMBER:
+ case FIELD_ID_TEMPLATE_NAME:
+ case FIELD_ID_CHAPTER:
+ case FIELD_ID_FILE_NAME:
+ case FIELD_ID_SHEET_NAME:
+ case FIELD_ID_MEASURE:
+ case FIELD_ID_URL:
+ case FIELD_ID_DROP_DOWN:
+ case FIELD_ID_DRAW_DATE_TIME:
+ case FIELD_ID_DRAW_FOOTER:
+ case FIELD_ID_DRAW_HEADER:
+ ; // no formats for these fields!
+ break;
+
+ case FIELD_ID_UNKNOWN:
+ default:
+ OSL_FAIL("unknown field type!");
+ // ignore -> no format for unknown
+ break;
+ }
+}
+
+/// export the given field to XML. Called on second pass through document
+void XMLTextFieldExport::ExportField(
+ const Reference<XTextField> & rTextField, bool bProgress,
+ bool & rPrevCharIsSpace)
+{
+ // get property set
+ Reference<XPropertySet> xPropSet(rTextField, UNO_QUERY);
+
+ // get property set of range (for the attributes)
+ Reference <XPropertySet> xRangePropSet(rTextField->getAnchor(), UNO_QUERY);
+
+ // get Field ID
+ enum FieldIdEnum nToken = GetFieldID(rTextField, xPropSet);
+
+ // special treatment for combined characters field, because it is
+ // exported as a style
+ const XMLPropertyState* aStates[] = { pCombinedCharactersPropertyState.get(), nullptr };
+ const XMLPropertyState **pStates =
+ FIELD_ID_COMBINED_CHARACTERS == nToken
+ ? aStates
+ : nullptr;
+
+ // find out whether we need to set the style
+ bool bIsUICharStyle;
+ bool bHasAutoStyle;
+ OUString sStyle = GetExport().GetTextParagraphExport()->
+ FindTextStyle( xRangePropSet, bIsUICharStyle, bHasAutoStyle, pStates );
+ bool bHasStyle = !sStyle.isEmpty();
+
+ {
+ Reference<XPropertySetInfo> xRangePropSetInfo;
+ XMLTextCharStyleNamesElementExport aCharStylesExport(
+ GetExport(), bIsUICharStyle &&
+ GetExport().GetTextParagraphExport()
+ ->GetCharStyleNamesPropInfoCache().hasProperty(
+ xRangePropSet, xRangePropSetInfo ), bHasAutoStyle,
+ xRangePropSet, gsPropertyCharStyleNames );
+
+ // export span with style (if necessary)
+ // (except for combined characters field)
+ if( bHasStyle )
+ {
+ // export <text:span> element
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
+ GetExport().EncodeStyleName( sStyle ) );
+ }
+ SvXMLElementExport aSpan( GetExport(), bHasStyle,
+ XML_NAMESPACE_TEXT, XML_SPAN,
+ false, false);
+
+ // finally, export the field itself
+ ExportFieldHelper( rTextField, xPropSet, xRangePropSet, nToken,
+ bProgress, rPrevCharIsSpace);
+ }
+}
+
+/// export the given field to XML. Called on second pass through document
+void XMLTextFieldExport::ExportFieldHelper(
+ const Reference<XTextField> & rTextField,
+ const Reference<XPropertySet> & rPropSet,
+ const Reference<XPropertySet> &,
+ enum FieldIdEnum nToken,
+ bool bProgress,
+ bool & rPrevCharIsSpace)
+{
+ // get property set info (because some attributes are not support
+ // in all implementations)
+ Reference<XPropertySetInfo> xPropSetInfo(rPropSet->getPropertySetInfo());
+
+ OUString sPresentation = rTextField->getPresentation(false);
+
+ // process each field type
+ switch (nToken) {
+ case FIELD_ID_AUTHOR:
+ // author field: fixed, field (sub-)type
+ if (xPropSetInfo->hasPropertyByName(gsPropertyIsFixed))
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_FIXED,
+ (GetBoolProperty(gsPropertyIsFixed, rPropSet) ? XML_TRUE : XML_FALSE) );
+ }
+ ExportElement(MapAuthorFieldName(rPropSet), sPresentation);
+ break;
+
+ case FIELD_ID_SENDER:
+ // sender field: fixed, field (sub-)type
+ ProcessBoolean(XML_FIXED,
+ GetBoolProperty(gsPropertyIsFixed, rPropSet), true);
+ ExportElement(MapSenderFieldName(rPropSet), sPresentation);
+ break;
+
+ case FIELD_ID_PLACEHOLDER:
+ // placeholder field: type, name, description
+ ProcessString(XML_PLACEHOLDER_TYPE,
+ MapPlaceholderType(
+ GetInt16Property(gsPropertyPlaceholderType, rPropSet)));
+ ProcessString(XML_DESCRIPTION,
+ GetStringProperty(gsPropertyHint,rPropSet), true);
+ ExportElement(XML_PLACEHOLDER, sPresentation);
+ break;
+
+ case FIELD_ID_VARIABLE_SET:
+ {
+ // variable set field: name, visible, format&value
+ ProcessString(XML_NAME,
+ GetStringProperty(gsPropertyVariableName, rPropSet));
+ ProcessDisplay(GetBoolProperty(gsPropertyIsVisible, rPropSet),
+ false);
+ ProcessString(XML_FORMULA, XML_NAMESPACE_OOOW,
+ GetStringProperty(gsPropertyContent, rPropSet),
+ sPresentation);
+ ProcessValueAndType(IsStringField(nToken, rPropSet),
+ GetIntProperty(gsPropertyNumberFormat, rPropSet),
+ GetStringProperty(gsPropertyContent, rPropSet),
+ sPresentation,
+ GetDoubleProperty(gsPropertyValue, rPropSet),
+ true, true, true,
+ ! GetOptionalBoolProperty(
+ gsPropertyIsFixedLanguage,
+ rPropSet, xPropSetInfo, false ) );
+ ExportElement(XML_VARIABLE_SET, sPresentation);
+ break;
+ }
+ case FIELD_ID_VARIABLE_GET:
+ {
+ // variable get field: name, format&value
+ ProcessString(XML_NAME,
+ GetStringProperty(gsPropertyContent, rPropSet));
+ bool bCmd = GetBoolProperty(gsPropertyIsShowFormula, rPropSet);
+ ProcessDisplay(true, bCmd);
+ // show style, unless name will be shown
+ ProcessValueAndType(IsStringField(nToken, rPropSet),
+ GetIntProperty(gsPropertyNumberFormat, rPropSet),
+ "", u"", 0.0, // values not used
+ false,
+ false,
+ !bCmd,
+ ! GetOptionalBoolProperty(
+ gsPropertyIsFixedLanguage,
+ rPropSet, xPropSetInfo, false ) );
+ ExportElement(XML_VARIABLE_GET, sPresentation);
+ break;
+ }
+ case FIELD_ID_VARIABLE_INPUT:
+ // variable input field: name, description, format&value
+ ProcessString(XML_NAME,
+ GetStringProperty(gsPropertyVariableName, rPropSet));
+ ProcessString(XML_DESCRIPTION,
+ GetStringProperty(gsPropertyHint , rPropSet));
+ ProcessDisplay(GetBoolProperty(gsPropertyIsVisible, rPropSet),
+ false);
+ ProcessString(XML_FORMULA, XML_NAMESPACE_OOOW,
+ GetStringProperty(gsPropertyContent, rPropSet),
+ sPresentation);
+ ProcessValueAndType(IsStringField(nToken, rPropSet),
+ GetIntProperty(gsPropertyNumberFormat, rPropSet),
+ GetStringProperty(gsPropertyContent, rPropSet),
+ sPresentation,
+ GetDoubleProperty(gsPropertyValue, rPropSet),
+ true, true, true,
+ ! GetOptionalBoolProperty(
+ gsPropertyIsFixedLanguage,
+ rPropSet, xPropSetInfo, false ) );
+ ExportElement(XML_VARIABLE_INPUT, sPresentation);
+ break;
+
+ case FIELD_ID_USER_GET:
+ // user field: name, hidden, style
+ {
+ bool bCmd = GetBoolProperty(gsPropertyIsShowFormula, rPropSet);
+ ProcessDisplay(GetBoolProperty(gsPropertyIsVisible, rPropSet),
+ bCmd);
+ ProcessValueAndType(IsStringField(nToken, rPropSet),
+ GetIntProperty(gsPropertyNumberFormat, rPropSet),
+ "", u"", 0.0, // values not used
+ false, false, !bCmd,
+ ! GetOptionalBoolProperty(
+ gsPropertyIsFixedLanguage,
+ rPropSet, xPropSetInfo, false ) );
+
+ // name from FieldMaster
+ ProcessString(XML_NAME,
+ GetStringProperty(gsPropertyName,
+ GetMasterPropertySet(rTextField)));
+ ExportElement(XML_USER_FIELD_GET, sPresentation);
+ break;
+ }
+
+ case FIELD_ID_USER_INPUT:
+ // user input field: name (from FieldMaster), description
+// ProcessString(XML_NAME,
+// GetStringProperty(sPropertyName,
+// GetMasterPropertySet(rTextField)));
+ ProcessString(XML_NAME,
+ GetStringProperty(gsPropertyContent, rPropSet));
+ ProcessString(XML_DESCRIPTION,
+ GetStringProperty(gsPropertyHint, rPropSet));
+ ExportElement(XML_USER_FIELD_INPUT, sPresentation);
+ break;
+
+ case FIELD_ID_SEQUENCE:
+ {
+ // sequence field: name, formula, seq-format
+ OUString sName = GetStringProperty(gsPropertyVariableName, rPropSet);
+ // TODO: use reference name only if actually being referenced.
+ ProcessString(XML_REF_NAME,
+ MakeSequenceRefName(
+ GetInt16Property(gsPropertySequenceValue, rPropSet),
+ sName));
+ ProcessString(XML_NAME, sName);
+ ProcessString(XML_FORMULA, XML_NAMESPACE_OOOW,
+ GetStringProperty(gsPropertyContent, rPropSet),
+ sPresentation);
+ ProcessNumberingType(GetInt16Property(gsPropertyNumberingType,
+ rPropSet));
+ ExportElement(XML_SEQUENCE, sPresentation);
+ break;
+ }
+
+ case FIELD_ID_EXPRESSION:
+ {
+ // formula field: formula, format&value
+ bool bCmd = GetBoolProperty(gsPropertyIsShowFormula, rPropSet);
+ ProcessString(XML_FORMULA, XML_NAMESPACE_OOOW,
+ GetStringProperty(gsPropertyContent, rPropSet),
+ sPresentation);
+ ProcessDisplay(true, bCmd);
+ ProcessValueAndType(IsStringField(nToken, rPropSet),
+ GetIntProperty(gsPropertyNumberFormat, rPropSet),
+ GetStringProperty(gsPropertyContent, rPropSet),
+ sPresentation,
+ GetDoubleProperty(gsPropertyValue, rPropSet),
+ !bCmd, !bCmd, !bCmd,
+ ! GetOptionalBoolProperty(
+ gsPropertyIsFixedLanguage,
+ rPropSet, xPropSetInfo, false ) );
+ ExportElement(XML_EXPRESSION, sPresentation);
+ break;
+ }
+
+ case FIELD_ID_TEXT_INPUT:
+ // text input field: description and string-value
+ ProcessString(XML_DESCRIPTION,
+ GetStringProperty(gsPropertyHint, rPropSet));
+ ProcessString(XML_HELP,
+ GetStringProperty(gsPropertyHelp, rPropSet), true);
+ ProcessString(XML_HINT,
+ GetStringProperty(gsPropertyTooltip, rPropSet), true);
+ ExportElement(XML_TEXT_INPUT, sPresentation);
+ break;
+
+ case FIELD_ID_TIME:
+ // all properties (except IsDate) are optional!
+ if (xPropSetInfo->hasPropertyByName(gsPropertyNumberFormat))
+ {
+ ProcessValueAndType(false,
+ GetIntProperty(gsPropertyNumberFormat,rPropSet),
+ "", u"", 0.0, // not used
+ false, false, true,
+ ! GetOptionalBoolProperty(
+ gsPropertyIsFixedLanguage,
+ rPropSet, xPropSetInfo, false ),
+ true);
+ }
+ if (xPropSetInfo->hasPropertyByName(gsPropertyDateTimeValue))
+ {
+ // no value -> current time
+ ProcessTimeOrDateTime(XML_TIME_VALUE,
+ GetDateTimeProperty(gsPropertyDateTimeValue,
+ rPropSet));
+ }
+ if (xPropSetInfo->hasPropertyByName(gsPropertyDateTime))
+ {
+ // no value -> current time
+ ProcessTimeOrDateTime(XML_TIME_VALUE,
+ GetDateTimeProperty(gsPropertyDateTime,rPropSet));
+ }
+ if (xPropSetInfo->hasPropertyByName(gsPropertyIsFixed))
+ {
+ ProcessBoolean(XML_FIXED,
+ GetBoolProperty(gsPropertyIsFixed, rPropSet),
+ false);
+ }
+ if (xPropSetInfo->hasPropertyByName(gsPropertyAdjust))
+ {
+ // adjust value given as integer in minutes
+ ProcessDateTime(XML_TIME_ADJUST,
+ GetIntProperty(gsPropertyAdjust, rPropSet),
+ false, true);
+ }
+ ExportElement(XML_TIME, sPresentation);
+ break;
+
+ case FIELD_ID_DATE:
+ // all properties (except IsDate) are optional!
+ if (xPropSetInfo->hasPropertyByName(gsPropertyNumberFormat))
+ {
+ ProcessValueAndType(false,
+ GetIntProperty(gsPropertyNumberFormat,rPropSet),
+ "", u"", 0.0, // not used
+ false, false, true,
+ ! GetOptionalBoolProperty(
+ gsPropertyIsFixedLanguage,
+ rPropSet, xPropSetInfo, false ) );
+ }
+ if (xPropSetInfo->hasPropertyByName(gsPropertyDateTimeValue))
+ {
+ // no value -> current date
+ ProcessDateTime(XML_DATE_VALUE,
+ GetDateTimeProperty(gsPropertyDateTimeValue,
+ rPropSet));
+ }
+ // TODO: remove double-handling after SRC614
+ else if (xPropSetInfo->hasPropertyByName(gsPropertyDateTime))
+ {
+ ProcessDateTime(XML_DATE_VALUE,
+ GetDateTimeProperty(gsPropertyDateTime,rPropSet));
+ }
+ if (xPropSetInfo->hasPropertyByName(gsPropertyIsFixed))
+ {
+ ProcessBoolean(XML_FIXED,
+ GetBoolProperty(gsPropertyIsFixed, rPropSet),
+ false);
+ }
+ if (xPropSetInfo->hasPropertyByName(gsPropertyAdjust))
+ {
+ // adjust value given as number of days
+ ProcessDateTime(XML_DATE_ADJUST,
+ GetIntProperty(gsPropertyAdjust, rPropSet),
+ true, true);
+ }
+ ExportElement(XML_DATE, sPresentation);
+ break;
+
+ case FIELD_ID_PAGENUMBER:
+ // all properties are optional
+ if (xPropSetInfo->hasPropertyByName(gsPropertyNumberingType))
+ {
+ ProcessNumberingType(GetInt16Property(gsPropertyNumberingType,
+ rPropSet));
+ }
+ if (xPropSetInfo->hasPropertyByName(gsPropertyOffset))
+ {
+ sal_Int32 nAdjust = GetIntProperty(gsPropertyOffset, rPropSet);
+
+ if (xPropSetInfo->hasPropertyByName(gsPropertySubType))
+ {
+ // property SubType used in MapPageNumberName
+ ProcessString(XML_SELECT_PAGE,
+ MapPageNumberName(rPropSet, nAdjust));
+ }
+ ProcessIntegerDef(XML_PAGE_ADJUST, nAdjust, 0);
+ }
+ ExportElement(XML_PAGE_NUMBER, sPresentation);
+ break;
+
+ case FIELD_ID_PAGESTRING:
+ {
+ ProcessString(XML_STRING_VALUE,
+ GetStringProperty(gsPropertyUserText, rPropSet),
+ sPresentation);
+ sal_Int32 nDummy = 0; // MapPageNumberName need int
+ ProcessString(XML_SELECT_PAGE, MapPageNumberName(rPropSet, nDummy));
+ ExportElement(XML_PAGE_CONTINUATION, sPresentation);
+ break;
+ }
+
+ case FIELD_ID_DATABASE_NAME:
+ ProcessString(XML_TABLE_NAME,
+ GetStringProperty(gsPropertyDataTableName, rPropSet));
+ ProcessCommandType(GetIntProperty(gsPropertyDataCommandType, rPropSet));
+ ProcessDisplay(GetBoolProperty(gsPropertyIsVisible, rPropSet),
+ false);
+ ExportDataBaseElement(XML_DATABASE_NAME, sPresentation,
+ rPropSet, xPropSetInfo);
+ break;
+
+ case FIELD_ID_DATABASE_NUMBER:
+ ProcessString(XML_TABLE_NAME,
+ GetStringProperty(gsPropertyDataTableName, rPropSet));
+ ProcessCommandType(GetIntProperty(gsPropertyDataCommandType, rPropSet));
+ ProcessNumberingType(
+ GetInt16Property(gsPropertyNumberingType,rPropSet));
+ ProcessInteger(XML_VALUE,
+ GetIntProperty(gsPropertySetNumber, rPropSet));
+ ProcessDisplay(GetBoolProperty(gsPropertyIsVisible, rPropSet),
+ false);
+ ExportDataBaseElement(XML_DATABASE_ROW_NUMBER, sPresentation,
+ rPropSet, xPropSetInfo);
+ break;
+
+ case FIELD_ID_DATABASE_NEXT:
+ ProcessString(XML_TABLE_NAME,
+ GetStringProperty(gsPropertyDataTableName, rPropSet));
+ ProcessCommandType(GetIntProperty(gsPropertyDataCommandType, rPropSet));
+ ProcessString(XML_CONDITION, XML_NAMESPACE_OOOW,
+ GetStringProperty(gsPropertyCondition, rPropSet));
+ DBG_ASSERT(sPresentation.isEmpty(),
+ "Unexpected presentation for database next field");
+ ExportDataBaseElement(XML_DATABASE_NEXT, OUString(),
+ rPropSet, xPropSetInfo);
+ break;
+
+ case FIELD_ID_DATABASE_SELECT:
+ ProcessString(XML_TABLE_NAME,
+ GetStringProperty(gsPropertyDataTableName, rPropSet));
+ ProcessCommandType(GetIntProperty(gsPropertyDataCommandType, rPropSet));
+ ProcessString(XML_CONDITION, XML_NAMESPACE_OOOW,
+ GetStringProperty(gsPropertyCondition, rPropSet));
+ ProcessInteger(XML_ROW_NUMBER,
+ GetIntProperty(gsPropertySetNumber, rPropSet));
+ DBG_ASSERT(sPresentation.isEmpty(),
+ "Unexpected presentation for database select field");
+ ExportDataBaseElement(XML_DATABASE_ROW_SELECT, OUString(),
+ rPropSet, xPropSetInfo);
+ break;
+
+ case FIELD_ID_DATABASE_DISPLAY:
+ {
+ // get database, table and column name from field master
+ const Reference<XPropertySet> & xMaster = GetMasterPropertySet(rTextField);
+ ProcessString(XML_TABLE_NAME,
+ GetStringProperty(gsPropertyDataTableName, xMaster));
+ ProcessCommandType(GetIntProperty(gsPropertyDataCommandType, xMaster));
+ ProcessString(XML_COLUMN_NAME,
+ GetStringProperty(gsPropertyDataColumnName, xMaster));
+ // export number format if available (happens only for numbers!)
+ if (!GetBoolProperty(gsPropertyIsDataBaseFormat, rPropSet))
+ {
+ ProcessValueAndType(false, // doesn't happen for text
+ GetIntProperty(gsPropertyNumberFormat,rPropSet),
+ "", u"", 0.0, // not used
+ false, false, true, false);
+ }
+ ProcessDisplay(GetBoolProperty(gsPropertyIsVisible, rPropSet),
+ false);
+ ExportDataBaseElement(XML_DATABASE_DISPLAY, sPresentation,
+ xMaster, xMaster->getPropertySetInfo());
+ break;
+ }
+
+ case FIELD_ID_DOCINFO_REVISION:
+ ProcessBoolean(XML_FIXED,
+ GetBoolProperty(gsPropertyIsFixed, rPropSet), false);
+ ExportElement(MapDocInfoFieldName(nToken), sPresentation);
+ break;
+
+ case FIELD_ID_DOCINFO_EDIT_DURATION:
+ case FIELD_ID_DOCINFO_SAVE_TIME:
+ case FIELD_ID_DOCINFO_CREATION_TIME:
+ case FIELD_ID_DOCINFO_PRINT_TIME:
+ case FIELD_ID_DOCINFO_SAVE_DATE:
+ case FIELD_ID_DOCINFO_CREATION_DATE:
+ case FIELD_ID_DOCINFO_PRINT_DATE:
+ ProcessValueAndType(false,
+ GetIntProperty(gsPropertyNumberFormat, rPropSet),
+ "", u"", 0.0,
+ false, false, true,
+ ! GetOptionalBoolProperty(
+ gsPropertyIsFixedLanguage,
+ rPropSet, xPropSetInfo, false ) );
+
+ // todo: export date/time value, but values not available -> core bug
+ ProcessBoolean(XML_FIXED,
+ GetBoolProperty(gsPropertyIsFixed, rPropSet), false);
+ ExportElement(MapDocInfoFieldName(nToken), sPresentation);
+ break;
+
+ case FIELD_ID_DOCINFO_CREATION_AUTHOR:
+ case FIELD_ID_DOCINFO_DESCRIPTION:
+ case FIELD_ID_DOCINFO_PRINT_AUTHOR:
+ case FIELD_ID_DOCINFO_TITLE:
+ case FIELD_ID_DOCINFO_SUBJECT:
+ case FIELD_ID_DOCINFO_KEYWORDS:
+ case FIELD_ID_DOCINFO_SAVE_AUTHOR:
+ if (xPropSetInfo->hasPropertyByName(gsPropertyIsFixed))
+ {
+ ProcessBoolean(XML_FIXED,
+ GetBoolProperty(gsPropertyIsFixed, rPropSet), false);
+ }
+ ExportElement(MapDocInfoFieldName(nToken), sPresentation);
+ break;
+
+ case FIELD_ID_DOCINFO_CUSTOM:
+ {
+ ProcessValueAndType(false, // doesn't happen for text
+ GetIntProperty(gsPropertyNumberFormat,rPropSet),
+ "", u"", 0.0, // not used
+ false, false, true,
+ ! GetOptionalBoolProperty(
+ gsPropertyIsFixedLanguage,
+ rPropSet, xPropSetInfo, false ));
+ uno::Any aAny = rPropSet->getPropertyValue( gsPropertyName );
+ OUString sName;
+ aAny >>= sName;
+ ProcessString(XML_NAME, sName);
+ ProcessBoolean(XML_FIXED, GetBoolProperty(gsPropertyIsFixed, rPropSet), false);
+ ExportElement(XML_USER_DEFINED, sPresentation);
+ break;
+ }
+
+ case FIELD_ID_COUNT_PAGES:
+ case FIELD_ID_COUNT_PARAGRAPHS:
+ case FIELD_ID_COUNT_WORDS:
+ case FIELD_ID_COUNT_CHARACTERS:
+ case FIELD_ID_COUNT_TABLES:
+ case FIELD_ID_COUNT_GRAPHICS:
+ case FIELD_ID_COUNT_OBJECTS:
+ // all properties optional (applies to pages only, but I'll do
+ // it for all for sake of common implementation)
+ if (xPropSetInfo->hasPropertyByName(gsPropertyNumberingType))
+ {
+ ProcessNumberingType(GetInt16Property(gsPropertyNumberingType,
+ rPropSet));
+ }
+ ExportElement(MapCountFieldName(nToken), sPresentation);
+ break;
+
+ case FIELD_ID_CONDITIONAL_TEXT:
+ ProcessString(XML_CONDITION, XML_NAMESPACE_OOOW,
+ GetStringProperty(gsPropertyCondition, rPropSet));
+ ProcessString(XML_STRING_VALUE_IF_TRUE,
+ GetStringProperty(gsPropertyTrueContent, rPropSet));
+ ProcessString(XML_STRING_VALUE_IF_FALSE,
+ GetStringProperty(gsPropertyFalseContent, rPropSet));
+ ProcessBoolean(XML_CURRENT_VALUE,
+ GetBoolProperty(gsPropertyIsConditionTrue, rPropSet),
+ false);
+ ExportElement(XML_CONDITIONAL_TEXT, sPresentation);
+ break;
+
+ case FIELD_ID_HIDDEN_TEXT:
+ ProcessString(XML_CONDITION, XML_NAMESPACE_OOOW,
+ GetStringProperty(gsPropertyCondition, rPropSet));
+ ProcessString(XML_STRING_VALUE,
+ GetStringProperty(gsPropertyContent, rPropSet));
+ ProcessBoolean(XML_IS_HIDDEN,
+ GetBoolProperty(gsPropertyIsHidden, rPropSet),
+ false);
+ ExportElement(XML_HIDDEN_TEXT, sPresentation);
+ break;
+
+ case FIELD_ID_HIDDEN_PARAGRAPH:
+ ProcessString(XML_CONDITION, XML_NAMESPACE_OOOW,
+ GetStringProperty(gsPropertyCondition, rPropSet));
+ ProcessBoolean(XML_IS_HIDDEN,
+ GetBoolProperty(gsPropertyIsHidden, rPropSet),
+ false);
+ DBG_ASSERT(sPresentation.isEmpty(),
+ "Unexpected presentation for hidden paragraph field");
+ ExportElement(XML_HIDDEN_PARAGRAPH);
+ break;
+
+ case FIELD_ID_TEMPLATE_NAME:
+ ProcessString(XML_DISPLAY,
+ MapTemplateDisplayFormat(
+ GetInt16Property(gsPropertyFileFormat, rPropSet)));
+ ExportElement(XML_TEMPLATE_NAME, sPresentation);
+ break;
+
+ case FIELD_ID_CHAPTER:
+ ProcessString(XML_DISPLAY,
+ MapChapterDisplayFormat(
+ GetInt16Property(gsPropertyChapterFormat, rPropSet)));
+ // API numbers 0..9, we number 1..10
+ ProcessInteger(XML_OUTLINE_LEVEL,
+ GetInt8Property(gsPropertyLevel, rPropSet) + 1);
+ ExportElement(XML_CHAPTER, sPresentation);
+ break;
+
+ case FIELD_ID_FILE_NAME:
+ // all properties are optional
+ if (xPropSetInfo->hasPropertyByName(gsPropertyFileFormat))
+ {
+ ProcessString(XML_DISPLAY,
+ MapFilenameDisplayFormat(
+ GetInt16Property(gsPropertyFileFormat, rPropSet)));
+ }
+ if (xPropSetInfo->hasPropertyByName(gsPropertyIsFixed))
+ {
+ ProcessBoolean(XML_FIXED,
+ GetBoolProperty(gsPropertyIsFixed, rPropSet),
+ false);
+ }
+ ExportElement(XML_FILE_NAME, sPresentation);
+ break;
+
+ case FIELD_ID_REFPAGE_SET:
+ ProcessBoolean(XML_ACTIVE,
+ GetBoolProperty(gsPropertyOn, rPropSet), true);
+ ProcessIntegerDef(XML_PAGE_ADJUST,
+ GetInt16Property(gsPropertyOffset, rPropSet), 0);
+ DBG_ASSERT(sPresentation.isEmpty(),
+ "Unexpected presentation page variable field");
+ ExportElement(XML_PAGE_VARIABLE_SET);
+ break;
+
+ case FIELD_ID_REFPAGE_GET:
+ ProcessNumberingType(
+ GetInt16Property(gsPropertyNumberingType, rPropSet));
+ ExportElement(XML_PAGE_VARIABLE_GET, sPresentation);
+ break;
+
+ case FIELD_ID_MACRO:
+ ExportMacro( rPropSet, sPresentation );
+ break;
+
+ case FIELD_ID_REF_SEQUENCE:
+ // reference to sequence: format, name, find value (and element)
+ // was: if (nSeqNumber != -1) ...
+ ProcessString(XML_REFERENCE_FORMAT,
+ MapReferenceType(GetInt16Property(
+ gsPropertyReferenceFieldPart, rPropSet)),
+ XML_TEMPLATE);
+ ProcessString(XML_REF_NAME,
+ MakeSequenceRefName(
+ GetInt16Property(gsPropertySequenceNumber, rPropSet),
+ GetStringProperty(gsPropertySourceName, rPropSet) ) );
+ if (xPropSetInfo->hasPropertyByName(gsPropertyReferenceFieldLanguage) &&
+ GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
+ {
+ // export text:reference-language attribute, if not empty
+ ProcessString(XML_REFERENCE_LANGUAGE,
+ GetStringProperty(gsPropertyReferenceFieldLanguage, rPropSet), true, XML_NAMESPACE_LO_EXT);
+ }
+ ExportElement(
+ MapReferenceSource(
+ GetInt16Property(gsPropertyReferenceFieldSource, rPropSet)),
+ sPresentation);
+ break;
+
+ case FIELD_ID_REF_REFERENCE:
+ case FIELD_ID_REF_BOOKMARK:
+ // reference to bookmarks, references: format, name (and element)
+ ProcessString(XML_REFERENCE_FORMAT,
+ MapReferenceType(GetInt16Property(
+ gsPropertyReferenceFieldPart, rPropSet)),
+ XML_TEMPLATE);
+ ProcessString(XML_REF_NAME,
+ GetStringProperty(gsPropertySourceName, rPropSet));
+ if (xPropSetInfo->hasPropertyByName(gsPropertyReferenceFieldLanguage) &&
+ GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
+ {
+ // export text:reference-language attribute, if not empty
+ ProcessString(XML_REFERENCE_LANGUAGE,
+ GetStringProperty(gsPropertyReferenceFieldLanguage, rPropSet), true, XML_NAMESPACE_LO_EXT);
+ }
+ ExportElement(
+ MapReferenceSource(GetInt16Property(
+ gsPropertyReferenceFieldSource, rPropSet)),
+ sPresentation);
+ break;
+
+ case FIELD_ID_REF_FOOTNOTE:
+ case FIELD_ID_REF_ENDNOTE:
+ // reference to end-/footnote: format, generate name, (and element)
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_NOTE_CLASS,
+ FIELD_ID_REF_ENDNOTE==nToken ? XML_ENDNOTE : XML_FOOTNOTE );
+ ProcessString(XML_REFERENCE_FORMAT,
+ MapReferenceType(GetInt16Property(
+ gsPropertyReferenceFieldPart, rPropSet)),
+ XML_TEMPLATE);
+ ProcessString(XML_REF_NAME,
+ MakeFootnoteRefName(GetInt16Property(
+ gsPropertySequenceNumber, rPropSet)));
+ if (xPropSetInfo->hasPropertyByName(gsPropertyReferenceFieldLanguage) &&
+ GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
+ {
+ // export text:reference-language attribute, if not empty
+ ProcessString(XML_REFERENCE_LANGUAGE,
+ GetStringProperty(gsPropertyReferenceFieldLanguage, rPropSet), true, XML_NAMESPACE_LO_EXT);
+ }
+ ExportElement(
+ MapReferenceSource(GetInt16Property(
+ gsPropertyReferenceFieldSource, rPropSet)),
+ sPresentation);
+ break;
+
+ case FIELD_ID_REF_STYLE:
+ {
+ ProcessString(XML_REFERENCE_FORMAT,
+ MapReferenceType(GetInt16Property(gsPropertyReferenceFieldPart, rPropSet)),
+ XML_TEMPLATE);
+ ProcessString(XML_REF_NAME, GetStringProperty(gsPropertySourceName, rPropSet));
+
+ sal_uInt16 referenceFieldFlags = GetIntProperty(gsPropertyReferenceFieldFlags, rPropSet);
+ // In reality gsPropertyReferenceFieldFlags is a uInt16... but there is no GetUInt16Property
+
+ bool fromBottom = (referenceFieldFlags & REFFLDFLAG_STYLE_FROM_BOTTOM) == REFFLDFLAG_STYLE_FROM_BOTTOM;
+ bool hideNonNumerical = (referenceFieldFlags & REFFLDFLAG_STYLE_HIDE_NON_NUMERICAL) == REFFLDFLAG_STYLE_HIDE_NON_NUMERICAL;
+
+ ProcessBoolean(XML_REFERENCE_FROM_BOTTOM, fromBottom, false, XML_NAMESPACE_LO_EXT);
+ ProcessBoolean(XML_REFERENCE_HIDE_NON_NUMERICAL, hideNonNumerical, false, XML_NAMESPACE_LO_EXT);
+
+ if (xPropSetInfo->hasPropertyByName(gsPropertyReferenceFieldLanguage)
+ && GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
+ {
+ // export text:reference-language attribute, if not empty
+ ProcessString(XML_REFERENCE_LANGUAGE,
+ GetStringProperty(gsPropertyReferenceFieldLanguage, rPropSet), true,
+ XML_NAMESPACE_LO_EXT);
+ }
+ SvXMLElementExport aElem(
+ GetExport(),
+ XML_NAMESPACE_LO_EXT,
+ MapReferenceSource(GetInt16Property(gsPropertyReferenceFieldSource, rPropSet)),
+ false,
+ false);
+ GetExport().Characters(sPresentation);
+ break;
+ }
+
+ case FIELD_ID_DDE:
+ // name from field master
+ ProcessString(XML_CONNECTION_NAME,
+
+ GetStringProperty(gsPropertyName,
+ GetMasterPropertySet(rTextField)));
+ ExportElement(XML_DDE_CONNECTION, sPresentation);
+ break;
+
+ case FIELD_ID_SHEET_NAME:
+ // name of spreadsheet (Calc only)
+ ExportElement(XML_SHEET_NAME, sPresentation);
+ break;
+
+ case FIELD_ID_PAGENAME:
+ {
+ if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
+ {
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_LO_EXT, XML_PAGE_NAME, false, false );
+ GetExport().Characters( sPresentation );
+ }
+ break;
+ }
+
+ case FIELD_ID_URL:
+ {
+ // this field is a special case because it gets mapped onto a
+ // hyperlink, rather than one of the regular text field.
+ ProcessString(XML_HREF, GetExport().GetRelativeReference(GetStringProperty(gsPropertyURL, rPropSet)),
+ false, XML_NAMESPACE_XLINK);
+ ProcessString(XML_TARGET_FRAME_NAME,
+ GetStringProperty(gsPropertyTargetFrame,rPropSet),
+ true, XML_NAMESPACE_OFFICE);
+ GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
+ SvXMLElementExport aUrlField(rExport, XML_NAMESPACE_TEXT, XML_A,
+ false, false);
+ GetExport().Characters(sPresentation);
+ break;
+ }
+
+ case FIELD_ID_BIBLIOGRAPHY:
+ {
+ ProcessBibliographyData(rPropSet);
+ ExportElement(XML_BIBLIOGRAPHY_MARK, sPresentation);
+ break;
+ }
+
+ case FIELD_ID_SCRIPT:
+ ProcessString(XML_LANGUAGE,
+ GetStringProperty(gsPropertyScriptType, rPropSet),
+ true, XML_NAMESPACE_SCRIPT);
+ DBG_ASSERT(sPresentation.isEmpty(),
+ "Unexpected presentation for script field");
+ if (GetBoolProperty(gsPropertyURLContent, rPropSet))
+ {
+ ProcessString(XML_HREF,
+ GetExport().GetRelativeReference(GetStringProperty(gsPropertyContent, rPropSet)),
+ false, XML_NAMESPACE_XLINK);
+ ExportElement(XML_SCRIPT);
+ }
+ else
+ {
+ ExportElement(XML_SCRIPT,
+ GetStringProperty(gsPropertyContent, rPropSet));
+ }
+ break;
+
+ case FIELD_ID_ANNOTATION:
+ {
+ // check for empty presentation (just in case)
+ DBG_ASSERT(sPresentation.isEmpty(),
+ "Unexpected presentation for annotation field");
+
+ bool bRemovePersonalInfo = SvtSecurityOptions::IsOptionSet(
+ SvtSecurityOptions::EOption::DocWarnRemovePersonalInfo ) && !SvtSecurityOptions::IsOptionSet(
+ SvtSecurityOptions::EOption::DocWarnKeepNoteAuthorDateInfo);
+
+ // annotation element + content
+ OUString aName;
+ rPropSet->getPropertyValue(gsPropertyName) >>= aName;
+ if (!aName.isEmpty())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_OFFICE, XML_NAME, aName);
+ }
+
+ OUString aParentName;
+ rPropSet->getPropertyValue(gsPropertyParentName) >>= aParentName;
+ if (!aParentName.isEmpty())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_PARENT_NAME, aParentName);
+ }
+
+ SvtSaveOptions::ODFSaneDefaultVersion eVersion = rExport.getSaneDefaultVersion();
+ if (eVersion & SvtSaveOptions::ODFSVER_EXTENDED)
+ {
+ bool b = GetBoolProperty("Resolved", rPropSet);
+ OUString aResolvedText;
+ OUStringBuffer aResolvedTextBuffer;
+ ::sax::Converter::convertBool(aResolvedTextBuffer, b);
+ aResolvedText = aResolvedTextBuffer.makeStringAndClear();
+
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_RESOLVED, aResolvedText);
+ }
+ SvXMLElementExport aElem(GetExport(), XML_NAMESPACE_OFFICE,
+ XML_ANNOTATION, false, true);
+
+ // author
+ OUString aAuthor( GetStringProperty(gsPropertyAuthor, rPropSet) );
+ if( !aAuthor.isEmpty() )
+ {
+ SvXMLElementExport aCreatorElem( GetExport(), XML_NAMESPACE_DC,
+ XML_CREATOR, true,
+ false );
+ GetExport().Characters( bRemovePersonalInfo
+ ? "Author" + OUString::number( rExport.GetInfoID(aAuthor) )
+ : aAuthor );
+ }
+
+ // date time
+ util::DateTime aDate( GetDateTimeProperty(gsPropertyDateTimeValue, rPropSet) );
+ if ( !bRemovePersonalInfo )
+ {
+ OUStringBuffer aBuffer;
+ ::sax::Converter::convertDateTime(aBuffer, aDate, nullptr, true);
+ SvXMLElementExport aDateElem( GetExport(), XML_NAMESPACE_DC,
+ XML_DATE, true,
+ false );
+ GetExport().Characters(aBuffer.makeStringAndClear());
+ }
+
+ if (GetExport().getSaneDefaultVersion() > SvtSaveOptions::ODFSVER_012)
+ {
+ // initials
+ OUString aInitials( GetStringProperty(gsPropertyInitials, rPropSet) );
+ if( !aInitials.isEmpty() )
+ {
+ // ODF 1.3 OFFICE-3776 export meta:creator-initials for ODF 1.3
+ SvXMLElementExport aCreatorElem( GetExport(),
+ (SvtSaveOptions::ODFSVER_013 <= GetExport().getSaneDefaultVersion())
+ ? XML_NAMESPACE_META
+ : XML_NAMESPACE_LO_EXT,
+
+ (SvtSaveOptions::ODFSVER_013 <= GetExport().getSaneDefaultVersion())
+ ? XML_CREATOR_INITIALS
+ : XML_SENDER_INITIALS,
+ true, false );
+ GetExport().Characters( bRemovePersonalInfo
+ ? OUString::number( rExport.GetInfoID(aInitials) )
+ : aInitials);
+ }
+ }
+
+ css::uno::Reference < css::text::XText > xText;
+ try
+ {
+ css::uno::Any aRet = rPropSet->getPropertyValue(gsPropertyTextRange);
+ aRet >>= xText;
+ }
+ catch ( css::uno::Exception& )
+ {}
+
+ if ( xText.is() )
+ GetExport().GetTextParagraphExport()->exportText( xText );
+ else
+ ProcessParagraphSequence(GetStringProperty(gsPropertyContent,rPropSet));
+ break;
+ }
+
+ case FIELD_ID_COMBINED_CHARACTERS:
+ {
+ // The style with the combined characters attribute has
+ // already been handled in the ExportField method. So all that
+ // is left to do now is to export the characters.
+ GetExport().Characters(sPresentation);
+ break;
+ }
+
+ case FIELD_ID_META:
+ {
+ ExportMetaField(rPropSet, false, bProgress, rPrevCharIsSpace);
+ break;
+ }
+
+ case FIELD_ID_MEASURE:
+ {
+ ProcessString(XML_KIND, MapMeasureKind(GetInt16Property(gsPropertyMeasureKind, rPropSet)));
+ ExportElement( XML_MEASURE, sPresentation );
+ break;
+ }
+
+ case FIELD_ID_TABLE_FORMULA:
+ ProcessString( XML_FORMULA, XML_NAMESPACE_OOOW,
+ GetStringProperty(gsPropertyContent, rPropSet) );
+ ProcessDisplay( true,
+ GetBoolProperty(gsPropertyIsShowFormula, rPropSet) );
+ ProcessValueAndType( false,
+ GetIntProperty(gsPropertyNumberFormat, rPropSet),
+ "", u"", 0.0f,
+ false, false, true,
+ false );
+ ExportElement( XML_TABLE_FORMULA, sPresentation );
+ break;
+
+ case FIELD_ID_DROP_DOWN:
+ {
+ // tdf#133555 don't export in strict ODF versions that don't have it
+ if (GetExport().getSaneDefaultVersion() <= SvtSaveOptions::ODFSVER_012)
+ {
+ break;
+ }
+ ProcessString(XML_NAME, GetStringProperty(gsPropertyName, rPropSet));
+ ProcessString(XML_HELP,
+ GetStringProperty(gsPropertyHelp, rPropSet), true);
+ ProcessString(XML_HINT,
+ GetStringProperty(gsPropertyTooltip, rPropSet), true);
+ SvXMLElementExport aElem( GetExport(),
+ XML_NAMESPACE_TEXT, XML_DROP_DOWN,
+ false, false );
+ ProcessStringSequence
+ (GetStringSequenceProperty( gsPropertyItems, rPropSet ),
+ GetStringProperty( gsPropertySelectedItem, rPropSet ) );
+
+ GetExport().Characters( sPresentation );
+ }
+ break;
+
+ case FIELD_ID_DRAW_HEADER:
+ {
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_PRESENTATION, XML_HEADER, false, false );
+ }
+ break;
+
+ case FIELD_ID_DRAW_FOOTER:
+ {
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_PRESENTATION, XML_FOOTER, false, false );
+ }
+ break;
+
+ case FIELD_ID_DRAW_DATE_TIME:
+ {
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_PRESENTATION, XML_DATE_TIME, false, false );
+ }
+ break;
+
+
+ case FIELD_ID_UNKNOWN:
+ default:
+ OSL_FAIL("unknown field type encountered!");
+ // always export content
+ GetExport().Characters(sPresentation);
+ }
+}
+
+
+/// export field declarations / field masters
+void XMLTextFieldExport::ExportFieldDeclarations()
+{
+ Reference<XText> xEmptyText;
+ ExportFieldDeclarations(xEmptyText);
+}
+
+/// export field declarations / field masters
+void XMLTextFieldExport::ExportFieldDeclarations(
+ const Reference<XText> & rText )
+{
+ // store lists for decl elements
+ std::vector<OUString> aVarName;
+ std::vector<OUString> aUserName;
+ std::vector<OUString> aSeqName;
+ std::vector<OUString> aDdeName;
+
+ // get text fields supplier and field master name access
+ Reference<XTextFieldsSupplier> xTextFieldsSupp(GetExport().GetModel(),
+ UNO_QUERY);
+ if( !xTextFieldsSupp.is() )
+ return;
+
+ Reference<container::XNameAccess> xFieldMasterNameAccess =
+ xTextFieldsSupp->getTextFieldMasters();
+
+ // where to get the text field masters from?
+ // a) we get a specific XText: then use pUsedMasters
+ // b) the XText is empty: then export all text fields
+ Sequence<OUString> aFieldMasters;
+ if (rText.is())
+ {
+ // export only used masters
+ DBG_ASSERT(nullptr != pUsedMasters,
+ "field masters must be recorded in order to be "
+ "written out separately" );
+ if (nullptr != pUsedMasters)
+ {
+ std::map<Reference<XText>, std::set<OUString> > ::iterator aMapIter =
+ pUsedMasters->find(rText);
+ if (aMapIter != pUsedMasters->end())
+ {
+ // found the set of used field masters
+ aFieldMasters = comphelper::containerToSequence(aMapIter->second);
+ pUsedMasters->erase(rText);
+ }
+ // else: XText not found -> ignore
+ }
+ // else: no field masters have been recorded -> ignore
+ }
+ else
+ {
+ // no XText: export all!
+ aFieldMasters = xFieldMasterNameAccess->getElementNames();
+ }
+
+ for(const OUString& sFieldMaster : std::as_const(aFieldMasters)) {
+
+ // workaround for #no-bug#
+ if ( sFieldMaster.startsWithIgnoreAsciiCase(
+ "com.sun.star.text.FieldMaster.DataBase.") )
+ {
+ continue;
+ }
+
+
+ OUString sFieldMasterType;
+ OUString sVarName;
+ ExplodeFieldMasterName(sFieldMaster, sFieldMasterType, sVarName);
+
+ // get XPropertySet of this field master
+ Reference<XPropertySet> xPropSet;
+ Any aAny = xFieldMasterNameAccess->getByName(sFieldMaster);
+ aAny >>= xPropSet;
+
+ // save interesting field masters
+ if (sFieldMasterType == FIELD_SERVICE_SETEXP)
+ {
+ sal_Int32 nType = GetIntProperty(gsPropertySubType, xPropSet);
+
+ // sequence or variable?
+ if ( SetVariableType::SEQUENCE == nType )
+ {
+ aSeqName.push_back( sFieldMaster );
+ }
+ else
+ {
+ aVarName.push_back( sFieldMaster );
+ }
+ }
+ else if (sFieldMasterType == FIELD_SERVICE_USER)
+ {
+ aUserName.push_back( sFieldMaster );
+ }
+ else if (sFieldMasterType == FIELD_SERVICE_DDE)
+ {
+ aDdeName.push_back( sFieldMaster );
+ }
+ else
+ {
+ ; // ignore
+ }
+ }
+
+ // now process fields:
+
+ // variable field masters:
+ if ( !aVarName.empty() )
+ {
+ SvXMLElementExport aElem( GetExport(),
+ XML_NAMESPACE_TEXT,
+ XML_VARIABLE_DECLS,
+ true, true );
+
+ for (const auto& sName : aVarName)
+ {
+ // get field master property set
+ Reference<XPropertySet> xPropSet;
+ Any aAny = xFieldMasterNameAccess->getByName(sName);
+ aAny >>= xPropSet;
+
+ // field name and type
+ OUString sFieldMasterType;
+ OUString sVarName;
+ ExplodeFieldMasterName(sName, sFieldMasterType, sVarName);
+
+ // determine string/numeric field
+ bool bIsString = ( GetIntProperty(gsPropertySubType, xPropSet)
+ == SetVariableType::STRING );
+
+ // get dependent field property set
+ Reference<XPropertySet> xFieldPropSet;
+ if (GetDependentFieldPropertySet(xPropSet, xFieldPropSet))
+ {
+ // process value and type.
+ ProcessValueAndType(
+ bIsString,
+ GetIntProperty(gsPropertyNumberFormat, xFieldPropSet),
+ "", u"", 0.0,
+ false, true, false, false);
+ }
+ else
+ {
+ // If no dependent field is found, only string and
+ // float types can be supported
+
+ // number format: 0 is default number format for 1st
+ // language. should be: getDefaultNumberFormat(Locale)
+ // from NumberFormats
+ ProcessValueAndType(
+ bIsString,
+ 0, "", u"", 0.0,
+ false, true, false, false);
+ }
+
+ ProcessString(XML_NAME, sVarName);
+ ExportElement(XML_VARIABLE_DECL, true);
+ }
+ }
+ // else: no declarations element
+
+ // sequence field masters:
+ if ( !aSeqName.empty() )
+ {
+ SvXMLElementExport aElem( GetExport(),
+ XML_NAMESPACE_TEXT,
+ XML_SEQUENCE_DECLS,
+ true, true );
+
+ for (const auto& sName : aSeqName)
+ {
+ // get field master property set
+ Reference<XPropertySet> xPropSet;
+ Any aAny = xFieldMasterNameAccess->getByName(sName);
+ aAny >>= xPropSet;
+
+ // field name and type
+ OUString sFieldMasterType;
+ OUString sVarName;
+ ExplodeFieldMasterName(sName, sFieldMasterType, sVarName);
+
+ // outline level
+ sal_Int32 nLevel = 1 + GetIntProperty(
+ gsPropertyChapterNumberingLevel, xPropSet);
+ DBG_ASSERT(nLevel >= 0, "illegal outline level");
+ DBG_ASSERT(nLevel < 127, "possible illegal outline level");
+ ProcessInteger(XML_DISPLAY_OUTLINE_LEVEL, nLevel);
+
+ // separation character
+ if (nLevel > 0) {
+ ProcessString(XML_SEPARATION_CHARACTER, GetStringProperty(
+ gsPropertyNumberingSeparator, xPropSet));
+ }
+ ProcessString(XML_NAME, sVarName);
+ ExportElement(XML_SEQUENCE_DECL, true);
+ }
+ }
+ // else: no declarations element
+
+ // user field masters:
+ if ( !aUserName.empty() )
+ {
+ SvXMLElementExport aElem( GetExport(),
+ XML_NAMESPACE_TEXT,
+ XML_USER_FIELD_DECLS,
+ true, true );
+
+ for (const auto& sName : aUserName)
+ {
+ // get field master property set
+ Reference<XPropertySet> xPropSet;
+ Any aAny = xFieldMasterNameAccess->getByName(sName);
+ aAny >>= xPropSet;
+
+ // field name and type
+ OUString sFieldMasterType;
+ OUString sVarName;
+ ExplodeFieldMasterName(sName, sFieldMasterType, sVarName);
+
+ if (GetBoolProperty(gsPropertyIsExpression, xPropSet))
+ {
+ // expression:
+ ProcessValueAndType(
+ false,
+ 0, "", u"",
+ GetDoubleProperty(gsPropertyValue, xPropSet),
+ true,
+ true,
+ false,
+ false);
+ }
+ else
+ {
+ // string: write regardless of default
+ ProcessString(XML_VALUE_TYPE, XML_STRING,
+ XML_NAMESPACE_OFFICE);
+ ProcessString(XML_STRING_VALUE,
+ GetStringProperty(gsPropertyContent, xPropSet),
+ false, XML_NAMESPACE_OFFICE );
+ }
+ ProcessString(XML_NAME, sVarName);
+ ExportElement(XML_USER_FIELD_DECL, true);
+ }
+ }
+ // else: no declarations element
+
+ // DDE field masters:
+ if ( aDdeName.empty() )
+ return;
+
+ SvXMLElementExport aElem( GetExport(),
+ XML_NAMESPACE_TEXT,
+ XML_DDE_CONNECTION_DECLS,
+ true, true );
+
+ for (const auto& sName : aDdeName)
+ {
+ // get field master property set
+ Reference<XPropertySet> xPropSet;
+ Any aAny = xFieldMasterNameAccess->getByName(sName);
+ aAny >>= xPropSet;
+
+ // check if this connection is being used by a field
+ Reference<XPropertySet> xDummy;
+ if (GetDependentFieldPropertySet(xPropSet, xDummy))
+ {
+
+ ProcessString(XML_NAME,
+ GetStringProperty(gsPropertyName, xPropSet),
+ false, XML_NAMESPACE_OFFICE);
+
+ // export elements; can't use ProcessString because
+ // elements are in office namespace
+ ProcessString(XML_DDE_APPLICATION,
+ GetStringProperty(gsPropertyDDECommandType,
+ xPropSet),
+ false, XML_NAMESPACE_OFFICE);
+ ProcessString(XML_DDE_TOPIC,
+ GetStringProperty(gsPropertyDDECommandFile,
+ xPropSet),
+ false, XML_NAMESPACE_OFFICE);
+ ProcessString(XML_DDE_ITEM,
+ GetStringProperty(gsPropertyDDECommandElement,
+ xPropSet),
+ false, XML_NAMESPACE_OFFICE);
+ bool bIsAutomaticUpdate = GetBoolProperty(
+ gsPropertyIsAutomaticUpdate, xPropSet);
+ if (bIsAutomaticUpdate)
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_OFFICE,
+ XML_AUTOMATIC_UPDATE,
+ XML_TRUE);
+ }
+
+ ExportElement(XML_DDE_CONNECTION_DECL, true);
+ }
+ // else: no dependent field -> no export of field declaration
+ }
+ // else: no declarations element
+}
+
+void XMLTextFieldExport::SetExportOnlyUsedFieldDeclarations(
+ bool bExportOnlyUsed)
+{
+ pUsedMasters.reset();
+
+ // create used masters set (if none is used)
+ if (bExportOnlyUsed)
+ pUsedMasters.reset( new std::map<Reference<XText>, std::set<OUString> > );
+}
+
+void XMLTextFieldExport::ExportElement(enum XMLTokenEnum eElementName,
+ bool bAddSpace)
+{
+ // can't call ExportElement(eElementName, const OUString&) with empty
+ // string because xmlprinter only uses empty tags if no content
+ // (not even empty content) was written.
+
+ DBG_ASSERT(XML_TOKEN_INVALID != eElementName, "invalid element name!");
+ if (XML_TOKEN_INVALID != eElementName)
+ {
+ // Element
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
+ eElementName, bAddSpace, bAddSpace );
+ } // else: ignore
+}
+
+void XMLTextFieldExport::ExportElement(enum XMLTokenEnum eElementName,
+ const OUString& sContent)
+{
+ DBG_ASSERT(eElementName != XML_TOKEN_INVALID, "invalid element name!");
+ if (eElementName != XML_TOKEN_INVALID)
+ {
+ // Element
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
+ eElementName, false, false );
+ // export content
+ GetExport().Characters(sContent);
+ } else {
+ // always export content
+ GetExport().Characters(sContent);
+ }
+}
+
+void XMLTextFieldExport::ExportMacro(
+ const Reference<XPropertySet> & rPropSet,
+ const OUString& rContent )
+{
+ // some strings we'll need
+ OUString sEventType( "EventType" );
+
+
+ // the description attribute
+ ProcessString(XML_DESCRIPTION,
+ GetStringProperty(gsPropertyHint, rPropSet),
+ rContent);
+
+ // the element
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
+ XML_EXECUTE_MACRO, false, false );
+
+ // the <office:events>-macro:
+
+ // 1) build sequence of PropertyValues
+ Sequence<PropertyValue> aSeq;
+ OUString sName;
+ rPropSet->getPropertyValue("ScriptURL") >>= sName;
+
+ // if the ScriptURL property is not empty then this is a Scripting
+ // Framework URL, otherwise treat it as a Basic Macro
+ if (!sName.isEmpty())
+ {
+ OUString sScript( "Script" );
+ aSeq = Sequence<PropertyValue>
+ {
+ comphelper::makePropertyValue(sEventType, sScript),
+ comphelper::makePropertyValue(sScript, sName)
+ };
+ }
+ else
+ {
+ aSeq = Sequence<PropertyValue>
+ {
+ comphelper::makePropertyValue(sEventType, OUString("StarBasic")),
+ comphelper::makePropertyValue("Library", rPropSet->getPropertyValue( "MacroLibrary" )),
+ comphelper::makePropertyValue("MacroName", rPropSet->getPropertyValue( "MacroName" ))
+ };
+ }
+
+ // 2) export the sequence
+ GetExport().GetEventExport().ExportSingleEvent( aSeq, "OnClick", false );
+
+ // and finally, the field presentation
+ GetExport().Characters(rContent);
+}
+
+void XMLTextFieldExport::ExportMetaField(
+ const Reference<XPropertySet> & i_xMeta,
+ bool i_bAutoStyles, bool i_bProgress,
+ bool & rPrevCharIsSpace)
+{
+ bool doExport(!i_bAutoStyles); // do not export element if autostyles
+ // check version >= 1.2
+ switch (GetExport().getSaneDefaultVersion()) {
+ case SvtSaveOptions::ODFSVER_011: // fall through
+ case SvtSaveOptions::ODFSVER_010: doExport = false; break;
+ default: break;
+ }
+
+ const Reference < XEnumerationAccess > xEA( i_xMeta, UNO_QUERY_THROW );
+ const Reference < XEnumeration > xTextEnum( xEA->createEnumeration() );
+
+ if (doExport)
+ {
+ const Reference<rdf::XMetadatable> xMeta( i_xMeta, UNO_QUERY_THROW );
+
+ // style:data-style-name
+ ProcessValueAndType(false,
+ GetIntProperty(gsPropertyNumberFormat, i_xMeta),
+ "", u"", 0.0, false, false, true,
+ false );
+
+ // text:meta-field without xml:id is invalid
+ xMeta->ensureMetadataReference();
+
+ // xml:id for RDF metadata
+ GetExport().AddAttributeXmlId(xMeta);
+ }
+
+ SvXMLElementExport aElem( GetExport(), doExport,
+ XML_NAMESPACE_TEXT, XML_META_FIELD, false, false );
+
+ // recurse to export content
+ GetExport().GetTextParagraphExport()->
+ exportTextRangeEnumeration(xTextEnum, i_bAutoStyles, i_bProgress, rPrevCharIsSpace);
+}
+
+/// export all data-style related attributes
+void XMLTextFieldExport::ProcessValueAndType(
+ bool bIsString, /// do we process a string or a number?
+ sal_Int32 nFormatKey, /// format key for NumberFormatter; inv. if string
+ const OUString& sContent, /// string content; possibly invalid
+ std::u16string_view sDefault, /// default string
+ double fValue, /// float content; possibly invalid
+ bool bExportValue, /// export value attribute?
+ bool bExportValueType, /// export value-type attribute?
+ bool bExportStyle, /// export style-attribute?
+ bool bForceSystemLanguage, /// export language attributes?
+ bool bTimeStyle) // exporting a time style?
+{
+ // String or number?
+ if (bIsString)
+ {
+
+ // string: attributes value-type=string, string-value=...
+
+ if (bExportValue || bExportValueType)
+ {
+ XMLNumberFormatAttributesExportHelper::SetNumberFormatAttributes(
+ GetExport(), sContent, sDefault, bExportValue);
+ }
+
+ }
+ else
+ {
+
+ // number: value-type=..., value...=..., data-style-name=...
+
+ DBG_ASSERT(bExportValueType || !bExportValue, "value w/o value type not supported!");
+
+ // take care of illegal formats
+ // (shouldn't happen, but does if document is corrupted)
+ if (-1 != nFormatKey)
+ {
+ if (bExportValue || bExportValueType)
+ {
+ XMLNumberFormatAttributesExportHelper::
+ SetNumberFormatAttributes(
+ GetExport(), nFormatKey, fValue, bExportValue);
+ }
+
+ if (bExportStyle)
+ {
+ // don't export language (if desired)
+ if( bForceSystemLanguage )
+ nFormatKey =
+ GetExport().dataStyleForceSystemLanguage( nFormatKey );
+
+ OUString sDataStyleName =
+ GetExport().getDataStyleName(nFormatKey, bTimeStyle);
+ if( !sDataStyleName.isEmpty() )
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE,
+ XML_DATA_STYLE_NAME,
+ sDataStyleName );
+ } // else: ignore (no valid number format)
+ } // else: ignore (no number format)
+ }
+ }
+}
+
+
+/// process display related properties
+void XMLTextFieldExport::ProcessDisplay(bool bIsVisible,
+ bool bIsCommand)
+{
+ enum XMLTokenEnum eValue;
+
+ if (bIsVisible)
+ {
+ eValue = bIsCommand ? XML_FORMULA : XML_VALUE;
+ }
+ else
+ {
+ eValue = XML_NONE;
+ }
+
+ // omit attribute if default
+ if (eValue != XML_VALUE)
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_DISPLAY, eValue);
+ }
+}
+
+
+void XMLTextFieldExport::ProcessBoolean(enum XMLTokenEnum eName,
+ bool bBool, bool bDefault)
+{
+ ProcessBoolean(eName, bBool, bDefault, XML_NAMESPACE_TEXT);
+}
+
+/// export boolean property
+void XMLTextFieldExport::ProcessBoolean(enum XMLTokenEnum eName,
+ bool bBool, bool bDefault, sal_uInt16 nPrefix)
+{
+ SAL_WARN_IF( eName == XML_TOKEN_INVALID, "xmloff.text", "invalid element token");
+ if ( XML_TOKEN_INVALID == eName )
+ return;
+
+ // write attribute (if different than default)
+ // negate to force 0/1 values (and make sal_Bool comparable)
+ if ((!bBool) != (!bDefault)) {
+ GetExport().AddAttribute(nPrefix, eName,
+ (bBool ? XML_TRUE : XML_FALSE) );
+ }
+}
+
+/// export string attribute
+void XMLTextFieldExport::ProcessString(enum XMLTokenEnum eName,
+ const OUString& sValue,
+ bool bOmitEmpty,
+ sal_uInt16 nPrefix)
+{
+ SAL_WARN_IF( eName == XML_TOKEN_INVALID, "xmloff.text", "invalid element token");
+ if ( XML_TOKEN_INVALID == eName )
+ return;
+
+ // check for empty string, if applicable
+ if ( bOmitEmpty && sValue.isEmpty() )
+ return;
+
+ // write attribute
+ GetExport().AddAttribute(nPrefix, eName, sValue);
+}
+
+void XMLTextFieldExport::ProcessString(enum XMLTokenEnum eName,
+ sal_uInt16 nValuePrefix,
+ const OUString& sValue)
+{
+ OUString sQValue =
+ GetExport().GetNamespaceMap().GetQNameByKey( nValuePrefix, sValue, false );
+ ProcessString( eName, sQValue );
+}
+
+/// export a string attribute
+void XMLTextFieldExport::ProcessString(enum XMLTokenEnum eName,
+ const OUString& sValue,
+ std::u16string_view sDefault)
+{
+ if (sValue != sDefault)
+ {
+ ProcessString(eName, sValue);
+ }
+}
+
+/// export a string attribute
+void XMLTextFieldExport::ProcessString(enum XMLTokenEnum eName,
+ sal_uInt16 nValuePrefix,
+ const OUString& sValue,
+ std::u16string_view sDefault)
+{
+ if (sValue != sDefault)
+ {
+ ProcessString(eName, nValuePrefix, sValue);
+ }
+}
+
+
+/// export string attribute
+void XMLTextFieldExport::ProcessString(
+ enum XMLTokenEnum eName,
+ enum XMLTokenEnum eValue,
+ sal_uInt16 nPrefix)
+{
+ SAL_WARN_IF( eName == XML_TOKEN_INVALID, "xmloff.text", "invalid element token" );
+ SAL_WARN_IF( eValue == XML_TOKEN_INVALID, "xmloff.text", "invalid value token" );
+ if ( XML_TOKEN_INVALID == eName )
+ return;
+
+ GetExport().AddAttribute(nPrefix, eName, eValue);
+}
+
+/// export a string attribute
+void XMLTextFieldExport::ProcessString(
+ enum XMLTokenEnum eName,
+ enum XMLTokenEnum eValue,
+ enum XMLTokenEnum eDefault)
+{
+ if ( eValue != eDefault )
+ ProcessString( eName, eValue);
+}
+
+
+/// export a string as a sequence of paragraphs
+void XMLTextFieldExport::ProcessParagraphSequence(
+ std::u16string_view sParagraphSequence)
+{
+ // iterate over all string-pieces separated by return (0x0a) and
+ // put each inside a paragraph element.
+ SvXMLTokenEnumerator aEnumerator(sParagraphSequence, char(0x0a));
+ std::u16string_view aSubString;
+ while (aEnumerator.getNextToken(aSubString))
+ {
+ SvXMLElementExport aParagraph(
+ GetExport(), XML_NAMESPACE_TEXT, XML_P, true, false);
+ GetExport().Characters(OUString(aSubString));
+ }
+}
+
+// export an integer attribute
+void XMLTextFieldExport::ProcessInteger(enum XMLTokenEnum eName,
+ sal_Int32 nNum)
+{
+ SAL_WARN_IF( eName == XML_TOKEN_INVALID, "xmloff.text", "invalid element token");
+ if ( XML_TOKEN_INVALID == eName )
+ return;
+
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, eName,
+ OUString::number(nNum));
+}
+
+/// export an integer attribute, omit if default
+void XMLTextFieldExport::ProcessIntegerDef(enum XMLTokenEnum eName,
+ sal_Int32 nNum, sal_Int32 nDefault)
+{
+ if (nNum != nDefault)
+ ProcessInteger(eName, nNum);
+}
+
+
+/// export a numbering type
+void XMLTextFieldExport::ProcessNumberingType(sal_Int16 nNumberingType)
+{
+ // process only if real format (not: like page descriptor)
+ if (NumberingType::PAGE_DESCRIPTOR == nNumberingType)
+ return;
+
+ OUStringBuffer sTmp( 10 );
+ // number type: num format
+ GetExport().GetMM100UnitConverter().convertNumFormat( sTmp,
+ nNumberingType );
+ GetExport().AddAttribute(XML_NAMESPACE_STYLE, XML_NUM_FORMAT,
+ sTmp.makeStringAndClear() );
+ // and letter sync, if applicable
+ SvXMLUnitConverter::convertNumLetterSync( sTmp, nNumberingType );
+
+ if (!sTmp.isEmpty())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_STYLE, XML_NUM_LETTER_SYNC,
+ sTmp.makeStringAndClear() );
+ }
+ // else: like page descriptor => ignore
+}
+
+
+/// export a date, time, or duration
+void XMLTextFieldExport::ProcessDateTime(enum XMLTokenEnum eName,
+ double dValue,
+ bool bIsDate,
+ bool bIsDuration,
+ bool bOmitDurationIfZero,
+ sal_uInt16 nPrefix)
+{
+ // truncate for date granularity
+ if (bIsDate)
+ {
+ dValue = ::rtl::math::approxFloor(dValue);
+ }
+
+ OUStringBuffer aBuffer;
+ if (bIsDuration)
+ {
+ // date/time duration handle bOmitDurationIfZero
+ if (!bOmitDurationIfZero || dValue != 0.0)
+ {
+ ::sax::Converter::convertDuration(aBuffer, dValue);
+ }
+ }
+ else
+ {
+ // date/time value
+ rExport.GetMM100UnitConverter().convertDateTime(aBuffer, dValue);
+ }
+
+ // output attribute
+ ProcessString(eName, aBuffer.makeStringAndClear(), true, nPrefix);
+}
+
+/// export a date or time
+void XMLTextFieldExport::ProcessDateTime(enum XMLTokenEnum eName,
+ const util::DateTime& rTime)
+{
+ OUStringBuffer aBuffer;
+
+ util::DateTime aDateTime(rTime);
+
+ // date/time value
+ ::sax::Converter::convertDateTime(aBuffer, aDateTime, nullptr);
+
+ // output attribute
+ ProcessString(eName, aBuffer.makeStringAndClear(), true);
+}
+
+/// export a date, time, or duration
+void XMLTextFieldExport::ProcessDateTime(enum XMLTokenEnum eName,
+ sal_Int32 nMinutes,
+ bool bIsDate,
+ bool bIsDuration)
+{
+ // handle bOmitDurationIfZero here, because we can precisely compare ints
+ if (!(bIsDuration && (nMinutes==0)))
+ {
+ ProcessDateTime(eName, static_cast<double>(nMinutes) / double(24*60),
+ bIsDate, bIsDuration);
+ }
+}
+
+/// export a time or dateTime
+void XMLTextFieldExport::ProcessTimeOrDateTime(enum XMLTokenEnum eName,
+ const util::DateTime& rTime)
+{
+ OUStringBuffer aBuffer;
+
+ // date/time value
+ ::sax::Converter::convertTimeOrDateTime(aBuffer, rTime);
+
+ // output attribute
+ ProcessString(eName, aBuffer.makeStringAndClear(), true);
+}
+
+
+SvXMLEnumMapEntry<sal_Int16> const aBibliographyDataTypeMap[] =
+{
+ { XML_ARTICLE, BibliographyDataType::ARTICLE },
+ { XML_BOOK, BibliographyDataType::BOOK },
+ { XML_BOOKLET, BibliographyDataType::BOOKLET },
+ { XML_CONFERENCE, BibliographyDataType::CONFERENCE },
+ { XML_CUSTOM1, BibliographyDataType::CUSTOM1 },
+ { XML_CUSTOM2, BibliographyDataType::CUSTOM2 },
+ { XML_CUSTOM3, BibliographyDataType::CUSTOM3 },
+ { XML_CUSTOM4, BibliographyDataType::CUSTOM4 },
+ { XML_CUSTOM5, BibliographyDataType::CUSTOM5 },
+ { XML_EMAIL, BibliographyDataType::EMAIL },
+ { XML_INBOOK, BibliographyDataType::INBOOK },
+ { XML_INCOLLECTION, BibliographyDataType::INCOLLECTION },
+ { XML_INPROCEEDINGS, BibliographyDataType::INPROCEEDINGS },
+ { XML_JOURNAL, BibliographyDataType::JOURNAL },
+ { XML_MANUAL, BibliographyDataType::MANUAL },
+ { XML_MASTERSTHESIS, BibliographyDataType::MASTERSTHESIS },
+ { XML_MISC, BibliographyDataType::MISC },
+ { XML_PHDTHESIS, BibliographyDataType::PHDTHESIS },
+ { XML_PROCEEDINGS, BibliographyDataType::PROCEEDINGS },
+ { XML_TECHREPORT, BibliographyDataType::TECHREPORT },
+ { XML_UNPUBLISHED, BibliographyDataType::UNPUBLISHED },
+ { XML_WWW, BibliographyDataType::WWW },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+
+void XMLTextFieldExport::ProcessBibliographyData(
+ const Reference<XPropertySet>& rPropSet)
+{
+ // get the values
+ Any aAny = rPropSet->getPropertyValue(gsPropertyFields);
+ Sequence<PropertyValue> aValues;
+ aAny >>= aValues;
+
+ // one attribute per value (unless empty)
+ for (const auto& rProp : std::as_const(aValues))
+ {
+ if( rProp.Name == "BibiliographicType" )
+ {
+ sal_Int16 nTypeId = 0;
+ rProp.Value >>= nTypeId;
+ OUStringBuffer sBuf;
+
+ if (SvXMLUnitConverter::convertEnum(sBuf, nTypeId,
+ aBibliographyDataTypeMap))
+ {
+ rExport.AddAttribute(XML_NAMESPACE_TEXT,
+ XML_BIBLIOGRAPHY_TYPE,
+ sBuf.makeStringAndClear());
+ }
+ // else: ignore this argument
+ }
+ else
+ {
+ OUString sStr;
+ rProp.Value >>= sStr;
+
+ if (!sStr.isEmpty())
+ {
+ XMLTokenEnum eElement = MapBibliographyFieldName(rProp.Name);
+ if (eElement == XML_URL || eElement == XML_LOCAL_URL || eElement == XML_TARGET_URL)
+ {
+ sStr = GetExport().GetRelativeReference(sStr);
+ }
+ sal_uInt16 nPrefix = XML_NAMESPACE_TEXT;
+ if (eElement == XML_LOCAL_URL || eElement == XML_TARGET_TYPE
+ || eElement == XML_TARGET_URL)
+ {
+ nPrefix = XML_NAMESPACE_LO_EXT;
+ }
+ rExport.AddAttribute(nPrefix, eElement, sStr);
+ }
+ }
+ }
+}
+
+/// export CommandTypeAttribute
+void XMLTextFieldExport::ProcessCommandType(
+ sal_Int32 nCommandType)
+{
+ enum XMLTokenEnum eToken = XML_TOKEN_INVALID;
+ switch( nCommandType )
+ {
+ case sdb::CommandType::TABLE: eToken = XML_TABLE; break;
+ case sdb::CommandType::QUERY: eToken = XML_QUERY; break;
+ case sdb::CommandType::COMMAND: eToken = XML_COMMAND; break;
+ }
+
+ if( eToken != XML_TOKEN_INVALID )
+ rExport.AddAttribute( XML_NAMESPACE_TEXT, XML_TABLE_TYPE, eToken );
+}
+
+
+void XMLTextFieldExport::ProcessStringSequence(
+ const Sequence<OUString>& rSequence,
+ const OUString& sSelected )
+{
+ // find selected element
+ sal_Int32 nSelected = comphelper::findValue(rSequence, sSelected);
+
+ // delegate to ProcessStringSequence(OUString,sal_Int32)
+ ProcessStringSequence( rSequence, nSelected );
+}
+
+void XMLTextFieldExport::ProcessStringSequence(
+ const Sequence<OUString>& rSequence,
+ sal_Int32 nSelected )
+{
+ sal_Int32 nLength = rSequence.getLength();
+ const OUString* pSequence = rSequence.getConstArray();
+ for( sal_Int32 i = 0; i < nLength; i++ )
+ {
+ if( i == nSelected )
+ rExport.AddAttribute( XML_NAMESPACE_TEXT,
+ XML_CURRENT_SELECTED, XML_TRUE );
+ rExport.AddAttribute( XML_NAMESPACE_TEXT, XML_VALUE, pSequence[i] );
+ SvXMLElementExport aElement( rExport, XML_NAMESPACE_TEXT, XML_LABEL,
+ false, false );
+ }
+}
+
+void XMLTextFieldExport::ExportDataBaseElement(
+ enum XMLTokenEnum eElementName,
+ const OUString& sPresentation,
+ const Reference<XPropertySet>& rPropertySet,
+ const Reference<XPropertySetInfo>& rPropertySetInfo )
+{
+ SAL_WARN_IF( eElementName == XML_TOKEN_INVALID, "xmloff.text", "need token" );
+ SAL_WARN_IF( !rPropertySet.is(), "xmloff.text", "need property set" );
+ SAL_WARN_IF( !rPropertySetInfo.is(), "xmloff.text", "need property set info" );
+
+ // get database properties
+ OUString sDataBaseName;
+ OUString sDataBaseURL;
+ OUString sStr;
+ if( ( rPropertySet->getPropertyValue( gsPropertyDataBaseName ) >>= sStr )
+ && !sStr.isEmpty() )
+ {
+ sDataBaseName = sStr;
+ }
+ else if( rPropertySetInfo->hasPropertyByName( gsPropertyDataBaseURL ) &&
+ (rPropertySet->getPropertyValue( gsPropertyDataBaseURL ) >>= sStr) &&
+ !sStr.isEmpty() )
+ {
+ sDataBaseURL = sStr;
+ }
+
+ // add database name property (if present)
+ if( !sDataBaseName.isEmpty() )
+ rExport.AddAttribute( XML_NAMESPACE_TEXT, XML_DATABASE_NAME,
+ sDataBaseName );
+ SvXMLElementExport aDataBaseElement( GetExport(),
+ XML_NAMESPACE_TEXT, eElementName,
+ false, false );
+
+ // write URL as children
+ if( !sDataBaseURL.isEmpty() )
+ {
+ rExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, sDataBaseURL );
+ SvXMLElementExport aDataSourceElement(
+ GetExport(), XML_NAMESPACE_FORM, XML_CONNECTION_RESOURCE,
+ false, false );
+ }
+
+ // write presentation
+ rExport.Characters( sPresentation );
+}
+
+
+// explode a field master name into field type and field name
+void XMLTextFieldExport::ExplodeFieldMasterName(
+ std::u16string_view sMasterName, OUString& sFieldType, OUString& sVarName)
+{
+ sal_Int32 nLength = gsFieldMasterPrefix.getLength();
+ size_t nSeparator = sMasterName.find('.', nLength);
+
+ // '.' found?
+ if (nSeparator == o3tl::make_unsigned(nLength) || nSeparator == std::u16string_view::npos) {
+ SAL_WARN("xmloff.text", "no field var name!");
+ }
+ else
+ {
+ sFieldType = sMasterName.substr(nLength, nSeparator-nLength);
+ sVarName = sMasterName.substr(nSeparator+1);
+ }
+}
+
+
+// for XDependentTextFields, get PropertySet of FieldMaster
+Reference<XPropertySet> XMLTextFieldExport::GetMasterPropertySet(
+ const Reference<XTextField> & rTextField)
+{
+ // name, value => get Property set of TextFieldMaster
+ Reference<XDependentTextField> xDep(rTextField, UNO_QUERY);
+ return xDep->getTextFieldMaster();
+}
+
+// get PropertySet of (any; the first) dependent field
+bool XMLTextFieldExport::GetDependentFieldPropertySet(
+ const Reference<XPropertySet> & xMaster,
+ Reference<XPropertySet> & xField)
+{
+ Any aAny;
+ Sequence<Reference<XDependentTextField> > aFields;
+ aAny = xMaster->getPropertyValue(gsPropertyDependentTextFields);
+ aAny >>= aFields;
+
+ // any fields?
+ if (aFields.hasElements())
+ {
+ // get first one and return
+ Reference<XDependentTextField> xTField = aFields[0];
+ xField.set(xTField, UNO_QUERY);
+ DBG_ASSERT(xField.is(),
+ "Surprisingly, this TextField refuses to be a PropertySet!");
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
+/// map placeholder type
+enum XMLTokenEnum XMLTextFieldExport::MapPlaceholderType(sal_uInt16 nType)
+{
+ enum XMLTokenEnum eType = XML_TEXT;
+
+ switch (nType)
+ {
+ case PlaceholderType::TEXT:
+ eType = XML_TEXT;
+ break;
+
+ case PlaceholderType::TABLE:
+ eType = XML_TABLE;
+ break;
+
+ case PlaceholderType::TEXTFRAME:
+ eType = XML_TEXT_BOX;
+ break;
+
+ case PlaceholderType::GRAPHIC:
+ eType = XML_IMAGE;
+ break;
+
+ case PlaceholderType::OBJECT:
+ eType = XML_OBJECT;
+ break;
+
+ default:
+ // unknown placeholder: XML_TEXT
+ OSL_FAIL("unknown placeholder type");
+ }
+
+ return eType;
+}
+
+
+/// element name for author fields
+enum XMLTokenEnum XMLTextFieldExport::MapAuthorFieldName(
+ const Reference<XPropertySet> & xPropSet)
+{
+ // Initials or full name?
+ return GetBoolProperty(gsPropertyFullName, xPropSet)
+ ? XML_AUTHOR_NAME : XML_AUTHOR_INITIALS;
+}
+
+enum XMLTokenEnum XMLTextFieldExport::MapPageNumberName(
+ const Reference<XPropertySet> & xPropSet,
+ sal_Int32& nOffset)
+{
+ enum XMLTokenEnum eName = XML_TOKEN_INVALID;
+ PageNumberType ePage;
+ Any aAny = xPropSet->getPropertyValue(gsPropertySubType);
+ ePage = *o3tl::doAccess<PageNumberType>(aAny);
+
+ switch (ePage)
+ {
+ case PageNumberType_PREV:
+ eName = XML_PREVIOUS;
+ nOffset += 1;
+ break;
+ case PageNumberType_CURRENT:
+ eName = XML_CURRENT;
+ break;
+ case PageNumberType_NEXT:
+ eName = XML_NEXT;
+ nOffset -= 1;
+ break;
+ default:
+ OSL_FAIL("unknown page number type");
+ eName = XML_TOKEN_INVALID;
+ break;
+ }
+
+ return eName;
+}
+
+/// map TemplateDisplayFormat to XML
+enum XMLTokenEnum XMLTextFieldExport::MapTemplateDisplayFormat(sal_Int16 nFormat)
+{
+ enum XMLTokenEnum eName = XML_TOKEN_INVALID;
+
+ switch (nFormat)
+ {
+ case TemplateDisplayFormat::FULL:
+ eName = XML_FULL;
+ break;
+ case TemplateDisplayFormat::PATH:
+ eName = XML_PATH;
+ break;
+ case TemplateDisplayFormat::NAME:
+ eName = XML_NAME;
+ break;
+ case TemplateDisplayFormat::NAME_AND_EXT:
+ eName = XML_NAME_AND_EXTENSION;
+ break;
+ case TemplateDisplayFormat::AREA:
+ eName = XML_AREA;
+ break;
+ case TemplateDisplayFormat::TITLE:
+ eName = XML_TITLE;
+ break;
+ default:
+ OSL_FAIL("unknown template display format");
+ eName = XML_TOKEN_INVALID;
+ break;
+ }
+
+ return eName;
+}
+
+/// map count/statistics field token to XML name
+enum XMLTokenEnum XMLTextFieldExport::MapCountFieldName(FieldIdEnum nToken)
+{
+ enum XMLTokenEnum eElement = XML_TOKEN_INVALID;
+
+ switch (nToken)
+ {
+ case FIELD_ID_COUNT_PAGES:
+ eElement = XML_PAGE_COUNT;
+ break;
+ case FIELD_ID_COUNT_PARAGRAPHS:
+ eElement = XML_PARAGRAPH_COUNT;
+ break;
+ case FIELD_ID_COUNT_WORDS:
+ eElement = XML_WORD_COUNT;
+ break;
+ case FIELD_ID_COUNT_CHARACTERS:
+ eElement = XML_CHARACTER_COUNT;
+ break;
+ case FIELD_ID_COUNT_TABLES:
+ eElement = XML_TABLE_COUNT;
+ break;
+ case FIELD_ID_COUNT_GRAPHICS:
+ eElement = XML_IMAGE_COUNT;
+ break;
+ case FIELD_ID_COUNT_OBJECTS:
+ eElement = XML_OBJECT_COUNT;
+ break;
+ default:
+ OSL_FAIL("no count field token");
+ eElement = XML_TOKEN_INVALID;
+ break;
+ }
+
+ return eElement;
+}
+
+/// map ChapterDisplayFormat to XML string
+enum XMLTokenEnum XMLTextFieldExport::MapChapterDisplayFormat(sal_Int16 nFormat)
+{
+ enum XMLTokenEnum eName = XML_TOKEN_INVALID;
+
+ switch (nFormat)
+ {
+ case ChapterFormat::NAME:
+ eName = XML_NAME;
+ break;
+ case ChapterFormat::NUMBER:
+ eName = XML_NUMBER;
+ break;
+ case ChapterFormat::NAME_NUMBER:
+ eName = XML_NUMBER_AND_NAME;
+ break;
+ case ChapterFormat::NO_PREFIX_SUFFIX:
+ eName = XML_PLAIN_NUMBER_AND_NAME;
+ break;
+ case ChapterFormat::DIGIT:
+ eName = XML_PLAIN_NUMBER;
+ break;
+ default:
+ OSL_FAIL("unknown chapter display format");
+ eName = XML_TOKEN_INVALID;
+ break;
+ }
+
+ return eName;
+}
+
+
+/// map FilenameDisplayFormat to XML attribute names
+enum XMLTokenEnum XMLTextFieldExport::MapFilenameDisplayFormat(sal_Int16 nFormat)
+{
+ enum XMLTokenEnum eName = XML_TOKEN_INVALID;
+
+ switch (nFormat)
+ {
+ case FilenameDisplayFormat::FULL:
+ eName = XML_FULL;
+ break;
+ case FilenameDisplayFormat::PATH:
+ eName = XML_PATH;
+ break;
+ case FilenameDisplayFormat::NAME:
+ eName = XML_NAME;
+ break;
+ case FilenameDisplayFormat::NAME_AND_EXT:
+ eName = XML_NAME_AND_EXTENSION;
+ break;
+ default:
+ OSL_FAIL("unknown filename display format");
+ }
+
+ return eName;
+}
+
+
+/// map ReferenceFieldPart to XML string
+enum XMLTokenEnum XMLTextFieldExport::MapReferenceType(sal_Int16 nType)
+{
+ enum XMLTokenEnum eElement = XML_TOKEN_INVALID;
+
+ switch (nType)
+ {
+ case ReferenceFieldPart::PAGE:
+ eElement = XML_PAGE;
+ break;
+ case ReferenceFieldPart::CHAPTER:
+ eElement = XML_CHAPTER;
+ break;
+ case ReferenceFieldPart::TEXT:
+ eElement = XML_TEXT;
+ break;
+ case ReferenceFieldPart::UP_DOWN:
+ eElement = XML_DIRECTION;
+ break;
+ case ReferenceFieldPart::CATEGORY_AND_NUMBER:
+ eElement = XML_CATEGORY_AND_VALUE;
+ break;
+ case ReferenceFieldPart::ONLY_CAPTION:
+ eElement = XML_CAPTION;
+ break;
+ case ReferenceFieldPart::ONLY_SEQUENCE_NUMBER:
+ eElement = XML_VALUE;
+ break;
+ case ReferenceFieldPart::PAGE_DESC:
+ // small hack: this value never gets written, because
+ // XML_TEMPLATE is default
+ eElement = XML_TEMPLATE;
+ break;
+ // Core implementation for direct cross-references (#i81002#)
+ case ReferenceFieldPart::NUMBER:
+ eElement = XML_NUMBER;
+ break;
+ case ReferenceFieldPart::NUMBER_NO_CONTEXT:
+ eElement = XML_NUMBER_NO_SUPERIOR;
+ break;
+ case ReferenceFieldPart::NUMBER_FULL_CONTEXT:
+ eElement = XML_NUMBER_ALL_SUPERIOR;
+ break;
+ default:
+ OSL_FAIL("unknown reference type");
+ eElement = XML_TEMPLATE;
+ break;
+ }
+
+ return eElement;
+}
+
+/// map ReferenceFieldPart to XML string
+enum XMLTokenEnum XMLTextFieldExport::MapReferenceSource(sal_Int16 nType)
+{
+ enum XMLTokenEnum eElement = XML_TOKEN_INVALID;
+
+ switch (nType)
+ {
+ case ReferenceFieldSource::REFERENCE_MARK:
+ eElement = XML_REFERENCE_REF;
+ break;
+ case ReferenceFieldSource::SEQUENCE_FIELD:
+ eElement = XML_SEQUENCE_REF;
+ break;
+ case ReferenceFieldSource::BOOKMARK:
+ eElement = XML_BOOKMARK_REF;
+ break;
+ case ReferenceFieldSource::FOOTNOTE:
+ case ReferenceFieldSource::ENDNOTE:
+ eElement = XML_NOTE_REF;
+ break;
+ case ReferenceFieldSource::STYLE:
+ eElement = XML_STYLE_REF;
+ break;
+ default:
+ OSL_FAIL("unknown reference source");
+ break;
+ }
+
+ return eElement;
+}
+
+
+/// element name for sender fields
+enum XMLTokenEnum XMLTextFieldExport::MapSenderFieldName(
+ const Reference<XPropertySet> & xPropSet)
+{
+ enum XMLTokenEnum eName = XML_TOKEN_INVALID;
+
+ // sub-field type
+ switch (GetInt16Property(gsPropertyFieldSubType, xPropSet))
+ {
+ case UserDataPart::COMPANY :
+ eName = XML_SENDER_COMPANY;
+ break;
+ case UserDataPart::FIRSTNAME :
+ eName = XML_SENDER_FIRSTNAME;
+ break;
+ case UserDataPart::NAME :
+ eName = XML_SENDER_LASTNAME;
+ break;
+ case UserDataPart::SHORTCUT :
+ eName = XML_SENDER_INITIALS;
+ break;
+ case UserDataPart::STREET :
+ eName = XML_SENDER_STREET;
+ break;
+ case UserDataPart::COUNTRY :
+ eName = XML_SENDER_COUNTRY;
+ break;
+ case UserDataPart::ZIP :
+ eName = XML_SENDER_POSTAL_CODE;
+ break;
+ case UserDataPart::CITY :
+ eName = XML_SENDER_CITY;
+ break;
+ case UserDataPart::TITLE :
+ eName = XML_SENDER_TITLE;
+ break;
+ case UserDataPart::POSITION :
+ eName = XML_SENDER_POSITION;
+ break;
+ case UserDataPart::PHONE_PRIVATE :
+ eName = XML_SENDER_PHONE_PRIVATE;
+ break;
+ case UserDataPart::PHONE_COMPANY :
+ eName = XML_SENDER_PHONE_WORK;
+ break;
+ case UserDataPart::FAX :
+ eName = XML_SENDER_FAX;
+ break;
+ case UserDataPart::EMAIL :
+ eName = XML_SENDER_EMAIL;
+ break;
+ case UserDataPart::STATE :
+ eName = XML_SENDER_STATE_OR_PROVINCE;
+ break;
+ default:
+ SAL_WARN("xmloff.text", "unknown sender type");
+ eName = XML_TOKEN_INVALID;
+ break;
+ }
+
+ return eName;
+}
+
+enum XMLTokenEnum XMLTextFieldExport::MapDocInfoFieldName(
+ enum FieldIdEnum nToken)
+{
+ enum XMLTokenEnum eElement = XML_TOKEN_INVALID;
+
+ switch (nToken)
+ {
+ case FIELD_ID_DOCINFO_CREATION_AUTHOR:
+ eElement = XML_INITIAL_CREATOR;
+ break;
+ case FIELD_ID_DOCINFO_CREATION_DATE:
+ eElement = XML_CREATION_DATE;
+ break;
+ case FIELD_ID_DOCINFO_CREATION_TIME:
+ eElement = XML_CREATION_TIME;
+ break;
+ case FIELD_ID_DOCINFO_DESCRIPTION:
+ eElement = XML_DESCRIPTION;
+ break;
+ case FIELD_ID_DOCINFO_PRINT_TIME:
+ eElement = XML_PRINT_TIME;
+ break;
+ case FIELD_ID_DOCINFO_PRINT_DATE:
+ eElement = XML_PRINT_DATE;
+ break;
+ case FIELD_ID_DOCINFO_PRINT_AUTHOR:
+ eElement = XML_PRINTED_BY;
+ break;
+ case FIELD_ID_DOCINFO_TITLE:
+ eElement = XML_TITLE;
+ break;
+ case FIELD_ID_DOCINFO_SUBJECT:
+ eElement = XML_SUBJECT;
+ break;
+ case FIELD_ID_DOCINFO_KEYWORDS:
+ eElement = XML_KEYWORDS;
+ break;
+ case FIELD_ID_DOCINFO_REVISION:
+ eElement = XML_EDITING_CYCLES;
+ break;
+ case FIELD_ID_DOCINFO_EDIT_DURATION:
+ eElement = XML_EDITING_DURATION;
+ break;
+ case FIELD_ID_DOCINFO_SAVE_TIME:
+ eElement = XML_MODIFICATION_TIME;
+ break;
+ case FIELD_ID_DOCINFO_SAVE_DATE:
+ eElement = XML_MODIFICATION_DATE;
+ break;
+ case FIELD_ID_DOCINFO_SAVE_AUTHOR:
+ eElement = XML_CREATOR;
+ break;
+ default:
+ SAL_WARN("xmloff.text", "unknown docinfo field type!");
+ eElement = XML_TOKEN_INVALID;
+ break;
+ }
+
+ return eElement;
+}
+
+enum XMLTokenEnum XMLTextFieldExport::MapBibliographyFieldName(std::u16string_view sName)
+{
+ enum XMLTokenEnum eName = XML_TOKEN_INVALID;
+
+ if( sName == u"Identifier" )
+ {
+ eName = XML_IDENTIFIER;
+ }
+ else if( sName == u"BibiliographicType" )
+ {
+ eName = XML_BIBLIOGRAPHY_TYPE;
+ }
+ else if( sName == u"Address" )
+ {
+ eName = XML_ADDRESS;
+ }
+ else if( sName == u"Annote" )
+ {
+ eName = XML_ANNOTE;
+ }
+ else if( sName == u"Author" )
+ {
+ eName = XML_AUTHOR;
+ }
+ else if( sName == u"Booktitle" )
+ {
+ eName = XML_BOOKTITLE;
+ }
+ else if( sName == u"Chapter" )
+ {
+ eName = XML_CHAPTER;
+ }
+ else if( sName == u"Edition" )
+ {
+ eName = XML_EDITION;
+ }
+ else if( sName == u"Editor" )
+ {
+ eName = XML_EDITOR;
+ }
+ else if( sName == u"Howpublished" )
+ {
+ eName = XML_HOWPUBLISHED;
+ }
+ else if( sName == u"Institution" )
+ {
+ eName = XML_INSTITUTION;
+ }
+ else if( sName == u"Journal" )
+ {
+ eName = XML_JOURNAL;
+ }
+ else if( sName == u"Month" )
+ {
+ eName = XML_MONTH;
+ }
+ else if( sName == u"Note" )
+ {
+ eName = XML_NOTE;
+ }
+ else if( sName == u"Number" )
+ {
+ eName = XML_NUMBER;
+ }
+ else if( sName == u"Organizations" )
+ {
+ eName = XML_ORGANIZATIONS;
+ }
+ else if( sName == u"Pages" )
+ {
+ eName = XML_PAGES;
+ }
+ else if( sName == u"Publisher" )
+ {
+ eName = XML_PUBLISHER;
+ }
+ else if( sName == u"School" )
+ {
+ eName = XML_SCHOOL;
+ }
+ else if( sName == u"Series" )
+ {
+ eName = XML_SERIES;
+ }
+ else if( sName == u"Title" )
+ {
+ eName = XML_TITLE;
+ }
+ else if( sName == u"Report_Type" )
+ {
+ eName = XML_REPORT_TYPE;
+ }
+ else if( sName == u"Volume" )
+ {
+ eName = XML_VOLUME;
+ }
+ else if( sName == u"Year" )
+ {
+ eName = XML_YEAR;
+ }
+ else if( sName == u"URL" )
+ {
+ eName = XML_URL;
+ }
+ else if( sName == u"Custom1" )
+ {
+ eName = XML_CUSTOM1;
+ }
+ else if( sName == u"Custom2" )
+ {
+ eName = XML_CUSTOM2;
+ }
+ else if( sName == u"Custom3" )
+ {
+ eName = XML_CUSTOM3;
+ }
+ else if( sName == u"Custom4" )
+ {
+ eName = XML_CUSTOM4;
+ }
+ else if( sName == u"Custom5" )
+ {
+ eName = XML_CUSTOM5;
+ }
+ else if( sName == u"ISBN" )
+ {
+ eName = XML_ISBN;
+ }
+ else if (sName == u"LocalURL")
+ {
+ eName = XML_LOCAL_URL;
+ }
+ else if (sName == u"TargetType")
+ {
+ eName = XML_TARGET_TYPE;
+ }
+ else if (sName == u"TargetURL")
+ {
+ eName = XML_TARGET_URL;
+ }
+ else
+ {
+ SAL_WARN("xmloff.text", "Unknown bibliography info data");
+ eName = XML_TOKEN_INVALID;
+ }
+
+ return eName;
+}
+
+enum XMLTokenEnum XMLTextFieldExport::MapMeasureKind(sal_Int16 nKind)
+{
+ switch( nKind )
+ {
+ case 0:
+ return XML_VALUE;
+ case 1:
+ return XML_UNIT;
+ }
+ return XML_GAP;
+}
+
+OUString XMLTextFieldExport::MakeFootnoteRefName(
+ sal_Int16 nSeqNo)
+{
+ // generate foot-/endnote ID
+ return "ftn" + OUString::number(static_cast<sal_Int32>(nSeqNo));
+}
+
+OUString XMLTextFieldExport::MakeSequenceRefName(
+ sal_Int16 nSeqNo,
+ std::u16string_view rSeqName)
+{
+ // generate foot-/endnote ID
+ return OUString::Concat("ref") +rSeqName + OUString::number(static_cast<sal_Int32>(nSeqNo));
+}
+
+
+// Property accessor helper functions
+
+
+// to be relegated (does that word exist?) to a more appropriate place
+
+
+bool GetBoolProperty(
+ const OUString& sPropName,
+ const Reference<XPropertySet> & xPropSet)
+{
+ Any aAny = xPropSet->getPropertyValue(sPropName);
+ bool bBool = *o3tl::doAccess<bool>(aAny);
+ return bBool;
+}
+
+bool GetOptionalBoolProperty(
+ const OUString& sPropName,
+ const Reference<XPropertySet> & xPropSet,
+ const Reference<XPropertySetInfo> & xPropSetInfo,
+ bool bDefault)
+{
+ return xPropSetInfo->hasPropertyByName( sPropName )
+ ? GetBoolProperty( sPropName, xPropSet ) : bDefault;
+}
+
+double GetDoubleProperty(
+ const OUString& sPropName,
+ const Reference<XPropertySet> & xPropSet)
+{
+ Any aAny = xPropSet->getPropertyValue(sPropName);
+ double fDouble = 0.0;
+ aAny >>= fDouble;
+ return fDouble;
+}
+
+OUString GetStringProperty(
+ const OUString& sPropName,
+ const Reference<XPropertySet> & xPropSet)
+{
+ Any aAny = xPropSet->getPropertyValue(sPropName);
+ OUString sString;
+ aAny >>= sString;
+ return sString;
+}
+
+sal_Int32 GetIntProperty(
+ const OUString& sPropName,
+ const Reference<XPropertySet> & xPropSet)
+{
+ Any aAny = xPropSet->getPropertyValue(sPropName);
+ sal_Int32 nInt = 0;
+ aAny >>= nInt;
+ return nInt;
+}
+
+sal_Int16 GetInt16Property(
+ const OUString& sPropName,
+ const Reference<XPropertySet> & xPropSet)
+{
+ Any aAny = xPropSet->getPropertyValue(sPropName);
+ sal_Int16 nInt = 0;
+ aAny >>= nInt;
+ return nInt;
+}
+
+sal_Int8 GetInt8Property(
+ const OUString& sPropName,
+ const Reference<XPropertySet> & xPropSet)
+{
+ Any aAny = xPropSet->getPropertyValue(sPropName);
+ sal_Int8 nInt = 0;
+ aAny >>= nInt;
+ return nInt;
+}
+
+util::DateTime GetDateTimeProperty(
+ const OUString& sPropName,
+ const Reference<XPropertySet> & xPropSet)
+{
+ Any aAny = xPropSet->getPropertyValue(sPropName);
+ util::DateTime aTime;
+ aAny >>= aTime;
+ return aTime;
+}
+
+Sequence<OUString> GetStringSequenceProperty(
+ const OUString& sPropName,
+ const Reference<XPropertySet> & xPropSet)
+{
+ Any aAny = xPropSet->getPropertyValue(sPropName);
+ Sequence<OUString> aSequence;
+ aAny >>= aSequence;
+ return aSequence;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/txtfldi.cxx b/xmloff/source/text/txtfldi.cxx
new file mode 100644
index 0000000000..1228e232d3
--- /dev/null
+++ b/xmloff/source/text/txtfldi.cxx
@@ -0,0 +1,3661 @@
+/* -*- 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 .
+ */
+
+
+/** @#file
+ *
+ * Import of all text fields except those from txtvfldi.cxx
+ * (variable related text fields and database display fields)
+ */
+
+#include <o3tl/safeint.hxx>
+#include <sal/config.h>
+
+#include <cassert>
+
+#include <txtfldi.hxx>
+#include <txtvfldi.hxx>
+#include <utility>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/txtimp.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlement.hxx>
+#include <XMLStringBufferImportContext.hxx>
+#include <xmloff/XMLEventsImportContext.hxx>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/xml/sax/XAttributeList.hpp>
+#include <com/sun/star/text/UserDataPart.hpp>
+#include <com/sun/star/style/NumberingType.hpp>
+#include <com/sun/star/text/PlaceholderType.hpp>
+#include <com/sun/star/text/ReferenceFieldPart.hpp>
+#include <com/sun/star/text/ReferenceFieldSource.hpp>
+#include <com/sun/star/text/XTextContent.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/text/XTextFieldsSupplier.hpp>
+#include <com/sun/star/text/XDependentTextField.hpp>
+#include <com/sun/star/text/FilenameDisplayFormat.hpp>
+#include <com/sun/star/text/ChapterFormat.hpp>
+#include <com/sun/star/text/TemplateDisplayFormat.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/text/BibliographyDataType.hpp>
+#include <com/sun/star/util/XUpdatable.hpp>
+#include <com/sun/star/sdb/CommandType.hpp>
+#include <com/sun/star/container/XIndexReplace.hpp>
+
+#include <sax/tools/converter.hxx>
+
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <rtl/math.hxx>
+#include <tools/debug.hxx>
+#include <osl/diagnose.h>
+#include <comphelper/diagnose_ex.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::document;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::xml::sax;
+using namespace ::xmloff::token;
+
+
+// SO API string constants
+
+
+// service prefix and service names
+constexpr OUString sAPI_textfield_prefix = u"com.sun.star.text.TextField."_ustr;
+constexpr char16_t sAPI_fieldmaster_prefix[] = u"com.sun.star.text.FieldMaster.";
+constexpr OUString sAPI_presentation_prefix = u"com.sun.star.presentation.TextField."_ustr;
+
+constexpr OUString sAPI_date_time = u"DateTime"_ustr;
+constexpr OUString sAPI_page_number = u"PageNumber"_ustr;
+constexpr OUString sAPI_docinfo_change_date_time = u"DocInfo.ChangeDateTime"_ustr;
+constexpr OUString sAPI_docinfo_create_date_time = u"DocInfo.CreateDateTime"_ustr;
+constexpr OUString sAPI_docinfo_custom = u"DocInfo.Custom"_ustr;
+constexpr OUString sAPI_docinfo_print_date_time = u"DocInfo.PrintDateTime"_ustr;
+constexpr OUString sAPI_dde = u"DDE"_ustr;
+constexpr OUString sAPI_url = u"URL"_ustr;
+
+// property names
+constexpr OUString sAPI_is_fixed = u"IsFixed"_ustr;
+constexpr OUString sAPI_content = u"Content"_ustr;
+constexpr OUString sAPI_author = u"Author"_ustr;
+constexpr OUString sAPI_hint = u"Hint"_ustr;
+constexpr OUString sAPI_name = u"Name"_ustr;
+constexpr OUStringLiteral sAPI_parent_name = u"ParentName";
+constexpr OUString sAPI_sub_type = u"SubType"_ustr;
+constexpr OUString sAPI_date_time_value = u"DateTimeValue"_ustr;
+constexpr OUString sAPI_number_format = u"NumberFormat"_ustr;
+constexpr OUString sAPI_numbering_type = u"NumberingType"_ustr;
+constexpr OUString sAPI_offset = u"Offset"_ustr;
+constexpr OUString sAPI_condition = u"Condition"_ustr;
+constexpr OUString sAPI_set_number = u"SetNumber"_ustr;
+constexpr OUString sAPI_file_format = u"FileFormat"_ustr;
+constexpr OUString sAPI_is_date = u"IsDate"_ustr;
+constexpr OUString sAPI_current_presentation = u"CurrentPresentation"_ustr;
+constexpr OUString sAPI_is_hidden = u"IsHidden"_ustr;
+constexpr OUString sAPI_is_fixed_language = u"IsFixedLanguage"_ustr;
+
+constexpr OUString sAPI_true = u"TRUE"_ustr;
+
+
+XMLTextFieldImportContext::XMLTextFieldImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp,
+ OUString aService)
+: SvXMLImportContext( rImport )
+, sServiceName(std::move(aService))
+, rTextImportHelper(rHlp)
+, sServicePrefix(sAPI_textfield_prefix)
+, bValid(false)
+{
+}
+
+void XMLTextFieldImportContext::startFastElement(
+ sal_Int32 /*nElement*/,
+ const Reference<XFastAttributeList> & xAttrList)
+{
+ // process attributes
+ for( auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ) )
+ ProcessAttribute(aIter.getToken(), aIter.toView() );
+}
+
+OUString const & XMLTextFieldImportContext::GetContent()
+{
+ if (sContent.isEmpty())
+ {
+ sContent = sContentBuffer.makeStringAndClear();
+ }
+
+ return sContent;
+}
+
+void XMLTextFieldImportContext::endFastElement(sal_Int32 )
+{
+ if (bValid)
+ {
+
+ // create field/Service
+ Reference<XPropertySet> xPropSet;
+ if (CreateField(xPropSet, sServicePrefix + GetServiceName()))
+ {
+ // set field properties
+ PrepareField(xPropSet);
+
+ // attach field to document
+ Reference<XTextContent> xTextContent(xPropSet, UNO_QUERY);
+
+ // workaround for #80606#
+ try
+ {
+ rTextImportHelper.InsertTextContent(xTextContent);
+ }
+ catch (const lang::IllegalArgumentException&)
+ {
+ // ignore
+ }
+ return;
+ }
+ }
+
+ // in case of error: write element content
+ rTextImportHelper.InsertString(GetContent());
+}
+
+void XMLTextFieldImportContext::characters(const OUString& rContent)
+{
+ sContentBuffer.append(rContent);
+}
+
+bool XMLTextFieldImportContext::CreateField(
+ Reference<XPropertySet> & xField,
+ const OUString& rServiceName)
+{
+ // instantiate new XTextField:
+ // ask import for model, model is factory, ask factory to create service
+
+ Reference<XMultiServiceFactory> xFactory(GetImport().GetModel(),UNO_QUERY);
+ if( xFactory.is() )
+ {
+ Reference<XInterface> xIfc = xFactory->createInstance(rServiceName);
+ if( xIfc.is() )
+ {
+ Reference<XPropertySet> xTmp( xIfc, UNO_QUERY );
+
+ xField = xTmp;
+ } else {
+ return false; // can't create instance
+ }
+ } else {
+ return false; // can't get MultiServiceFactory
+ }
+
+ return true;
+}
+
+/// create the appropriate field context from
+XMLTextFieldImportContext*
+XMLTextFieldImportContext::CreateTextFieldImportContext(
+ SvXMLImport& rImport,
+ XMLTextImportHelper& rHlp,
+ sal_Int32 nToken)
+{
+ XMLTextFieldImportContext* pContext = nullptr;
+
+ switch (nToken)
+ {
+ case XML_ELEMENT(TEXT, XML_SENDER_FIRSTNAME):
+ case XML_ELEMENT(TEXT, XML_SENDER_LASTNAME):
+ case XML_ELEMENT(LO_EXT, XML_SENDER_INITIALS):
+ case XML_ELEMENT(TEXT, XML_SENDER_INITIALS):
+ case XML_ELEMENT(TEXT, XML_SENDER_TITLE):
+ case XML_ELEMENT(TEXT, XML_SENDER_POSITION):
+ case XML_ELEMENT(TEXT, XML_SENDER_EMAIL):
+ case XML_ELEMENT(TEXT, XML_SENDER_PHONE_PRIVATE):
+
+ case XML_ELEMENT(TEXT, XML_SENDER_FAX):
+ case XML_ELEMENT(TEXT, XML_SENDER_COMPANY):
+ case XML_ELEMENT(TEXT, XML_SENDER_PHONE_WORK):
+ case XML_ELEMENT(TEXT, XML_SENDER_STREET):
+ case XML_ELEMENT(TEXT, XML_SENDER_CITY):
+ case XML_ELEMENT(TEXT, XML_SENDER_POSTAL_CODE):
+ case XML_ELEMENT(TEXT, XML_SENDER_COUNTRY):
+ case XML_ELEMENT(TEXT, XML_SENDER_STATE_OR_PROVINCE):
+ pContext =
+ new XMLSenderFieldImportContext( rImport, rHlp );
+ break;
+
+ case XML_ELEMENT(TEXT, XML_AUTHOR_NAME):
+ case XML_ELEMENT(TEXT, XML_AUTHOR_INITIALS):
+ pContext =
+ new XMLAuthorFieldImportContext( rImport, rHlp );
+ break;
+
+ case XML_ELEMENT(TEXT, XML_PLACEHOLDER):
+ pContext =
+ new XMLPlaceholderFieldImportContext( rImport, rHlp);
+ break;
+ case XML_ELEMENT(TEXT, XML_SEQUENCE):
+ pContext =
+ new XMLSequenceFieldImportContext( rImport, rHlp );
+ break;
+ case XML_ELEMENT(TEXT, XML_TEXT_INPUT):
+ pContext =
+ new XMLTextInputFieldImportContext( rImport, rHlp );
+ break;
+ case XML_ELEMENT(TEXT, XML_EXPRESSION):
+ pContext =
+ new XMLExpressionFieldImportContext( rImport, rHlp );
+ break;
+ case XML_ELEMENT(TEXT, XML_VARIABLE_SET):
+ pContext =
+ new XMLVariableSetFieldImportContext( rImport, rHlp );
+ break;
+ case XML_ELEMENT(TEXT, XML_VARIABLE_INPUT):
+ pContext =
+ new XMLVariableInputFieldImportContext( rImport, rHlp );
+ break;
+ case XML_ELEMENT(TEXT, XML_VARIABLE_GET):
+ pContext =
+ new XMLVariableGetFieldImportContext( rImport, rHlp );
+ break;
+ case XML_ELEMENT(TEXT, XML_USER_FIELD_GET):
+ pContext = new XMLUserFieldImportContext( rImport, rHlp );
+ break;
+ case XML_ELEMENT(TEXT, XML_USER_FIELD_INPUT):
+ pContext = new XMLUserFieldInputImportContext( rImport, rHlp );
+ break;
+ case XML_ELEMENT(TEXT, XML_TIME):
+ pContext = new XMLTimeFieldImportContext( rImport, rHlp );
+ break;
+ case XML_ELEMENT(TEXT, XML_PAGE_CONTINUATION_STRING):
+ case XML_ELEMENT(TEXT, XML_PAGE_CONTINUATION):
+ pContext = new XMLPageContinuationImportContext( rImport, rHlp );
+ break;
+
+ case XML_ELEMENT(TEXT, XML_PAGE_NUMBER):
+ pContext = new XMLPageNumberImportContext( rImport, rHlp );
+ break;
+
+ case XML_ELEMENT(TEXT, XML_DATE):
+ pContext = new XMLDateFieldImportContext( rImport, rHlp );
+ break;
+
+ case XML_ELEMENT(TEXT, XML_DATABASE_NAME):
+ pContext = new XMLDatabaseNameImportContext( rImport, rHlp );
+ break;
+ case XML_ELEMENT(TEXT, XML_DATABASE_NEXT):
+ pContext = new XMLDatabaseNextImportContext( rImport, rHlp );
+ break;
+ case XML_ELEMENT(TEXT, XML_DATABASE_ROW_SELECT):
+ pContext = new XMLDatabaseSelectImportContext( rImport, rHlp );
+ break;
+ case XML_ELEMENT(TEXT, XML_DATABASE_ROW_NUMBER):
+ pContext = new XMLDatabaseNumberImportContext( rImport, rHlp );
+ break;
+ case XML_ELEMENT(TEXT, XML_DATABASE_DISPLAY):
+ pContext = new XMLDatabaseDisplayImportContext( rImport, rHlp );
+ break;
+ case XML_ELEMENT(TEXT, XML_CONDITIONAL_TEXT):
+ pContext = new XMLConditionalTextImportContext( rImport, rHlp );
+ break;
+ case XML_ELEMENT(TEXT, XML_HIDDEN_TEXT):
+ pContext = new XMLHiddenTextImportContext( rImport, rHlp );
+ break;
+ case XML_ELEMENT(TEXT, XML_HIDDEN_PARAGRAPH):
+ pContext = new XMLHiddenParagraphImportContext( rImport, rHlp );
+ break;
+ case XML_ELEMENT(TEXT, XML_DESCRIPTION):
+ case XML_ELEMENT(TEXT, XML_TITLE):
+ case XML_ELEMENT(TEXT, XML_SUBJECT):
+ case XML_ELEMENT(TEXT, XML_KEYWORDS):
+ pContext = new XMLSimpleDocInfoImportContext( rImport, rHlp,
+ nToken, true,
+ false );
+ break;
+ case XML_ELEMENT(TEXT, XML_INITIAL_CREATOR):
+ case XML_ELEMENT(TEXT, XML_PRINTED_BY):
+ case XML_ELEMENT(TEXT, XML_CREATOR):
+ pContext = new XMLSimpleDocInfoImportContext( rImport, rHlp,
+ nToken, false,
+ true );
+ break;
+
+ case XML_ELEMENT(TEXT, XML_CREATION_DATE):
+ case XML_ELEMENT(TEXT, XML_CREATION_TIME):
+ case XML_ELEMENT(TEXT, XML_PRINT_DATE):
+ case XML_ELEMENT(TEXT, XML_PRINT_TIME):
+ case XML_ELEMENT(TEXT, XML_MODIFICATION_DATE):
+ case XML_ELEMENT(TEXT, XML_MODIFICATION_TIME):
+ case XML_ELEMENT(TEXT, XML_EDITING_DURATION):
+ pContext = new XMLDateTimeDocInfoImportContext( rImport, rHlp,
+ nToken );
+ break;
+
+ case XML_ELEMENT(TEXT, XML_EDITING_CYCLES):
+ pContext = new XMLRevisionDocInfoImportContext( rImport, rHlp,
+ nToken );
+ break;
+
+ case XML_ELEMENT(TEXT, XML_USER_DEFINED):
+ pContext = new XMLUserDocInfoImportContext( rImport, rHlp,
+ nToken );
+ break;
+
+ case XML_ELEMENT(TEXT, XML_FILE_NAME):
+ pContext = new XMLFileNameImportContext( rImport, rHlp );
+ break;
+
+ case XML_ELEMENT(TEXT, XML_CHAPTER):
+ pContext = new XMLChapterImportContext( rImport, rHlp );
+ break;
+
+ case XML_ELEMENT(TEXT, XML_TEMPLATE_NAME):
+ pContext = new XMLTemplateNameImportContext( rImport, rHlp );
+ break;
+
+ case XML_ELEMENT(TEXT, XML_WORD_COUNT):
+ case XML_ELEMENT(TEXT, XML_PARAGRAPH_COUNT):
+ case XML_ELEMENT(TEXT, XML_TABLE_COUNT):
+ case XML_ELEMENT(TEXT, XML_CHARACTER_COUNT):
+ case XML_ELEMENT(TEXT, XML_IMAGE_COUNT):
+ case XML_ELEMENT(TEXT, XML_OBJECT_COUNT):
+ case XML_ELEMENT(TEXT, XML_PAGE_COUNT):
+ pContext = new XMLCountFieldImportContext( rImport, rHlp, nToken);
+ break;
+
+ case XML_ELEMENT(TEXT, XML_PAGE_VARIABLE_GET):
+ pContext = new XMLPageVarGetFieldImportContext( rImport, rHlp );
+ break;
+
+ case XML_ELEMENT(TEXT, XML_PAGE_VARIABLE_SET):
+ pContext = new XMLPageVarSetFieldImportContext( rImport, rHlp );
+ break;
+
+ case XML_ELEMENT(TEXT, XML_EXECUTE_MACRO):
+ pContext = new XMLMacroFieldImportContext( rImport, rHlp );
+ break;
+
+ case XML_ELEMENT(TEXT, XML_DDE_CONNECTION):
+ pContext = new XMLDdeFieldImportContext( rImport, rHlp );
+ break;
+
+ case XML_ELEMENT(TEXT, XML_REFERENCE_REF):
+ case XML_ELEMENT(TEXT, XML_BOOKMARK_REF):
+ case XML_ELEMENT(TEXT, XML_NOTE_REF):
+ case XML_ELEMENT(TEXT, XML_SEQUENCE_REF):
+ case XML_ELEMENT(TEXT, XML_STYLE_REF):
+ case XML_ELEMENT(LO_EXT, XML_STYLE_REF):
+ pContext = new XMLReferenceFieldImportContext( rImport, rHlp, nToken );
+ break;
+
+ case XML_ELEMENT(TEXT, XML_SHEET_NAME):
+ pContext = new XMLSheetNameImportContext( rImport, rHlp );
+ break;
+
+ case XML_ELEMENT(TEXT, XML_PAGE_NAME):
+ case XML_ELEMENT(LO_EXT, XML_PAGE_NAME):
+ pContext = new XMLPageNameFieldImportContext( rImport, rHlp );
+ break;
+
+ case XML_ELEMENT(TEXT, XML_BIBLIOGRAPHY_MARK):
+ pContext = new XMLBibliographyFieldImportContext( rImport, rHlp );
+ break;
+
+ case XML_ELEMENT(OFFICE, XML_ANNOTATION):
+ case XML_ELEMENT(OFFICE, XML_ANNOTATION_END):
+ pContext = new XMLAnnotationImportContext( rImport, rHlp, nToken);
+ break;
+
+ case XML_ELEMENT(TEXT, XML_SCRIPT):
+ pContext = new XMLScriptImportContext( rImport, rHlp);
+ break;
+
+ case XML_ELEMENT(TEXT, XML_MEASURE):
+ pContext = new XMLMeasureFieldImportContext( rImport, rHlp );
+ break;
+
+ case XML_ELEMENT(TEXT, XML_TABLE_FORMULA):
+ pContext = new XMLTableFormulaImportContext( rImport, rHlp );
+ break;
+ case XML_ELEMENT(TEXT, XML_DROP_DOWN):
+ pContext = new XMLDropDownFieldImportContext( rImport, rHlp );
+ break;
+ case XML_ELEMENT(PRESENTATION, XML_HEADER):
+ pContext = new XMLHeaderFieldImportContext( rImport, rHlp );
+ break;
+ case XML_ELEMENT(PRESENTATION, XML_FOOTER):
+ pContext = new XMLFooterFieldImportContext( rImport, rHlp );
+ break;
+ case XML_ELEMENT(PRESENTATION, XML_DATE_TIME):
+ pContext = new XMLDateTimeFieldImportContext( rImport, rHlp );
+ break;
+
+ default:
+ // ignore! May not even be a textfield.
+ // (Reminder: This method is called inside default:-branch)
+ pContext = nullptr;
+ break;
+ }
+
+ return pContext;
+}
+
+
+void XMLTextFieldImportContext::ForceUpdate(
+ const Reference<XPropertySet> & rPropertySet)
+{
+ // force update
+ Reference<XUpdatable> xUpdate(rPropertySet, UNO_QUERY);
+ if (xUpdate.is())
+ {
+ xUpdate->update();
+ }
+ else
+ {
+ OSL_FAIL("Expected XUpdatable support!");
+ }
+}
+
+
+// XMLSenderFieldImportContext
+
+
+constexpr OUStringLiteral gsPropertyFieldSubType(u"UserDataType");
+
+XMLSenderFieldImportContext::XMLSenderFieldImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp)
+ : XMLTextFieldImportContext(rImport, rHlp, "ExtendedUser")
+ , nSubType(0)
+ , sPropertyFixed(sAPI_is_fixed)
+ , sPropertyContent(sAPI_content)
+ , bFixed(true)
+{
+}
+
+void XMLSenderFieldImportContext::startFastElement(
+ sal_Int32 nElement,
+ const Reference<XFastAttributeList> & xAttrList)
+{
+ bValid = true;
+ switch (nElement) {
+ case XML_ELEMENT(TEXT, XML_SENDER_FIRSTNAME):
+ nSubType = UserDataPart::FIRSTNAME;
+ break;
+ case XML_ELEMENT(TEXT, XML_SENDER_LASTNAME):
+ nSubType = UserDataPart::NAME;
+ break;
+ case XML_ELEMENT(LO_EXT, XML_SENDER_INITIALS):
+ case XML_ELEMENT(TEXT, XML_SENDER_INITIALS):
+ nSubType = UserDataPart::SHORTCUT;
+ break;
+ case XML_ELEMENT(TEXT, XML_SENDER_TITLE):
+ nSubType = UserDataPart::TITLE;
+ break;
+ case XML_ELEMENT(TEXT, XML_SENDER_POSITION):
+ nSubType = UserDataPart::POSITION;
+ break;
+ case XML_ELEMENT(TEXT, XML_SENDER_EMAIL):
+ nSubType = UserDataPart::EMAIL;
+ break;
+ case XML_ELEMENT(TEXT, XML_SENDER_PHONE_PRIVATE):
+ nSubType = UserDataPart::PHONE_PRIVATE;
+ break;
+ case XML_ELEMENT(TEXT, XML_SENDER_FAX):
+ nSubType = UserDataPart::FAX;
+ break;
+ case XML_ELEMENT(TEXT, XML_SENDER_COMPANY):
+ nSubType = UserDataPart::COMPANY;
+ break;
+ case XML_ELEMENT(TEXT, XML_SENDER_PHONE_WORK):
+ nSubType = UserDataPart::PHONE_COMPANY;
+ break;
+ case XML_ELEMENT(TEXT, XML_SENDER_STREET):
+ nSubType = UserDataPart::STREET;
+ break;
+ case XML_ELEMENT(TEXT, XML_SENDER_CITY):
+ nSubType = UserDataPart::CITY;
+ break;
+ case XML_ELEMENT(TEXT, XML_SENDER_POSTAL_CODE):
+ nSubType = UserDataPart::ZIP;
+ break;
+ case XML_ELEMENT(TEXT, XML_SENDER_COUNTRY):
+ nSubType = UserDataPart::COUNTRY;
+ break;
+ case XML_ELEMENT(TEXT, XML_SENDER_STATE_OR_PROVINCE):
+ nSubType = UserDataPart::STATE;
+ break;
+ default:
+ bValid = false;
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ break;
+ }
+
+ // process Attributes
+ XMLTextFieldImportContext::startFastElement(nElement, xAttrList);
+}
+
+void XMLSenderFieldImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue)
+{
+ if (XML_ELEMENT(TEXT, XML_FIXED) == nAttrToken) {
+
+ // set bVal
+ bool bVal(false);
+ bool const bRet = ::sax::Converter::convertBool(bVal, sAttrValue);
+
+ // set bFixed if successful
+ if (bRet) {
+ bFixed = bVal;
+ }
+ }
+ else
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+}
+
+void XMLSenderFieldImportContext::PrepareField(
+ const Reference<XPropertySet> & rPropSet)
+{
+ // set members
+ rPropSet->setPropertyValue(gsPropertyFieldSubType, Any(nSubType));
+
+ // set fixed
+ rPropSet->setPropertyValue(sPropertyFixed, Any(bFixed));
+
+ // set content if fixed
+ if (!bFixed)
+ return;
+
+ // in organizer or styles-only mode: force update
+ if (GetImport().GetTextImport()->IsOrganizerMode() ||
+ GetImport().GetTextImport()->IsStylesOnlyMode() )
+ {
+ ForceUpdate(rPropSet);
+ }
+ else
+ {
+ rPropSet->setPropertyValue(sPropertyContent, Any(GetContent()));
+ }
+}
+
+
+// XMLAuthorFieldImportContext
+
+constexpr OUStringLiteral gsPropertyAuthorFullName(u"FullName");
+
+XMLAuthorFieldImportContext::XMLAuthorFieldImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp)
+: XMLSenderFieldImportContext(rImport, rHlp)
+, bAuthorFullName(true)
+, sPropertyFixed(sAPI_is_fixed)
+, sPropertyContent(sAPI_content)
+{
+ // overwrite service name from XMLSenderFieldImportContext
+ SetServiceName(sAPI_author);
+}
+
+void XMLAuthorFieldImportContext::startFastElement(
+ sal_Int32 nElement,
+ const Reference<XFastAttributeList> & xAttrList)
+{
+ bAuthorFullName = ( XML_ELEMENT(TEXT, XML_AUTHOR_INITIALS) != nElement);
+ bValid = true;
+
+ // process Attributes
+ XMLTextFieldImportContext::startFastElement(nElement, xAttrList);
+}
+
+void XMLAuthorFieldImportContext::ProcessAttribute(sal_Int32 nAttrToken, std::string_view sAttrValue)
+{
+ if(nAttrToken == XML_ELEMENT(TEXT, XML_FIXED))
+ {
+ bool bTmp(false);
+ if (::sax::Converter::convertBool(bTmp, sAttrValue))
+ bFixed = bTmp;
+ }
+ else
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+}
+
+void XMLAuthorFieldImportContext::PrepareField(
+ const Reference<XPropertySet> & rPropSet)
+{
+ // set members
+ Any aAny;
+ rPropSet->setPropertyValue(gsPropertyAuthorFullName, Any(bAuthorFullName));
+
+ rPropSet->setPropertyValue(sPropertyFixed, Any(bFixed));
+
+ // set content if fixed
+ if (!bFixed)
+ return;
+
+ // organizer or styles-only mode: force update
+ if (GetImport().GetTextImport()->IsOrganizerMode() ||
+ GetImport().GetTextImport()->IsStylesOnlyMode() )
+ {
+ ForceUpdate(rPropSet);
+ }
+ else
+ {
+ aAny <<= GetContent();
+ rPropSet->setPropertyValue(sPropertyContent, aAny);
+ }
+}
+
+
+// page continuation string
+
+
+SvXMLEnumMapEntry<PageNumberType> const lcl_aSelectPageAttrMap[] =
+{
+ { XML_PREVIOUS, PageNumberType_PREV },
+ { XML_CURRENT, PageNumberType_CURRENT },
+ { XML_NEXT, PageNumberType_NEXT },
+ { XML_TOKEN_INVALID, PageNumberType(0) },
+};
+
+constexpr OUStringLiteral gsPropertyUserText(u"UserText");
+
+XMLPageContinuationImportContext::XMLPageContinuationImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp)
+: XMLTextFieldImportContext(rImport, rHlp, sAPI_page_number)
+, sPropertySubType(sAPI_sub_type)
+, sPropertyNumberingType(sAPI_numbering_type)
+, eSelectPage(PageNumberType_CURRENT)
+, sStringOK(false)
+{
+ bValid = true;
+}
+
+void XMLPageContinuationImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken, std::string_view sAttrValue )
+{
+ switch(nAttrToken)
+ {
+ case XML_ELEMENT(TEXT, XML_SELECT_PAGE):
+ {
+ PageNumberType nTmp;
+ if (SvXMLUnitConverter::convertEnum(nTmp, sAttrValue,
+ lcl_aSelectPageAttrMap)
+ && (PageNumberType_CURRENT != nTmp) )
+ {
+ eSelectPage = nTmp;
+ }
+ break;
+ }
+ case XML_ELEMENT(TEXT, XML_STRING_VALUE):
+ case XML_ELEMENT(OFFICE, XML_STRING_VALUE):
+ sString = OUString::fromUtf8(sAttrValue);
+ sStringOK = true;
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+ }
+}
+
+void XMLPageContinuationImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ Any aAny;
+
+ xPropertySet->setPropertyValue(sPropertySubType, Any(eSelectPage));
+
+ aAny <<= (sStringOK ? sString : GetContent());
+ xPropertySet->setPropertyValue(gsPropertyUserText, aAny);
+
+ aAny <<= style::NumberingType::CHAR_SPECIAL;
+ xPropertySet->setPropertyValue(sPropertyNumberingType, aAny);
+}
+
+
+// page number field
+
+
+XMLPageNumberImportContext::XMLPageNumberImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp)
+: XMLTextFieldImportContext(rImport, rHlp, sAPI_page_number)
+, sPropertySubType(sAPI_sub_type)
+, sPropertyNumberingType(sAPI_numbering_type)
+, sPropertyOffset(sAPI_offset)
+, sNumberSync(GetXMLToken(XML_FALSE))
+, nPageAdjust(0)
+, eSelectPage(PageNumberType_CURRENT)
+, sNumberFormatOK(false)
+{
+ bValid = true;
+}
+
+void XMLPageNumberImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ switch (nAttrToken)
+ {
+ case XML_ELEMENT(STYLE, XML_NUM_FORMAT):
+ sNumberFormat = OUString::fromUtf8(sAttrValue);
+ sNumberFormatOK = true;
+ break;
+ case XML_ELEMENT(STYLE, XML_NUM_LETTER_SYNC):
+ sNumberSync = OUString::fromUtf8(sAttrValue);
+ break;
+ case XML_ELEMENT(TEXT, XML_SELECT_PAGE):
+ SvXMLUnitConverter::convertEnum(eSelectPage, sAttrValue,
+ lcl_aSelectPageAttrMap);
+ break;
+ case XML_ELEMENT(TEXT, XML_PAGE_ADJUST):
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertNumber(nTmp, sAttrValue))
+ {
+ nPageAdjust = static_cast<sal_Int16>(nTmp);
+ }
+ break;
+ }
+ default:
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+ }
+}
+
+void XMLPageNumberImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ // all properties are optional
+ Reference<XPropertySetInfo> xPropertySetInfo(
+ xPropertySet->getPropertySetInfo());
+
+ if (xPropertySetInfo->hasPropertyByName(sPropertyNumberingType))
+ {
+ sal_Int16 nNumType;
+ if( sNumberFormatOK )
+ {
+ nNumType= style::NumberingType::ARABIC;
+ GetImport().GetMM100UnitConverter().convertNumFormat( nNumType,
+ sNumberFormat,
+ sNumberSync );
+ }
+ else
+ nNumType = style::NumberingType::PAGE_DESCRIPTOR;
+
+ xPropertySet->setPropertyValue(sPropertyNumberingType, Any(nNumType));
+ }
+
+ if (xPropertySetInfo->hasPropertyByName(sPropertyOffset))
+ {
+ // adjust offset
+ switch (eSelectPage)
+ {
+ case PageNumberType_PREV:
+ nPageAdjust--;
+ break;
+ case PageNumberType_CURRENT:
+ break;
+ case PageNumberType_NEXT:
+ nPageAdjust++;
+ break;
+ default:
+ SAL_WARN("xmloff.text", "unknown page number type");
+ }
+ xPropertySet->setPropertyValue(sPropertyOffset, Any(nPageAdjust));
+ }
+
+ if (xPropertySetInfo->hasPropertyByName(sPropertySubType))
+ {
+ xPropertySet->setPropertyValue(sPropertySubType, Any(eSelectPage));
+ }
+}
+
+
+// Placeholder
+
+
+constexpr OUStringLiteral gsPropertyPlaceholderType(u"PlaceHolderType");
+constexpr OUStringLiteral gsPropertyPlaceholder(u"PlaceHolder");
+
+XMLPlaceholderFieldImportContext::XMLPlaceholderFieldImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp)
+: XMLTextFieldImportContext(rImport, rHlp, "JumpEdit")
+, sPropertyHint(sAPI_hint)
+, nPlaceholderType(PlaceholderType::TEXT)
+{
+}
+
+/// process attribute values
+void XMLPlaceholderFieldImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken, std::string_view sAttrValue )
+{
+ switch (nAttrToken) {
+ case XML_ELEMENT(TEXT, XML_DESCRIPTION):
+ sDescription = OUString::fromUtf8(sAttrValue);
+ break;
+
+ case XML_ELEMENT(TEXT, XML_PLACEHOLDER_TYPE):
+ bValid = true;
+ if (IsXMLToken(sAttrValue, XML_TABLE))
+ {
+ nPlaceholderType = PlaceholderType::TABLE;
+ }
+ else if (IsXMLToken(sAttrValue, XML_TEXT))
+ {
+ nPlaceholderType = PlaceholderType::TEXT;
+ }
+ else if (IsXMLToken(sAttrValue, XML_TEXT_BOX))
+ {
+ nPlaceholderType = PlaceholderType::TEXTFRAME;
+ }
+ else if (IsXMLToken(sAttrValue, XML_IMAGE))
+ {
+ nPlaceholderType = PlaceholderType::GRAPHIC;
+ }
+ else if (IsXMLToken(sAttrValue, XML_OBJECT))
+ {
+ nPlaceholderType = PlaceholderType::OBJECT;
+ }
+ else
+ {
+ bValid = false;
+ }
+ break;
+
+ default:
+ // ignore
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+ }
+}
+
+void XMLPlaceholderFieldImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet) {
+
+ Any aAny;
+ xPropertySet->setPropertyValue(sPropertyHint, Any(sDescription));
+
+ // remove <...> around content (if present)
+ OUString aContent = GetContent();
+ sal_Int32 nStart = 0;
+ sal_Int32 nLength = aContent.getLength();
+ if (aContent.startsWith("<"))
+ {
+ --nLength;
+ ++nStart;
+ }
+ if (aContent.endsWith(">"))
+ {
+ --nLength;
+ }
+ aAny <<= aContent.copy(nStart, nLength);
+ xPropertySet->setPropertyValue(gsPropertyPlaceholder, aAny);
+
+ xPropertySet->setPropertyValue(gsPropertyPlaceholderType, Any(nPlaceholderType));
+}
+
+
+// time field
+
+constexpr OUString gsPropertyAdjust(u"Adjust"_ustr);
+
+XMLTimeFieldImportContext::XMLTimeFieldImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp)
+: XMLTextFieldImportContext(rImport, rHlp, sAPI_date_time)
+, sPropertyNumberFormat(sAPI_number_format)
+, sPropertyFixed(sAPI_is_fixed)
+, sPropertyDateTimeValue(sAPI_date_time_value)
+, sPropertyDateTime(sAPI_date_time)
+, sPropertyIsDate(sAPI_is_date)
+, sPropertyIsFixedLanguage(sAPI_is_fixed_language)
+, nAdjust(0)
+, nFormatKey(0)
+, bTimeOK(false)
+, bFormatOK(false)
+, bFixed(false)
+, bIsDate(false)
+, bIsDefaultLanguage( true )
+{
+ bValid = true; // always valid!
+}
+
+void XMLTimeFieldImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken, std::string_view sAttrValue )
+{
+ switch (nAttrToken)
+ {
+ case XML_ELEMENT(TEXT, XML_TIME_VALUE):
+ case XML_ELEMENT(OFFICE, XML_TIME_VALUE):
+ {
+ if (::sax::Converter::parseTimeOrDateTime(aDateTimeValue, sAttrValue))
+ {
+ bTimeOK = true;
+ }
+ break;
+ }
+ case XML_ELEMENT(TEXT, XML_FIXED):
+ {
+ bool bTmp(false);
+ if (::sax::Converter::convertBool(bTmp, sAttrValue))
+ {
+ bFixed = bTmp;
+ }
+ break;
+ }
+ case XML_ELEMENT(STYLE, XML_DATA_STYLE_NAME):
+ {
+ sal_Int32 nKey = GetImportHelper().GetDataStyleKey(
+ OUString::fromUtf8(sAttrValue), &bIsDefaultLanguage);
+ if (-1 != nKey)
+ {
+ nFormatKey = nKey;
+ bFormatOK = true;
+ }
+ break;
+ }
+ case XML_ELEMENT(TEXT, XML_TIME_ADJUST):
+ {
+ double fTmp;
+
+ if (::sax::Converter::convertDuration(fTmp, sAttrValue))
+ {
+ // convert to minutes
+ nAdjust = static_cast<sal_Int32>(::rtl::math::approxFloor(fTmp * 60 * 24));
+ }
+ break;
+ }
+ default:
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+ }
+}
+
+void XMLTimeFieldImportContext::PrepareField(
+ const Reference<XPropertySet> & rPropertySet)
+{
+ // all properties are optional (except IsDate)
+ Reference<XPropertySetInfo> xPropertySetInfo(
+ rPropertySet->getPropertySetInfo());
+
+ if (xPropertySetInfo->hasPropertyByName(sPropertyFixed))
+ {
+ rPropertySet->setPropertyValue(sPropertyFixed, Any(bFixed));
+ }
+
+ rPropertySet->setPropertyValue(sPropertyIsDate, Any(bIsDate));
+
+ if (xPropertySetInfo->hasPropertyByName(gsPropertyAdjust))
+ {
+ rPropertySet->setPropertyValue(gsPropertyAdjust, Any(nAdjust));
+ }
+
+ // set value
+ if (bFixed)
+ {
+ // organizer or styles-only mode: force update
+ if (GetImport().GetTextImport()->IsOrganizerMode() ||
+ GetImport().GetTextImport()->IsStylesOnlyMode() )
+ {
+ ForceUpdate(rPropertySet);
+ }
+ else
+ {
+ // normal mode: set value (if present)
+ if (bTimeOK)
+ {
+ if (xPropertySetInfo->hasPropertyByName(sPropertyDateTimeValue))
+ {
+ rPropertySet->setPropertyValue(sPropertyDateTimeValue, Any(aDateTimeValue));
+ }
+ else if (xPropertySetInfo->hasPropertyByName(sPropertyDateTime))
+ {
+ rPropertySet->setPropertyValue(sPropertyDateTime, Any(aDateTimeValue));
+ }
+ }
+ }
+ }
+
+ if (bFormatOK &&
+ xPropertySetInfo->hasPropertyByName(sPropertyNumberFormat))
+ {
+ rPropertySet->setPropertyValue(sPropertyNumberFormat, Any(nFormatKey));
+
+ if( xPropertySetInfo->hasPropertyByName( sPropertyIsFixedLanguage ) )
+ {
+ bool bIsFixedLanguage = ! bIsDefaultLanguage;
+ rPropertySet->setPropertyValue( sPropertyIsFixedLanguage, Any(bIsFixedLanguage) );
+ }
+ }
+}
+
+
+// date field
+
+
+XMLDateFieldImportContext::XMLDateFieldImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
+ XMLTimeFieldImportContext(rImport, rHlp)
+{
+ bIsDate = true; // always a date!
+}
+
+void XMLDateFieldImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ switch (nAttrToken)
+ {
+ case XML_ELEMENT(TEXT, XML_DATE_VALUE):
+ case XML_ELEMENT(OFFICE, XML_DATE_VALUE):
+ {
+ if (::sax::Converter::parseDateTime(aDateTimeValue, sAttrValue))
+ {
+ bTimeOK = true;
+ }
+ break;
+ }
+ case XML_ELEMENT(TEXT, XML_DATE_ADJUST):
+ // delegate to superclass, pretending it was a time-adjust attr.
+ XMLTimeFieldImportContext::ProcessAttribute(
+ XML_ELEMENT(TEXT, XML_TIME_ADJUST),
+ sAttrValue);
+ break;
+ case XML_ELEMENT(TEXT, XML_TIME_VALUE):
+ case XML_ELEMENT(OFFICE, XML_TIME_VALUE):
+ case XML_ELEMENT(TEXT, XML_TIME_ADJUST):
+ ; // ignore time-adjust and time-value attributes
+ break;
+ default:
+ // all others: delegate to super-class
+ return XMLTimeFieldImportContext::ProcessAttribute(nAttrToken,
+ sAttrValue);
+ break;
+ }
+}
+
+
+// database field superclass
+
+
+constexpr OUStringLiteral gsPropertyDataBaseName(u"DataBaseName");
+constexpr OUStringLiteral gsPropertyDataBaseURL(u"DataBaseURL");
+constexpr OUStringLiteral gsPropertyTableName(u"DataTableName");
+constexpr OUStringLiteral gsPropertyDataCommandType(u"DataCommandType");
+constexpr OUStringLiteral gsPropertyIsVisible(u"IsVisible");
+
+XMLDatabaseFieldImportContext::XMLDatabaseFieldImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp,
+ const OUString& pServiceName, bool bUseDisplay)
+: XMLTextFieldImportContext(rImport, rHlp, pServiceName)
+, m_nCommandType( sdb::CommandType::TABLE )
+, m_bCommandTypeOK(false)
+, m_bDisplay( true )
+, m_bDisplayOK( false )
+, m_bUseDisplay( bUseDisplay )
+, m_bDatabaseOK(false)
+, m_bDatabaseNameOK(false)
+, m_bDatabaseURLOK(false)
+, m_bTableOK(false)
+{
+}
+
+void XMLDatabaseFieldImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken, std::string_view sAttrValue )
+{
+ switch (nAttrToken)
+ {
+ case XML_ELEMENT(TEXT, XML_DATABASE_NAME):
+ m_sDatabaseName = OUString::fromUtf8(sAttrValue);
+ m_bDatabaseOK = true;
+ m_bDatabaseNameOK = true;
+ break;
+ case XML_ELEMENT(TEXT, XML_TABLE_NAME):
+ m_sTableName = OUString::fromUtf8(sAttrValue);
+ m_bTableOK = true;
+ break;
+ case XML_ELEMENT(TEXT, XML_TABLE_TYPE):
+ if( IsXMLToken( sAttrValue, XML_TABLE ) )
+ {
+ m_nCommandType = sdb::CommandType::TABLE;
+ m_bCommandTypeOK = true;
+ }
+ else if( IsXMLToken( sAttrValue, XML_QUERY ) )
+ {
+ m_nCommandType = sdb::CommandType::QUERY;
+ m_bCommandTypeOK = true;
+ }
+ else if( IsXMLToken( sAttrValue, XML_COMMAND ) )
+ {
+ m_nCommandType = sdb::CommandType::COMMAND;
+ m_bCommandTypeOK = true;
+ }
+ break;
+ case XML_ELEMENT(TEXT, XML_DISPLAY):
+ if( IsXMLToken( sAttrValue, XML_NONE ) )
+ {
+ m_bDisplay = false;
+ m_bDisplayOK = true;
+ }
+ else if( IsXMLToken( sAttrValue, XML_VALUE ) )
+ {
+ m_bDisplay = true;
+ m_bDisplayOK = true;
+ }
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+ }
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLDatabaseFieldImportContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ if (nElement == XML_ELEMENT(FORM, XML_CONNECTION_RESOURCE) )
+ {
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(XLINK, XML_HREF):
+ {
+ m_sDatabaseURL = aIter.toString();
+ m_bDatabaseOK = true;
+ m_bDatabaseURLOK = true;
+ }
+ break;
+ default:;
+ }
+ }
+
+ // we call ProcessAttribute in order to set bValid appropriately
+ ProcessAttribute( XML_TOKEN_INVALID, "" );
+ }
+ else
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+
+ return nullptr;
+}
+
+
+void XMLDatabaseFieldImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ xPropertySet->setPropertyValue(gsPropertyTableName, Any(m_sTableName));
+
+ if( m_bDatabaseNameOK )
+ {
+ xPropertySet->setPropertyValue(gsPropertyDataBaseName, Any(m_sDatabaseName));
+ }
+ else if( m_bDatabaseURLOK )
+ {
+ xPropertySet->setPropertyValue(gsPropertyDataBaseURL, Any(m_sDatabaseURL));
+ }
+
+ // #99980# load/save command type for all fields; also load
+ // old documents without command type
+ if( m_bCommandTypeOK )
+ {
+ xPropertySet->setPropertyValue( gsPropertyDataCommandType, Any(m_nCommandType) );
+ }
+
+ if( m_bUseDisplay && m_bDisplayOK )
+ {
+ xPropertySet->setPropertyValue( gsPropertyIsVisible, Any(m_bDisplay) );
+ }
+}
+
+
+// database name field
+
+
+XMLDatabaseNameImportContext::XMLDatabaseNameImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
+ XMLDatabaseFieldImportContext(rImport, rHlp, "DatabaseName", true)
+{
+}
+
+void XMLDatabaseNameImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken, std::string_view sAttrValue )
+{
+ // delegate to superclass and check for success
+ XMLDatabaseFieldImportContext::ProcessAttribute(nAttrToken, sAttrValue);
+ bValid = m_bDatabaseOK && m_bTableOK;
+}
+
+
+// database next field
+
+
+XMLDatabaseNextImportContext::XMLDatabaseNextImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp,
+ const OUString& pServiceName) :
+ XMLDatabaseFieldImportContext(rImport, rHlp, pServiceName, false),
+ sPropertyCondition(sAPI_condition),
+ sTrue(sAPI_true),
+ bConditionOK(false)
+{
+}
+
+XMLDatabaseNextImportContext::XMLDatabaseNextImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp)
+: XMLDatabaseFieldImportContext(rImport, rHlp, "DatabaseNextSet", false)
+, sPropertyCondition(sAPI_condition)
+, sTrue(sAPI_true)
+, bConditionOK(false)
+{
+}
+
+void XMLDatabaseNextImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken, std::string_view sAttrValue )
+{
+ if (XML_ELEMENT(TEXT, XML_CONDITION) == nAttrToken)
+ {
+ OUString sTmp;
+ sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrValueQName(
+ OUString::fromUtf8(sAttrValue), &sTmp );
+ if( XML_NAMESPACE_OOOW == nPrefix )
+ {
+ sCondition = sTmp;
+ bConditionOK = true;
+ }
+ else
+ sCondition = OUString::fromUtf8(sAttrValue);
+ }
+ else
+ {
+ XMLDatabaseFieldImportContext::ProcessAttribute(nAttrToken,
+ sAttrValue);
+ }
+
+ bValid = m_bDatabaseOK && m_bTableOK;
+}
+
+void XMLDatabaseNextImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ Any aAny;
+
+ aAny <<= bConditionOK ? sCondition : sTrue;
+ xPropertySet->setPropertyValue(sPropertyCondition, aAny);
+
+ XMLDatabaseFieldImportContext::PrepareField(xPropertySet);
+}
+
+
+// database select field
+
+
+XMLDatabaseSelectImportContext::XMLDatabaseSelectImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
+ XMLDatabaseNextImportContext(rImport, rHlp, "DatabaseNumberOfSet"),
+ sPropertySetNumber(sAPI_set_number),
+ nNumber(0),
+ bNumberOK(false)
+{
+}
+
+void XMLDatabaseSelectImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ if (XML_ELEMENT(TEXT, XML_ROW_NUMBER) == nAttrToken)
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertNumber( nTmp, sAttrValue
+ /* , nMin, nMax ??? */ ))
+ {
+ nNumber = nTmp;
+ bNumberOK = true;
+ }
+ }
+ else
+ {
+ XMLDatabaseNextImportContext::ProcessAttribute(nAttrToken, sAttrValue);
+ }
+
+ bValid = m_bTableOK && m_bDatabaseOK && bNumberOK;
+}
+
+void XMLDatabaseSelectImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ xPropertySet->setPropertyValue(sPropertySetNumber, Any(nNumber));
+
+ XMLDatabaseNextImportContext::PrepareField(xPropertySet);
+}
+
+
+// database display row number field
+
+
+XMLDatabaseNumberImportContext::XMLDatabaseNumberImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
+ XMLDatabaseFieldImportContext(rImport, rHlp, "DatabaseSetNumber", true),
+ sPropertyNumberingType(
+ sAPI_numbering_type),
+ sPropertySetNumber(sAPI_set_number),
+ sNumberFormat("1"),
+ sNumberSync(GetXMLToken(XML_FALSE)),
+ nValue(0),
+ bValueOK(false)
+{
+}
+
+void XMLDatabaseNumberImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ switch (nAttrToken)
+ {
+ case XML_ELEMENT(STYLE, XML_NUM_FORMAT):
+ sNumberFormat = OUString::fromUtf8(sAttrValue);
+ break;
+ case XML_ELEMENT(STYLE, XML_NUM_LETTER_SYNC):
+ sNumberSync = OUString::fromUtf8(sAttrValue);
+ break;
+ case XML_ELEMENT(TEXT, XML_VALUE_TYPE):
+ case XML_ELEMENT(OFFICE, XML_VALUE_TYPE):
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertNumber( nTmp, sAttrValue ))
+ {
+ nValue = nTmp;
+ bValueOK = true;
+ }
+ break;
+ }
+ default:
+ XMLDatabaseFieldImportContext::ProcessAttribute(nAttrToken,
+ sAttrValue);
+ break;
+ }
+
+ bValid = m_bTableOK && m_bDatabaseOK;
+}
+
+void XMLDatabaseNumberImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ sal_Int16 nNumType = style::NumberingType::ARABIC;
+ GetImport().GetMM100UnitConverter().convertNumFormat( nNumType,
+ sNumberFormat,
+ sNumberSync );
+ xPropertySet->setPropertyValue(sPropertyNumberingType, Any(nNumType));
+
+ if (bValueOK)
+ {
+ xPropertySet->setPropertyValue(sPropertySetNumber, Any(nValue));
+ }
+
+ XMLDatabaseFieldImportContext::PrepareField(xPropertySet);
+}
+
+
+// Simple doc info fields
+
+
+XMLSimpleDocInfoImportContext::XMLSimpleDocInfoImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp,
+ sal_Int32 nElementToken,
+ bool bContent, bool bAuthor)
+: XMLTextFieldImportContext(rImport, rHlp, MapTokenToServiceName(nElementToken) )
+, sPropertyFixed(sAPI_is_fixed)
+, sPropertyContent(sAPI_content)
+, sPropertyAuthor(sAPI_author)
+, sPropertyCurrentPresentation(sAPI_current_presentation)
+, bFixed(false)
+, bHasAuthor(bAuthor)
+, bHasContent(bContent)
+{
+ bValid = true;
+}
+
+void XMLSimpleDocInfoImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ if (XML_ELEMENT(TEXT, XML_FIXED) == nAttrToken)
+ {
+ bool bTmp(false);
+ if (::sax::Converter::convertBool(bTmp, sAttrValue))
+ {
+ bFixed = bTmp;
+ }
+ }
+ else
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+}
+
+void XMLSimpleDocInfoImportContext::PrepareField(
+ const Reference<XPropertySet> & rPropertySet)
+{
+ // title field in Calc has no Fixed property
+ Reference<XPropertySetInfo> xPropertySetInfo(rPropertySet->getPropertySetInfo());
+ if (!xPropertySetInfo->hasPropertyByName(sPropertyFixed))
+ return;
+
+ Any aAny;
+ rPropertySet->setPropertyValue(sPropertyFixed, Any(bFixed));
+
+ // set Content and CurrentPresentation (if fixed)
+ if (!bFixed)
+ return;
+
+ // in organizer-mode or styles-only-mode, only force update
+ if (GetImport().GetTextImport()->IsOrganizerMode() ||
+ GetImport().GetTextImport()->IsStylesOnlyMode() )
+ {
+ ForceUpdate(rPropertySet);
+ }
+ else
+ {
+ // set content (author, if that's the name) and current
+ // presentation
+ aAny <<= GetContent();
+
+ if (bFixed && bHasAuthor)
+ {
+ rPropertySet->setPropertyValue(sPropertyAuthor, aAny);
+ }
+
+ if (bFixed && bHasContent)
+ {
+ rPropertySet->setPropertyValue(sPropertyContent, aAny);
+ }
+
+ rPropertySet->setPropertyValue(sPropertyCurrentPresentation, aAny);
+ }
+}
+
+OUString XMLSimpleDocInfoImportContext::MapTokenToServiceName(
+ sal_Int32 nElementToken)
+{
+ OUString pServiceName;
+
+ switch(nElementToken)
+ {
+ case XML_ELEMENT(TEXT, XML_INITIAL_CREATOR):
+ pServiceName = "DocInfo.CreateAuthor";
+ break;
+ case XML_ELEMENT(TEXT, XML_CREATION_DATE):
+ pServiceName = sAPI_docinfo_create_date_time;
+ break;
+ case XML_ELEMENT(TEXT, XML_CREATION_TIME):
+ pServiceName = sAPI_docinfo_create_date_time;
+ break;
+ case XML_ELEMENT(TEXT, XML_DESCRIPTION):
+ pServiceName = "DocInfo.Description";
+ break;
+ case XML_ELEMENT(TEXT, XML_EDITING_DURATION):
+ pServiceName = "DocInfo.EditTime";
+ break;
+ case XML_ELEMENT(TEXT, XML_USER_DEFINED):
+ pServiceName = sAPI_docinfo_custom;
+ break;
+ case XML_ELEMENT(TEXT, XML_PRINTED_BY):
+ pServiceName = "DocInfo.PrintAuthor";
+ break;
+ case XML_ELEMENT(TEXT, XML_PRINT_DATE):
+ pServiceName = sAPI_docinfo_print_date_time;
+ break;
+ case XML_ELEMENT(TEXT, XML_PRINT_TIME):
+ pServiceName = sAPI_docinfo_print_date_time;
+ break;
+ case XML_ELEMENT(TEXT, XML_KEYWORDS):
+ pServiceName = "DocInfo.KeyWords";
+ break;
+ case XML_ELEMENT(TEXT, XML_SUBJECT):
+ pServiceName = "DocInfo.Subject";
+ break;
+ case XML_ELEMENT(TEXT, XML_EDITING_CYCLES):
+ pServiceName = "DocInfo.Revision";
+ break;
+ case XML_ELEMENT(TEXT, XML_CREATOR):
+ pServiceName = "DocInfo.ChangeAuthor";
+ break;
+ case XML_ELEMENT(TEXT, XML_MODIFICATION_DATE):
+ pServiceName = sAPI_docinfo_change_date_time;
+ break;
+ case XML_ELEMENT(TEXT, XML_MODIFICATION_TIME):
+ pServiceName = sAPI_docinfo_change_date_time;
+ break;
+ case XML_ELEMENT(TEXT, XML_TITLE):
+ pServiceName = "DocInfo.Title";
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElementToken);
+ assert(false);
+ }
+
+ return pServiceName;
+}
+
+
+// revision field
+
+constexpr OUStringLiteral sPropertyRevision(u"Revision");
+
+XMLRevisionDocInfoImportContext::XMLRevisionDocInfoImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp, sal_Int32 nElement) :
+ XMLSimpleDocInfoImportContext(rImport, rHlp, nElement, false, false)
+{
+ bValid = true;
+}
+
+void XMLRevisionDocInfoImportContext::PrepareField(
+ const Reference<XPropertySet> & rPropertySet)
+{
+ XMLSimpleDocInfoImportContext::PrepareField(rPropertySet);
+
+ // set revision number
+ // if fixed, if not in organizer-mode, if not in styles-only-mode
+ if (!bFixed)
+ return;
+
+ if ( GetImport().GetTextImport()->IsOrganizerMode() ||
+ GetImport().GetTextImport()->IsStylesOnlyMode() )
+ {
+ ForceUpdate(rPropertySet);
+ }
+ else
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertNumber(nTmp, GetContent()))
+ {
+ rPropertySet->setPropertyValue(sPropertyRevision, Any(nTmp));
+ }
+ }
+}
+
+
+// DocInfo fields with date/time attributes
+
+
+XMLDateTimeDocInfoImportContext::XMLDateTimeDocInfoImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp, sal_Int32 nElement)
+ : XMLSimpleDocInfoImportContext(rImport, rHlp, nElement, false, false)
+ , sPropertyNumberFormat(sAPI_number_format)
+ , sPropertyIsDate(sAPI_is_date)
+ , sPropertyIsFixedLanguage(sAPI_is_fixed_language)
+ , nFormat(0)
+ , bFormatOK(false)
+ , bIsDate(false)
+ , bHasDateTime(false)
+ , bIsDefaultLanguage(true)
+{
+ // we allow processing of EDIT_DURATION here, because import of actual
+ // is not supported anyway. If it was, we'd need an extra import class
+ // because times and time durations are presented differently!
+
+ bValid = true;
+ switch (nElement)
+ {
+ case XML_ELEMENT(TEXT, XML_CREATION_DATE):
+ case XML_ELEMENT(TEXT, XML_PRINT_DATE):
+ case XML_ELEMENT(TEXT, XML_MODIFICATION_DATE):
+ bIsDate = true;
+ bHasDateTime = true;
+ break;
+ case XML_ELEMENT(TEXT, XML_CREATION_TIME):
+ case XML_ELEMENT(TEXT, XML_PRINT_TIME):
+ case XML_ELEMENT(TEXT, XML_MODIFICATION_TIME):
+ bIsDate = false;
+ bHasDateTime = true;
+ break;
+ case XML_ELEMENT(TEXT, XML_EDITING_DURATION):
+ bIsDate = false;
+ bHasDateTime = false;
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ OSL_FAIL("XMLDateTimeDocInfoImportContext needs date/time doc. fields");
+ bValid = false;
+ break;
+ }
+}
+
+void XMLDateTimeDocInfoImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ switch (nAttrToken)
+ {
+ case XML_ELEMENT(STYLE, XML_DATA_STYLE_NAME):
+ {
+ sal_Int32 nKey = GetImportHelper().GetDataStyleKey(
+ OUString::fromUtf8(sAttrValue), &bIsDefaultLanguage);
+ if (-1 != nKey)
+ {
+ nFormat = nKey;
+ bFormatOK = true;
+ }
+ break;
+ }
+ case XML_ELEMENT(TEXT, XML_FIXED):
+ XMLSimpleDocInfoImportContext::ProcessAttribute(nAttrToken,
+ sAttrValue);
+ break;
+ default:
+ // ignore -> we can't set date/time value anyway!
+ break;
+ }
+}
+
+void XMLDateTimeDocInfoImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ // process fixed and presentation
+ XMLSimpleDocInfoImportContext::PrepareField(xPropertySet);
+
+ if (bHasDateTime)
+ {
+ xPropertySet->setPropertyValue(sPropertyIsDate, Any(bIsDate));
+ }
+
+ if (bFormatOK)
+ {
+ xPropertySet->setPropertyValue(sPropertyNumberFormat, Any(nFormat));
+
+ if( xPropertySet->getPropertySetInfo()->
+ hasPropertyByName( sPropertyIsFixedLanguage ) )
+ {
+ bool bIsFixedLanguage = ! bIsDefaultLanguage;
+ xPropertySet->setPropertyValue( sPropertyIsFixedLanguage, Any(bIsFixedLanguage) );
+ }
+ }
+
+ // can't set date/time/duration value! Sorry.
+}
+
+
+// user defined docinfo fields
+
+
+XMLUserDocInfoImportContext::XMLUserDocInfoImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp,
+ sal_Int32 nElement) :
+ XMLSimpleDocInfoImportContext(rImport, rHlp, nElement, false, false)
+ , sPropertyName(sAPI_name)
+ , sPropertyNumberFormat(sAPI_number_format)
+ , sPropertyIsFixedLanguage(sAPI_is_fixed_language)
+ , nFormat(0)
+ , bFormatOK(false)
+ , bIsDefaultLanguage( true )
+{
+ bValid = false;
+}
+
+void XMLUserDocInfoImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ switch (nAttrToken)
+ {
+ case XML_ELEMENT(STYLE, XML_DATA_STYLE_NAME):
+ {
+ sal_Int32 nKey = GetImportHelper().GetDataStyleKey(
+ OUString::fromUtf8(sAttrValue), &bIsDefaultLanguage);
+ if (-1 != nKey)
+ {
+ nFormat = nKey;
+ bFormatOK = true;
+ }
+ break;
+ }
+ case XML_ELEMENT(TEXT, XML_NAME):
+ {
+ if (!bValid)
+ {
+ SetServiceName(sAPI_docinfo_custom );
+ aName = OUString::fromUtf8(sAttrValue);
+ bValid = true;
+ }
+ break;
+ }
+
+ default:
+ XMLSimpleDocInfoImportContext::ProcessAttribute(nAttrToken,
+ sAttrValue);
+ break;
+ }
+}
+
+void XMLUserDocInfoImportContext::PrepareField(
+ const css::uno::Reference<css::beans::XPropertySet> & xPropertySet)
+{
+ if ( !aName.isEmpty() )
+ {
+ xPropertySet->setPropertyValue(sPropertyName, Any(aName));
+ }
+ Reference<XPropertySetInfo> xPropertySetInfo(
+ xPropertySet->getPropertySetInfo());
+ if (bFormatOK &&
+ xPropertySetInfo->hasPropertyByName(sPropertyNumberFormat))
+ {
+ xPropertySet->setPropertyValue(sPropertyNumberFormat, Any(nFormat));
+
+ if( xPropertySetInfo->hasPropertyByName( sPropertyIsFixedLanguage ) )
+ {
+ bool bIsFixedLanguage = ! bIsDefaultLanguage;
+ xPropertySet->setPropertyValue( sPropertyIsFixedLanguage, Any(bIsFixedLanguage) );
+ }
+ }
+
+ // call superclass to handle "fixed"
+ XMLSimpleDocInfoImportContext::PrepareField(xPropertySet);
+}
+
+
+// import hidden paragraph fields
+
+
+XMLHiddenParagraphImportContext::XMLHiddenParagraphImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
+ XMLTextFieldImportContext(rImport, rHlp, "HiddenParagraph"),
+ sPropertyCondition(sAPI_condition),
+ sPropertyIsHidden(sAPI_is_hidden),
+ bIsHidden(false)
+{
+}
+
+void XMLHiddenParagraphImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ if ( XML_ELEMENT(TEXT, XML_CONDITION) == nAttrToken)
+ {
+ OUString sTmp;
+ sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrValueQName(
+ OUString::fromUtf8(sAttrValue), &sTmp );
+ if( XML_NAMESPACE_OOOW == nPrefix )
+ {
+ sCondition = sTmp;
+ bValid = true;
+ }
+ else
+ sCondition = OUString::fromUtf8(sAttrValue);
+ }
+ else if ( XML_ELEMENT(TEXT, XML_IS_HIDDEN) == nAttrToken)
+ {
+ bool bTmp(false);
+ if (::sax::Converter::convertBool(bTmp, sAttrValue))
+ {
+ bIsHidden = bTmp;
+ }
+ }
+ else
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+}
+
+void XMLHiddenParagraphImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ xPropertySet->setPropertyValue(sPropertyCondition, Any(sCondition));
+ xPropertySet->setPropertyValue(sPropertyIsHidden, Any(bIsHidden));
+}
+
+
+// import conditional text (<text:conditional-text>)
+
+constexpr OUStringLiteral gsPropertyTrueContent(u"TrueContent");
+constexpr OUStringLiteral gsPropertyFalseContent(u"FalseContent");
+constexpr OUStringLiteral gsPropertyIsConditionTrue(u"IsConditionTrue");
+
+XMLConditionalTextImportContext::XMLConditionalTextImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
+ XMLTextFieldImportContext(rImport, rHlp, "ConditionalText"),
+ sPropertyCondition(sAPI_condition),
+ sPropertyCurrentPresentation(sAPI_current_presentation),
+ bConditionOK(false),
+ bTrueOK(false),
+ bFalseOK(false),
+ bCurrentValue(false)
+{
+}
+
+void XMLConditionalTextImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ switch (nAttrToken)
+ {
+ case XML_ELEMENT(TEXT, XML_CONDITION):
+ {
+ OUString sTmp;
+ sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
+ GetKeyByAttrValueQName(OUString::fromUtf8(sAttrValue), &sTmp);
+ if( XML_NAMESPACE_OOOW == nPrefix )
+ {
+ sCondition = sTmp;
+ bConditionOK = true;
+ }
+ else
+ sCondition = OUString::fromUtf8(sAttrValue);
+ }
+ break;
+ case XML_ELEMENT(TEXT, XML_STRING_VALUE_IF_FALSE):
+ sFalseContent = OUString::fromUtf8(sAttrValue);
+ bFalseOK = true;
+ break;
+ case XML_ELEMENT(TEXT, XML_STRING_VALUE_IF_TRUE):
+ sTrueContent = OUString::fromUtf8(sAttrValue);
+ bTrueOK = true;
+ break;
+ case XML_ELEMENT(TEXT, XML_CURRENT_VALUE):
+ {
+ bool bTmp(false);
+ if (::sax::Converter::convertBool(bTmp, sAttrValue))
+ {
+ bCurrentValue = bTmp;
+ }
+ break;
+ }
+ default:
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+ }
+
+ bValid = bConditionOK && bFalseOK && bTrueOK;
+}
+
+void XMLConditionalTextImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ xPropertySet->setPropertyValue(sPropertyCondition, Any(sCondition));
+ xPropertySet->setPropertyValue(gsPropertyFalseContent, Any(sFalseContent));
+ xPropertySet->setPropertyValue(gsPropertyTrueContent, Any(sTrueContent));
+ xPropertySet->setPropertyValue(gsPropertyIsConditionTrue, Any(bCurrentValue));
+ xPropertySet->setPropertyValue(sPropertyCurrentPresentation, Any(GetContent()));
+}
+
+
+// hidden text
+
+
+XMLHiddenTextImportContext::XMLHiddenTextImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
+ XMLTextFieldImportContext(rImport, rHlp, "HiddenText"),
+ sPropertyCondition(sAPI_condition),
+ sPropertyContent(sAPI_content),
+ sPropertyIsHidden(sAPI_is_hidden),
+ bConditionOK(false),
+ bStringOK(false),
+ bIsHidden(false)
+{
+}
+
+void XMLHiddenTextImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ switch (nAttrToken)
+ {
+ case XML_ELEMENT(TEXT, XML_CONDITION):
+ {
+ OUString sTmp;
+ sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
+ GetKeyByAttrValueQName(OUString::fromUtf8(sAttrValue), &sTmp);
+ if( XML_NAMESPACE_OOOW == nPrefix )
+ {
+ sCondition = sTmp;
+ bConditionOK = true;
+ }
+ else
+ sCondition = OUString::fromUtf8(sAttrValue);
+ }
+ break;
+ case XML_ELEMENT(TEXT, XML_STRING_VALUE):
+ case XML_ELEMENT(OFFICE, XML_STRING_VALUE):
+ sString = OUString::fromUtf8(sAttrValue);
+ bStringOK = true;
+ break;
+ case XML_ELEMENT(TEXT, XML_IS_HIDDEN):
+ {
+ bool bTmp(false);
+ if (::sax::Converter::convertBool(bTmp, sAttrValue))
+ {
+ bIsHidden = bTmp;
+ }
+ break;
+ }
+ default:
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+ }
+
+ bValid = bConditionOK && bStringOK;
+}
+
+void XMLHiddenTextImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ xPropertySet->setPropertyValue(sPropertyCondition, Any(sCondition));
+ xPropertySet->setPropertyValue(sPropertyContent, Any(sString));
+ xPropertySet->setPropertyValue(sPropertyIsHidden, Any(bIsHidden));
+}
+
+
+// file name fields
+
+
+const SvXMLEnumMapEntry<sal_uInt16> aFilenameDisplayMap[] =
+{
+ { XML_PATH, FilenameDisplayFormat::PATH },
+ { XML_NAME, FilenameDisplayFormat::NAME },
+ { XML_NAME_AND_EXTENSION, FilenameDisplayFormat::NAME_AND_EXT },
+ { XML_FULL, FilenameDisplayFormat::FULL },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+XMLFileNameImportContext::XMLFileNameImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
+ XMLTextFieldImportContext(rImport, rHlp, "FileName"),
+ sPropertyFixed(sAPI_is_fixed),
+ sPropertyFileFormat(sAPI_file_format),
+ sPropertyCurrentPresentation(
+ sAPI_current_presentation),
+ nFormat(FilenameDisplayFormat::FULL),
+ bFixed(false)
+{
+ bValid = true;
+}
+
+void XMLFileNameImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ switch (nAttrToken)
+ {
+ case XML_ELEMENT(TEXT, XML_FIXED):
+ {
+ bool bTmp(false);
+ if (::sax::Converter::convertBool(bTmp, sAttrValue))
+ {
+ bFixed = bTmp;
+ }
+ break;
+ }
+ case XML_ELEMENT(TEXT, XML_DISPLAY):
+ {
+ sal_uInt16 nTmp;
+ if (SvXMLUnitConverter::convertEnum(nTmp, sAttrValue,
+ aFilenameDisplayMap))
+ {
+ nFormat = nTmp;
+ }
+ break;
+ }
+ default:
+ // unknown attribute: ignore
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+ break;
+ }
+}
+
+void XMLFileNameImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ // properties are optional
+ Reference<XPropertySetInfo> xPropertySetInfo(
+ xPropertySet->getPropertySetInfo());
+
+ if (xPropertySetInfo->hasPropertyByName(sPropertyFixed))
+ {
+ xPropertySet->setPropertyValue(sPropertyFixed, Any(bFixed));
+ }
+
+ if (xPropertySetInfo->hasPropertyByName(sPropertyFileFormat))
+ {
+ xPropertySet->setPropertyValue(sPropertyFileFormat, Any(nFormat));
+ }
+
+ if (xPropertySetInfo->hasPropertyByName(sPropertyCurrentPresentation))
+ {
+ xPropertySet->setPropertyValue(sPropertyCurrentPresentation, Any(GetContent()));
+ }
+}
+
+
+// template name field
+
+
+const SvXMLEnumMapEntry<sal_uInt16> aTemplateDisplayMap[] =
+{
+ { XML_FULL, TemplateDisplayFormat::FULL },
+ { XML_PATH, TemplateDisplayFormat::PATH },
+ { XML_NAME, TemplateDisplayFormat::NAME },
+ { XML_NAME_AND_EXTENSION, TemplateDisplayFormat::NAME_AND_EXT },
+ { XML_AREA, TemplateDisplayFormat::AREA },
+ { XML_TITLE, TemplateDisplayFormat::TITLE },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+
+XMLTemplateNameImportContext::XMLTemplateNameImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
+ XMLTextFieldImportContext(rImport, rHlp, "TemplateName"),
+ sPropertyFileFormat(sAPI_file_format),
+ nFormat(TemplateDisplayFormat::FULL)
+{
+ bValid = true;
+}
+
+void XMLTemplateNameImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ switch (nAttrToken)
+ {
+ case XML_ELEMENT(TEXT, XML_DISPLAY):
+ {
+ sal_uInt16 nTmp;
+ if (SvXMLUnitConverter::convertEnum(nTmp, sAttrValue,
+ aTemplateDisplayMap))
+ {
+ nFormat = nTmp;
+ }
+ break;
+ }
+ default:
+ // unknown attribute: ignore
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+ break;
+ }
+}
+
+void XMLTemplateNameImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ xPropertySet->setPropertyValue(sPropertyFileFormat, Any(nFormat));
+}
+
+
+// import chapter fields
+
+
+const SvXMLEnumMapEntry<sal_uInt16> aChapterDisplayMap[] =
+{
+ { XML_NAME, ChapterFormat::NAME },
+ { XML_NUMBER, ChapterFormat::NUMBER },
+ { XML_NUMBER_AND_NAME, ChapterFormat::NAME_NUMBER },
+ { XML_PLAIN_NUMBER_AND_NAME, ChapterFormat::NO_PREFIX_SUFFIX },
+ { XML_PLAIN_NUMBER, ChapterFormat::DIGIT },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+constexpr OUStringLiteral gsPropertyChapterFormat(u"ChapterFormat");
+constexpr OUStringLiteral gsPropertyLevel(u"Level");
+
+XMLChapterImportContext::XMLChapterImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
+ XMLTextFieldImportContext(rImport, rHlp, "Chapter"),
+ nFormat(ChapterFormat::NAME_NUMBER),
+ nLevel(0)
+{
+ bValid = true;
+}
+
+void XMLChapterImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ switch (nAttrToken)
+ {
+ case XML_ELEMENT(TEXT, XML_DISPLAY):
+ {
+ sal_uInt16 nTmp;
+ if (SvXMLUnitConverter::convertEnum(nTmp, sAttrValue,
+ aChapterDisplayMap))
+ {
+ nFormat = static_cast<sal_Int16>(nTmp);
+ }
+ break;
+ }
+ case XML_ELEMENT(TEXT, XML_OUTLINE_LEVEL):
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertNumber(
+ nTmp, sAttrValue, 1,
+ GetImport().GetTextImport()->GetChapterNumbering()->getCount()
+ ))
+ {
+ // API numbers 0..9, we number 1..10
+ nLevel = static_cast<sal_Int8>(nTmp);
+ nLevel--;
+ }
+ break;
+ }
+ default:
+ // unknown attribute: ignore
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+ break;
+ }
+}
+
+void XMLChapterImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ xPropertySet->setPropertyValue(gsPropertyChapterFormat, Any(nFormat));
+ xPropertySet->setPropertyValue(gsPropertyLevel, Any(nLevel));
+}
+
+
+// counting fields
+
+
+XMLCountFieldImportContext::XMLCountFieldImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp,
+ sal_Int32 nElement) :
+ XMLTextFieldImportContext(rImport, rHlp, MapTokenToServiceName(nElement)),
+ sPropertyNumberingType(
+ sAPI_numbering_type),
+ bNumberFormatOK(false)
+{
+ bValid = true;
+}
+
+void XMLCountFieldImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ switch (nAttrToken)
+ {
+ case XML_ELEMENT(STYLE, XML_NUM_FORMAT):
+ sNumberFormat = OUString::fromUtf8(sAttrValue);
+ bNumberFormatOK = true;
+ break;
+ case XML_ELEMENT(STYLE, XML_NUM_LETTER_SYNC):
+ sLetterSync = OUString::fromUtf8(sAttrValue);
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+ }
+}
+
+void XMLCountFieldImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ // properties optional
+ // (only page count, but do for all to save common implementation)
+
+ if (!xPropertySet->getPropertySetInfo()->
+ hasPropertyByName(sPropertyNumberingType))
+ return;
+
+ sal_Int16 nNumType;
+ if( bNumberFormatOK )
+ {
+ nNumType= style::NumberingType::ARABIC;
+ GetImport().GetMM100UnitConverter().convertNumFormat( nNumType,
+ sNumberFormat,
+ sLetterSync );
+ }
+ else
+ nNumType = style::NumberingType::PAGE_DESCRIPTOR;
+ xPropertySet->setPropertyValue(sPropertyNumberingType, Any(nNumType));
+}
+
+OUString XMLCountFieldImportContext::MapTokenToServiceName(
+ sal_Int32 nElement)
+{
+ OUString pServiceName;
+
+ switch (nElement)
+ {
+ case XML_ELEMENT(TEXT, XML_WORD_COUNT):
+ pServiceName = "WordCount";
+ break;
+ case XML_ELEMENT(TEXT, XML_PARAGRAPH_COUNT):
+ pServiceName = "ParagraphCount";
+ break;
+ case XML_ELEMENT(TEXT, XML_TABLE_COUNT):
+ pServiceName = "TableCount";
+ break;
+ case XML_ELEMENT(TEXT, XML_CHARACTER_COUNT):
+ pServiceName = "CharacterCount";
+ break;
+ case XML_ELEMENT(TEXT, XML_IMAGE_COUNT):
+ pServiceName = "GraphicObjectCount";
+ break;
+ case XML_ELEMENT(TEXT, XML_OBJECT_COUNT):
+ pServiceName = "EmbeddedObjectCount";
+ break;
+ case XML_ELEMENT(TEXT, XML_PAGE_COUNT):
+ pServiceName = "PageCount";
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ assert(false);
+ }
+
+ return pServiceName;
+}
+
+
+// page variable import
+
+
+XMLPageVarGetFieldImportContext::XMLPageVarGetFieldImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
+ XMLTextFieldImportContext(rImport, rHlp, "ReferencePageGet"),
+ bNumberFormatOK(false)
+{
+ bValid = true;
+}
+
+void XMLPageVarGetFieldImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ switch (nAttrToken)
+ {
+ case XML_ELEMENT(STYLE, XML_NUM_FORMAT):
+ sNumberFormat = OUString::fromUtf8(sAttrValue);
+ bNumberFormatOK = true;
+ break;
+ case XML_ELEMENT(STYLE, XML_NUM_LETTER_SYNC):
+ sLetterSync = OUString::fromUtf8(sAttrValue);
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+ }
+}
+
+void XMLPageVarGetFieldImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ sal_Int16 nNumType;
+ if( bNumberFormatOK )
+ {
+ nNumType= style::NumberingType::ARABIC;
+ GetImport().GetMM100UnitConverter().convertNumFormat( nNumType,
+ sNumberFormat,
+ sLetterSync );
+ }
+ else
+ nNumType = style::NumberingType::PAGE_DESCRIPTOR;
+ xPropertySet->setPropertyValue(sAPI_numbering_type, Any(nNumType));
+
+ // display old content (#96657#)
+ xPropertySet->setPropertyValue( sAPI_current_presentation, Any(GetContent()) );
+}
+
+
+// page variable set fields
+
+
+XMLPageVarSetFieldImportContext::XMLPageVarSetFieldImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
+ XMLTextFieldImportContext(rImport, rHlp, "ReferencePageSet"),
+ nAdjust(0),
+ bActive(true)
+{
+ bValid = true;
+}
+
+void XMLPageVarSetFieldImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ switch (nAttrToken)
+ {
+ case XML_ELEMENT(TEXT, XML_ACTIVE):
+ {
+ bool bTmp(false);
+ if (::sax::Converter::convertBool(bTmp, sAttrValue))
+ {
+ bActive = bTmp;
+ }
+ break;
+ }
+ case XML_ELEMENT(TEXT, XML_PAGE_ADJUST):
+ {
+ sal_Int32 nTmp(0);
+ if (::sax::Converter::convertNumber(nTmp, sAttrValue))
+ {
+ nAdjust = static_cast<sal_Int16>(nTmp);
+ }
+ break;
+ }
+ default:
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+ break;
+ }
+}
+
+void XMLPageVarSetFieldImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ xPropertySet->setPropertyValue("On", Any(bActive));
+ xPropertySet->setPropertyValue(sAPI_offset, Any(nAdjust));
+}
+
+
+// macro fields
+
+
+XMLMacroFieldImportContext::XMLMacroFieldImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
+ XMLTextFieldImportContext(rImport, rHlp, "Macro"),
+ bDescriptionOK(false)
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLMacroFieldImportContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
+{
+ if ( nElement == XML_ELEMENT(OFFICE, XML_EVENT_LISTENERS) )
+ {
+ // create events context and remember it!
+ xEventContext = new XMLEventsImportContext( GetImport() );
+ bValid = true;
+ return xEventContext;
+ }
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+
+ return nullptr;
+}
+
+void XMLMacroFieldImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ switch (nAttrToken)
+ {
+ case XML_ELEMENT(TEXT, XML_DESCRIPTION):
+ sDescription = OUString::fromUtf8(sAttrValue);
+ bDescriptionOK = true;
+ break;
+ case XML_ELEMENT(TEXT, XML_NAME):
+ sMacro = OUString::fromUtf8(sAttrValue);
+ bValid = true;
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+ }
+}
+
+void XMLMacroFieldImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ Any aAny;
+ aAny <<= (bDescriptionOK ? sDescription : GetContent());
+ xPropertySet->setPropertyValue(sAPI_hint, aAny);
+
+ // if we have an events child element, we'll look for the OnClick
+ // event if not, it may be an old (pre-638i) document. Then, we'll
+ // have to look at the name attribute.
+ OUString sMacroName;
+ OUString sLibraryName;
+ OUString sScriptURL;
+
+ if ( xEventContext.is() )
+ {
+ // get event sequence
+ XMLEventsImportContext* pEvents = xEventContext.get();
+ Sequence<PropertyValue> aValues;
+ pEvents->GetEventSequence( "OnClick", aValues );
+
+ for( const auto& rValue : std::as_const(aValues) )
+ {
+ if ( rValue.Name == "ScriptType" )
+ {
+ // ignore ScriptType
+ }
+ else if ( rValue.Name == "Library" )
+ {
+ rValue.Value >>= sLibraryName;
+ }
+ else if ( rValue.Name == "MacroName" )
+ {
+ rValue.Value >>= sMacroName;
+ }
+ if ( rValue.Name == "Script" )
+ {
+ rValue.Value >>= sScriptURL;
+ }
+ }
+ }
+ else
+ {
+ // disassemble old-style macro-name: Everything before the
+ // third-last dot is the library
+ sal_Int32 nPos = sMacro.getLength() + 1; // the loop starts with nPos--
+ const sal_Unicode* pBuf = sMacro.getStr();
+ for( sal_Int32 i = 0; (i < 3) && (nPos > 0); i++ )
+ {
+ nPos--;
+ while ( (pBuf[nPos] != '.') && (nPos > 0) )
+ nPos--;
+ }
+
+ if (nPos > 0)
+ {
+ sLibraryName = sMacro.copy(0, nPos);
+ sMacroName = sMacro.copy(nPos+1);
+ }
+ else
+ sMacroName = sMacro;
+ }
+
+ xPropertySet->setPropertyValue("ScriptURL", Any(sScriptURL));
+ xPropertySet->setPropertyValue("MacroName", Any(sMacroName));
+ xPropertySet->setPropertyValue("MacroLibrary", Any(sLibraryName));
+}
+
+
+// reference field import
+
+
+XMLReferenceFieldImportContext::XMLReferenceFieldImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp,
+ sal_Int32 nToken)
+: XMLTextFieldImportContext(rImport, rHlp, "GetReference")
+, nElementToken(nToken)
+, nSource(0)
+, nType(ReferenceFieldPart::PAGE_DESC)
+, nFlags(0)
+, bNameOK(false)
+, bTypeOK(false)
+{
+}
+
+SvXMLEnumMapEntry<sal_uInt16> const lcl_aReferenceTypeTokenMap[] =
+{
+ { XML_PAGE, ReferenceFieldPart::PAGE},
+ { XML_CHAPTER, ReferenceFieldPart::CHAPTER },
+ { XML_TEXT, ReferenceFieldPart::TEXT },
+ { XML_DIRECTION, ReferenceFieldPart::UP_DOWN },
+ { XML_CATEGORY_AND_VALUE, ReferenceFieldPart::CATEGORY_AND_NUMBER },
+ { XML_CAPTION, ReferenceFieldPart::ONLY_CAPTION },
+ { XML_VALUE, ReferenceFieldPart::ONLY_SEQUENCE_NUMBER },
+ // Core implementation for direct cross-references (#i81002#)
+ { XML_NUMBER, ReferenceFieldPart::NUMBER },
+ { XML_NUMBER_NO_SUPERIOR, ReferenceFieldPart::NUMBER_NO_CONTEXT },
+ { XML_NUMBER_ALL_SUPERIOR, ReferenceFieldPart::NUMBER_FULL_CONTEXT },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+void XMLReferenceFieldImportContext::startFastElement(
+ sal_Int32 nElement,
+ const Reference<XFastAttributeList> & xAttrList)
+{
+ bTypeOK = true;
+ switch (nElementToken)
+ {
+ case XML_ELEMENT(TEXT, XML_REFERENCE_REF):
+ nSource = ReferenceFieldSource::REFERENCE_MARK;
+ break;
+ case XML_ELEMENT(TEXT, XML_BOOKMARK_REF):
+ nSource = ReferenceFieldSource::BOOKMARK;
+ break;
+ case XML_ELEMENT(TEXT, XML_NOTE_REF):
+ nSource = ReferenceFieldSource::FOOTNOTE;
+ break;
+ case XML_ELEMENT(TEXT, XML_SEQUENCE_REF):
+ nSource = ReferenceFieldSource::SEQUENCE_FIELD;
+ break;
+ case XML_ELEMENT(TEXT, XML_STYLE_REF):
+ case XML_ELEMENT(LO_EXT, XML_STYLE_REF):
+ nSource = ReferenceFieldSource::STYLE;
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElementToken);
+ bTypeOK = false;
+ break;
+ }
+
+ XMLTextFieldImportContext::startFastElement(nElement, xAttrList);
+}
+
+
+void XMLReferenceFieldImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ switch (nAttrToken)
+ {
+ case XML_ELEMENT(TEXT, XML_NOTE_CLASS):
+ if( IsXMLToken( sAttrValue, XML_ENDNOTE ) )
+ nSource = ReferenceFieldSource::ENDNOTE;
+ break;
+ case XML_ELEMENT(TEXT, XML_REF_NAME):
+ sName = OUString::fromUtf8(sAttrValue);
+ bNameOK = true;
+ break;
+ case XML_ELEMENT(TEXT, XML_REFERENCE_FORMAT):
+ {
+ sal_uInt16 nToken;
+ if (SvXMLUnitConverter::convertEnum(nToken, sAttrValue,
+ lcl_aReferenceTypeTokenMap))
+ {
+ nType = nToken;
+ }
+
+ // check for sequence-only-attributes
+ if ( (XML_ELEMENT(TEXT, XML_SEQUENCE_REF) != nElementToken) &&
+ ( (nType == ReferenceFieldPart::CATEGORY_AND_NUMBER) ||
+ (nType == ReferenceFieldPart::ONLY_CAPTION) ||
+ (nType == ReferenceFieldPart::ONLY_SEQUENCE_NUMBER) ) )
+ {
+ nType = ReferenceFieldPart::PAGE_DESC;
+ }
+
+ break;
+ }
+ case XML_ELEMENT(LO_EXT, XML_REFERENCE_LANGUAGE):
+ case XML_ELEMENT(TEXT, XML_REFERENCE_LANGUAGE):
+ sLanguage = OUString::fromUtf8(sAttrValue);
+ break;
+ case XML_ELEMENT(LO_EXT, XML_REFERENCE_HIDE_NON_NUMERICAL):
+ case XML_ELEMENT(TEXT, XML_REFERENCE_HIDE_NON_NUMERICAL):
+ if (OUString::fromUtf8(sAttrValue).toBoolean())
+ nFlags |= REFFLDFLAG_STYLE_HIDE_NON_NUMERICAL;
+ break;
+ case XML_ELEMENT(LO_EXT, XML_REFERENCE_FROM_BOTTOM):
+ case XML_ELEMENT(TEXT, XML_REFERENCE_FROM_BOTTOM):
+ if (OUString::fromUtf8(sAttrValue).toBoolean())
+ nFlags |= REFFLDFLAG_STYLE_FROM_BOTTOM;
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+ }
+
+ // bValid: we need proper element type and name
+ bValid = bTypeOK && bNameOK;
+}
+
+void XMLReferenceFieldImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ xPropertySet->setPropertyValue("ReferenceFieldPart", Any(nType));
+
+ xPropertySet->setPropertyValue("ReferenceFieldSource", Any(nSource));
+
+ xPropertySet->setPropertyValue("ReferenceFieldLanguage", Any(sLanguage));
+ switch (nElementToken)
+ {
+ case XML_ELEMENT(TEXT, XML_REFERENCE_REF):
+ case XML_ELEMENT(TEXT, XML_BOOKMARK_REF):
+ case XML_ELEMENT(TEXT, XML_STYLE_REF):
+ case XML_ELEMENT(LO_EXT, XML_STYLE_REF):
+ xPropertySet->setPropertyValue("SourceName", Any(sName));
+ xPropertySet->setPropertyValue("ReferenceFieldFlags", Any(nFlags));
+ break;
+
+ case XML_ELEMENT(TEXT, XML_NOTE_REF):
+ GetImportHelper().ProcessFootnoteReference(sName, xPropertySet);
+ break;
+
+ case XML_ELEMENT(TEXT, XML_SEQUENCE_REF):
+ GetImportHelper().ProcessSequenceReference(sName, xPropertySet);
+ break;
+ }
+
+ xPropertySet->setPropertyValue(sAPI_current_presentation, Any(GetContent()));
+}
+
+
+// field declarations container
+
+XMLDdeFieldDeclsImportContext::XMLDdeFieldDeclsImportContext(SvXMLImport& rImport) :
+ SvXMLImportContext(rImport)
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLDdeFieldDeclsImportContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& )
+{
+ if ( nElement == XML_ELEMENT(TEXT, XML_DDE_CONNECTION_DECL) )
+ {
+ return new XMLDdeFieldDeclImportContext(GetImport());
+ }
+ else
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ return nullptr;
+}
+
+
+// import dde field declaration
+
+
+XMLDdeFieldDeclImportContext::XMLDdeFieldDeclImportContext(SvXMLImport& rImport)
+: SvXMLImportContext(rImport)
+{
+}
+
+void XMLDdeFieldDeclImportContext::startFastElement(
+ sal_Int32 /*nElement*/,
+ const Reference<XFastAttributeList> & xAttrList)
+{
+ OUString sName;
+ OUString sCommandApplication;
+ OUString sCommandTopic;
+ OUString sCommandItem;
+
+ bool bUpdate = false;
+ bool bNameOK = false;
+ bool bCommandApplicationOK = false;
+ bool bCommandTopicOK = false;
+ bool bCommandItemOK = false;
+
+ // process attributes
+ for( auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ) )
+ {
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(OFFICE, XML_NAME):
+ sName = aIter.toString();
+ bNameOK = true;
+ break;
+ case XML_ELEMENT(OFFICE, XML_DDE_APPLICATION):
+ sCommandApplication = aIter.toString();
+ bCommandApplicationOK = true;
+ break;
+ case XML_ELEMENT(OFFICE, XML_DDE_TOPIC):
+ sCommandTopic = aIter.toString();
+ bCommandTopicOK = true;
+ break;
+ case XML_ELEMENT(OFFICE, XML_DDE_ITEM):
+ sCommandItem = aIter.toString();
+ bCommandItemOK = true;
+ break;
+ case XML_ELEMENT(OFFICE, XML_AUTOMATIC_UPDATE):
+ {
+ bool bTmp(false);
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()) )
+ {
+ bUpdate = bTmp;
+ }
+ break;
+ }
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+
+ // valid data?
+ if (!(bNameOK && bCommandApplicationOK && bCommandTopicOK && bCommandItemOK))
+ return;
+
+ // create DDE TextFieldMaster
+ Reference<XMultiServiceFactory> xFactory(GetImport().GetModel(),
+ UNO_QUERY);
+ if( !xFactory.is() )
+ return;
+
+ /* #i6432# There might be multiple occurrences of one DDE
+ declaration if it is used in more than one of
+ header/footer/body. createInstance will throw an exception if we
+ try to create the second, third, etc. instance of such a
+ declaration. Thus we ignore the exception. Otherwise this will
+ lead to an unloadable document. */
+ try
+ {
+ Reference<XInterface> xIfc =
+ xFactory->createInstance(OUString::Concat(sAPI_fieldmaster_prefix) + sAPI_dde);
+ if( xIfc.is() )
+ {
+ Reference<XPropertySet> xPropSet( xIfc, UNO_QUERY );
+ if (xPropSet.is() &&
+ xPropSet->getPropertySetInfo()->hasPropertyByName(
+ "DDECommandType"))
+ {
+ xPropSet->setPropertyValue(sAPI_name, Any(sName));
+
+ xPropSet->setPropertyValue("DDECommandType", Any(sCommandApplication));
+
+ xPropSet->setPropertyValue("DDECommandFile", Any(sCommandTopic));
+
+ xPropSet->setPropertyValue("DDECommandElement",
+ Any(sCommandItem));
+
+ xPropSet->setPropertyValue("IsAutomaticUpdate",
+ Any(bUpdate));
+ }
+ // else: ignore (can't get XPropertySet, or DDE
+ // properties are not supported)
+ }
+ // else: ignore
+ }
+ catch (const Exception&)
+ {
+ //ignore
+ }
+ // else: ignore
+ // else: ignore
+}
+
+
+// DDE field import
+
+
+XMLDdeFieldImportContext::XMLDdeFieldImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
+ XMLTextFieldImportContext(rImport, rHlp, sAPI_dde),
+ sPropertyContent(sAPI_content)
+{
+}
+
+void XMLDdeFieldImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ if ( XML_ELEMENT(TEXT, XML_CONNECTION_NAME) == nAttrToken)
+ {
+ sName = OUString::fromUtf8(sAttrValue);
+ bValid = true;
+ }
+ else
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+}
+
+
+void XMLDdeFieldImportContext::endFastElement(sal_Int32 )
+{
+ if (!bValid)
+ return;
+
+ // find master
+ OUString sMasterName = OUString::Concat(sAPI_fieldmaster_prefix) + sAPI_dde + "." + sName;
+
+ Reference<XTextFieldsSupplier> xTextFieldsSupp(GetImport().GetModel(),
+ UNO_QUERY);
+ Reference<container::XNameAccess> xFieldMasterNameAccess =
+ xTextFieldsSupp->getTextFieldMasters();
+
+ if (!xFieldMasterNameAccess->hasByName(sMasterName))
+ return;
+
+ Reference<XPropertySet> xMaster;
+ Any aAny = xFieldMasterNameAccess->getByName(sMasterName);
+ aAny >>= xMaster;
+ //apply the content to the master
+ xMaster->setPropertyValue( sPropertyContent, uno::Any( GetContent()));
+ // master exists: create text field and attach
+ Reference<XPropertySet> xField;
+ OUString sFieldName = OUString::Concat(sAPI_textfield_prefix) + sAPI_dde;
+ if (!CreateField(xField, sFieldName))
+ return;
+
+ Reference<XDependentTextField> xDepTextField(xField,UNO_QUERY);
+ xDepTextField->attachTextFieldMaster(xMaster);
+
+ // attach field to document
+ Reference<XTextContent> xTextContent(xField, UNO_QUERY);
+ if (xTextContent.is())
+ {
+ GetImportHelper().InsertTextContent(xTextContent);
+
+ // we're lucky. nothing else to prepare.
+ }
+ // else: fail, because text content could not be created
+ // else: fail, because field could not be created
+ // else: fail, because no master was found (faulty document?!)
+ // not valid: ignore
+}
+
+void XMLDdeFieldImportContext::PrepareField(
+ const Reference<XPropertySet> &)
+{
+ // empty, since not needed.
+}
+
+
+// sheet name fields
+
+
+XMLSheetNameImportContext::XMLSheetNameImportContext(
+ SvXMLImport& rImport,
+ XMLTextImportHelper& rHlp) :
+ XMLTextFieldImportContext(rImport, rHlp, "SheetName")
+{
+ bValid = true; // always valid!
+}
+
+void XMLSheetNameImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue)
+{
+ // no attributes -> nothing to be done
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+}
+
+void XMLSheetNameImportContext::PrepareField(
+ const Reference<XPropertySet> &)
+{
+ // no attributes -> nothing to be done
+}
+
+/** import page|slide name fields (<text:page-name>) */
+
+XMLPageNameFieldImportContext::XMLPageNameFieldImportContext(
+ SvXMLImport& rImport, /// XML Import
+ XMLTextImportHelper& rHlp) /// Text import helper
+: XMLTextFieldImportContext(rImport, rHlp, "PageName" )
+{
+ bValid = true;
+}
+
+/// process attribute values
+void XMLPageNameFieldImportContext::ProcessAttribute( sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+}
+
+/// prepare XTextField for insertion into document
+void XMLPageNameFieldImportContext::PrepareField(
+ const css::uno::Reference<css::beans::XPropertySet> &)
+{
+}
+
+
+// URL fields (Calc, Impress, Draw)
+
+
+XMLUrlFieldImportContext::XMLUrlFieldImportContext(
+ SvXMLImport& rImport,
+ XMLTextImportHelper& rHlp) :
+ XMLTextFieldImportContext(rImport, rHlp, sAPI_url),
+ bFrameOK(false)
+{
+}
+
+void XMLUrlFieldImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ switch (nAttrToken)
+ {
+ case XML_ELEMENT(XLINK, XML_HREF):
+ sURL = GetImport().GetAbsoluteReference( OUString::fromUtf8(sAttrValue) );
+ bValid = true;
+ break;
+ case XML_ELEMENT(OFFICE, XML_TARGET_FRAME_NAME):
+ sFrame = OUString::fromUtf8(sAttrValue);
+ bFrameOK = true;
+ break;
+ default:
+ // ignore
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+ break;
+ }
+}
+
+void XMLUrlFieldImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ xPropertySet->setPropertyValue(sAPI_url, Any(sURL));
+
+ if (bFrameOK)
+ {
+ xPropertySet->setPropertyValue("TargetFrame", Any(sFrame));
+ }
+
+ xPropertySet->setPropertyValue("Representation", Any(GetContent()));
+}
+
+
+XMLBibliographyFieldImportContext::XMLBibliographyFieldImportContext(
+ SvXMLImport& rImport,
+ XMLTextImportHelper& rHlp) :
+ XMLTextFieldImportContext(rImport, rHlp, "Bibliography")
+{
+ bValid = true;
+}
+
+// TODO: this is the same map as is used in the text field export
+SvXMLEnumMapEntry<sal_uInt16> const aBibliographyDataTypeMap[] =
+{
+ { XML_ARTICLE, BibliographyDataType::ARTICLE },
+ { XML_BOOK, BibliographyDataType::BOOK },
+ { XML_BOOKLET, BibliographyDataType::BOOKLET },
+ { XML_CONFERENCE, BibliographyDataType::CONFERENCE },
+ { XML_CUSTOM1, BibliographyDataType::CUSTOM1 },
+ { XML_CUSTOM2, BibliographyDataType::CUSTOM2 },
+ { XML_CUSTOM3, BibliographyDataType::CUSTOM3 },
+ { XML_CUSTOM4, BibliographyDataType::CUSTOM4 },
+ { XML_CUSTOM5, BibliographyDataType::CUSTOM5 },
+ { XML_EMAIL, BibliographyDataType::EMAIL },
+ { XML_INBOOK, BibliographyDataType::INBOOK },
+ { XML_INCOLLECTION, BibliographyDataType::INCOLLECTION },
+ { XML_INPROCEEDINGS, BibliographyDataType::INPROCEEDINGS },
+ { XML_JOURNAL, BibliographyDataType::JOURNAL },
+ { XML_MANUAL, BibliographyDataType::MANUAL },
+ { XML_MASTERSTHESIS, BibliographyDataType::MASTERSTHESIS },
+ { XML_MISC, BibliographyDataType::MISC },
+ { XML_PHDTHESIS, BibliographyDataType::PHDTHESIS },
+ { XML_PROCEEDINGS, BibliographyDataType::PROCEEDINGS },
+ { XML_TECHREPORT, BibliographyDataType::TECHREPORT },
+ { XML_UNPUBLISHED, BibliographyDataType::UNPUBLISHED },
+ { XML_WWW, BibliographyDataType::WWW },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+
+// we'll process attributes on our own and for fit the standard
+// textfield mechanism, because our attributes have zero overlap with
+// all the other textfields.
+void XMLBibliographyFieldImportContext::startFastElement(
+ sal_Int32 /*nElement*/,
+ const Reference<XFastAttributeList> & xAttrList)
+{
+ // iterate over attributes
+ for( auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ) )
+ {
+ if (IsTokenInNamespace(aIter.getToken(), XML_NAMESPACE_TEXT)
+ || IsTokenInNamespace(aIter.getToken(), XML_NAMESPACE_LO_EXT))
+ {
+ auto nToken = aIter.getToken() & TOKEN_MASK;
+ PropertyValue aValue;
+ aValue.Name = OUString::createFromAscii(
+ MapBibliographyFieldName(nToken));
+ Any aAny;
+
+ // special treatment for bibliography type
+ // biblio vs bibilio: #96658#; also read old documents
+ if (nToken == XML_BIBILIOGRAPHIC_TYPE ||
+ nToken == XML_BIBLIOGRAPHY_TYPE )
+ {
+ sal_uInt16 nTmp;
+ if (SvXMLUnitConverter::convertEnum(
+ nTmp, aIter.toView(),
+ aBibliographyDataTypeMap))
+ {
+ aAny <<= static_cast<sal_Int16>(nTmp);
+ aValue.Value = aAny;
+
+ aValues.push_back(aValue);
+ }
+ }
+ else
+ {
+ OUString aStringValue = aIter.toString();
+ if (nToken == XML_URL || nToken == XML_LOCAL_URL || nToken == XML_TARGET_URL)
+ {
+ aStringValue = GetImport().GetAbsoluteReference(aStringValue);
+ }
+ aAny <<= aStringValue;
+ aValue.Value = aAny;
+
+ aValues.push_back(aValue);
+ }
+ }
+ // else: unknown namespace -> ignore
+ }
+}
+
+void XMLBibliographyFieldImportContext::ProcessAttribute(
+ sal_Int32 ,
+ std::string_view )
+{
+ // attributes are handled in StartElement
+ assert(false && "This should not have happened.");
+}
+
+
+void XMLBibliographyFieldImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ // convert vector into sequence
+ sal_Int32 nCount = aValues.size();
+ Sequence<PropertyValue> aValueSequence(nCount);
+ auto aValueSequenceRange = asNonConstRange(aValueSequence);
+ for(sal_Int32 i = 0; i < nCount; i++)
+ {
+ aValueSequenceRange[i] = aValues[i];
+ }
+
+ // set sequence
+ xPropertySet->setPropertyValue("Fields", Any(aValueSequence));
+}
+
+const char* XMLBibliographyFieldImportContext::MapBibliographyFieldName(
+ sal_Int32 nElement)
+{
+ const char* pName = nullptr;
+
+ switch (nElement & TOKEN_MASK)
+ {
+ case XML_IDENTIFIER:
+ pName = "Identifier";
+ break;
+ case XML_BIBILIOGRAPHIC_TYPE:
+ case XML_BIBLIOGRAPHY_TYPE:
+ // biblio... vs bibilio...: #96658#: also read old documents
+ pName = "BibiliographicType";
+ break;
+ case XML_ADDRESS:
+ pName = "Address";
+ break;
+ case XML_ANNOTE:
+ pName = "Annote";
+ break;
+ case XML_AUTHOR:
+ pName = "Author";
+ break;
+ case XML_BOOKTITLE:
+ pName = "Booktitle";
+ break;
+ case XML_CHAPTER:
+ pName = "Chapter";
+ break;
+ case XML_EDITION:
+ pName = "Edition";
+ break;
+ case XML_EDITOR:
+ pName = "Editor";
+ break;
+ case XML_HOWPUBLISHED:
+ pName = "Howpublished";
+ break;
+ case XML_INSTITUTION:
+ pName = "Institution";
+ break;
+ case XML_JOURNAL:
+ pName = "Journal";
+ break;
+ case XML_MONTH:
+ pName = "Month";
+ break;
+ case XML_NOTE:
+ pName = "Note";
+ break;
+ case XML_NUMBER:
+ pName = "Number";
+ break;
+ case XML_ORGANIZATIONS:
+ pName = "Organizations";
+ break;
+ case XML_PAGES:
+ pName = "Pages";
+ break;
+ case XML_PUBLISHER:
+ pName = "Publisher";
+ break;
+ case XML_SCHOOL:
+ pName = "School";
+ break;
+ case XML_SERIES:
+ pName = "Series";
+ break;
+ case XML_TITLE:
+ pName = "Title";
+ break;
+ case XML_REPORT_TYPE:
+ pName = "Report_Type";
+ break;
+ case XML_VOLUME:
+ pName = "Volume";
+ break;
+ case XML_YEAR:
+ pName = "Year";
+ break;
+ case XML_URL:
+ pName = "URL";
+ break;
+ case XML_CUSTOM1:
+ pName = "Custom1";
+ break;
+ case XML_CUSTOM2:
+ pName = "Custom2";
+ break;
+ case XML_CUSTOM3:
+ pName = "Custom3";
+ break;
+ case XML_CUSTOM4:
+ pName = "Custom4";
+ break;
+ case XML_CUSTOM5:
+ pName = "Custom5";
+ break;
+ case XML_ISBN:
+ pName = "ISBN";
+ break;
+ case XML_LOCAL_URL:
+ pName = "LocalURL";
+ break;
+ case XML_TARGET_TYPE:
+ pName = "TargetType";
+ break;
+ case XML_TARGET_URL:
+ pName = "TargetURL";
+ break;
+ default:
+ assert(false && "Unknown bibliography info data");
+ pName = nullptr;
+ }
+ return pName;
+}
+
+// Annotation Field
+
+
+XMLAnnotationImportContext::XMLAnnotationImportContext(
+ SvXMLImport& rImport,
+ XMLTextImportHelper& rHlp,
+ sal_Int32 nElement) :
+ XMLTextFieldImportContext(rImport, rHlp, "Annotation"),
+ mnElement(nElement)
+{
+ bValid = true;
+
+ // remember old list item and block (#91964#) and reset them
+ // for the text frame
+ // do this in the constructor, not in CreateChildContext (#i93392#)
+ GetImport().GetTextImport()->PushListContext();
+}
+
+void XMLAnnotationImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ if (nAttrToken == XML_ELEMENT(OFFICE, XML_NAME))
+ aName = OUString::fromUtf8(sAttrValue);
+ else if (nAttrToken == XML_ELEMENT(LO_EXT, XML_RESOLVED))
+ aResolved = OUString::fromUtf8(sAttrValue);
+ else if (nAttrToken == XML_ELEMENT(LO_EXT, XML_PARENT_NAME))
+ aParentName = OUString::fromUtf8(sAttrValue);
+ else
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLAnnotationImportContext::createFastChildContext(
+ sal_Int32 nElement,
+ const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
+{
+ if( nElement == XML_ELEMENT(DC, XML_CREATOR) )
+ return new XMLStringBufferImportContext(GetImport(), aAuthorBuffer);
+ else if( nElement == XML_ELEMENT(DC, XML_DATE) )
+ return new XMLStringBufferImportContext(GetImport(), aDateBuffer);
+ else if (nElement == XML_ELEMENT(TEXT,XML_SENDER_INITIALS) ||
+ nElement == XML_ELEMENT(LO_EXT, XML_SENDER_INITIALS) ||
+ nElement == XML_ELEMENT(META, XML_CREATOR_INITIALS))
+ return new XMLStringBufferImportContext(GetImport(), aInitialsBuffer);
+
+ try
+ {
+ bool bOK = true;
+ if ( !mxField.is() )
+ bOK = CreateField( mxField, sServicePrefix + GetServiceName() );
+ if (bOK)
+ {
+ Any aAny = mxField->getPropertyValue( "TextRange" );
+ Reference< XText > xText;
+ aAny >>= xText;
+ if( xText.is() )
+ {
+ rtl::Reference < XMLTextImportHelper > xTxtImport = GetImport().GetTextImport();
+ if( !mxCursor.is() )
+ {
+ mxOldCursor = xTxtImport->GetCursor();
+ mxCursor = xText->createTextCursor();
+ }
+
+ if( mxCursor.is() )
+ {
+ xTxtImport->SetCursor( mxCursor );
+ return xTxtImport->CreateTextChildContext( GetImport(), nElement, xAttrList );
+ }
+ }
+ }
+ }
+ catch (const Exception&)
+ {
+ }
+
+ return new XMLStringBufferImportContext(GetImport(), aTextBuffer);
+}
+
+void XMLAnnotationImportContext::endFastElement(sal_Int32 /*nElement*/)
+{
+ DBG_ASSERT(!GetServiceName().isEmpty(), "no service name for element!");
+ if( mxCursor.is() )
+ {
+ // delete addition newline
+ mxCursor->gotoEnd( false );
+ mxCursor->goLeft( 1, true );
+ mxCursor->setString( "" );
+
+ // reset cursor
+ GetImport().GetTextImport()->ResetCursor();
+ }
+
+ if( mxOldCursor.is() )
+ GetImport().GetTextImport()->SetCursor( mxOldCursor );
+
+ // reinstall old list item #91964#
+ GetImport().GetTextImport()->PopListContext();
+
+ if ( bValid )
+ {
+ if ( mnElement == XML_ELEMENT(OFFICE, XML_ANNOTATION_END) )
+ {
+ // Search for a previous annotation with the same name.
+ uno::Reference< text::XTextContent > xPrevField;
+ {
+ Reference<XTextFieldsSupplier> xTextFieldsSupplier(GetImport().GetModel(), UNO_QUERY);
+ uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields());
+ uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration());
+ while (xFields->hasMoreElements())
+ {
+ uno::Reference<beans::XPropertySet> xCurrField(xFields->nextElement(), uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySetInfo> const xInfo(
+ xCurrField->getPropertySetInfo());
+ if (xInfo->hasPropertyByName(sAPI_name))
+ {
+ OUString aFieldName;
+ xCurrField->getPropertyValue(sAPI_name) >>= aFieldName;
+ if (aFieldName == aName)
+ {
+ xPrevField.set( xCurrField, uno::UNO_QUERY );
+ break;
+ }
+ }
+ }
+ }
+ if ( xPrevField.is() )
+ {
+ // So we are ending a previous annotation,
+ // let's create a text range covering the old and the current position.
+ uno::Reference<text::XText> xText = GetImportHelper().GetText();
+ uno::Reference<text::XTextCursor> xCursor =
+ xText->createTextCursorByRange(GetImportHelper().GetCursorAsRange());
+ try
+ {
+ xCursor->gotoRange(xPrevField->getAnchor(), true);
+ }
+ catch (const uno::RuntimeException&)
+ {
+ // Losing the start of the anchor is better than not opening the document at
+ // all.
+ TOOLS_WARN_EXCEPTION(
+ "xmloff.text",
+ "XMLAnnotationImportContext::endFastElement: gotoRange() failed: ");
+ }
+
+ xText->insertTextContent(xCursor, xPrevField, !xCursor->isCollapsed());
+ }
+ }
+ else
+ {
+ if ( mxField.is() || CreateField( mxField, sServicePrefix + GetServiceName() ) )
+ {
+ // set field properties
+ PrepareField( mxField );
+
+ // attach field to document
+ Reference < XTextContent > xTextContent( mxField, UNO_QUERY );
+
+ // workaround for #80606#
+ try
+ {
+ GetImportHelper().InsertTextContent( xTextContent );
+ }
+ catch (const lang::IllegalArgumentException&)
+ {
+ // ignore
+ }
+ }
+ }
+ }
+ else
+ GetImportHelper().InsertString(GetContent());
+}
+
+void XMLAnnotationImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet )
+{
+ // import (possibly empty) author
+ OUString sAuthor( aAuthorBuffer.makeStringAndClear() );
+ xPropertySet->setPropertyValue(sAPI_author, Any(sAuthor));
+
+ // import (possibly empty) initials
+ OUString sInitials( aInitialsBuffer.makeStringAndClear() );
+ xPropertySet->setPropertyValue("Initials", Any(sInitials));
+
+ //import resolved flag
+ bool bTmp(false);
+ (void)::sax::Converter::convertBool(bTmp, aResolved);
+ xPropertySet->setPropertyValue("Resolved", Any(bTmp));
+
+ util::DateTime aDateTime;
+ if (::sax::Converter::parseDateTime(aDateTime, aDateBuffer))
+ {
+ /*
+ Date aDate;
+ aDate.Year = aDateTime.Year;
+ aDate.Month = aDateTime.Month;
+ aDate.Day = aDateTime.Day;
+ xPropertySet->setPropertyValue(sPropertyDate, makeAny(aDate));
+ */
+ // why is there no UNO_NAME_DATE_TIME, but only UNO_NAME_DATE_TIME_VALUE?
+ xPropertySet->setPropertyValue(sAPI_date_time_value, Any(aDateTime));
+ }
+ aDateBuffer.setLength(0);
+
+ if ( aTextBuffer.getLength() )
+ {
+ // delete last paragraph mark (if necessary)
+ if (char(0x0a) == aTextBuffer[aTextBuffer.getLength()-1])
+ aTextBuffer.setLength(aTextBuffer.getLength()-1);
+ xPropertySet->setPropertyValue(sAPI_content, Any(aTextBuffer.makeStringAndClear()));
+ }
+
+ if (!aName.isEmpty())
+ xPropertySet->setPropertyValue(sAPI_name, Any(aName));
+
+ if (!aParentName.isEmpty())
+ xPropertySet->setPropertyValue(sAPI_parent_name, Any(aParentName));
+}
+
+
+// script field
+
+
+XMLScriptImportContext::XMLScriptImportContext(
+ SvXMLImport& rImport,
+ XMLTextImportHelper& rHlp)
+: XMLTextFieldImportContext(rImport, rHlp, "Script")
+, bContentOK(false)
+{
+}
+
+void XMLScriptImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ switch (nAttrToken)
+ {
+ case XML_ELEMENT(XLINK, XML_HREF):
+ sContent = GetImport().GetAbsoluteReference( OUString::fromUtf8(sAttrValue) );
+ bContentOK = true;
+ break;
+
+ case XML_ELEMENT(SCRIPT, XML_LANGUAGE):
+ sScriptType = OUString::fromUtf8(sAttrValue);
+ break;
+
+ default:
+ // ignore
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+ break;
+ }
+
+ // always valid (even without ScriptType; cf- #96531#)
+ bValid = true;
+}
+
+void XMLScriptImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ // if href attribute was present, we use it. Else we use element content
+ if (! bContentOK)
+ {
+ sContent = GetContent();
+ }
+ xPropertySet->setPropertyValue(sAPI_content, Any(sContent));
+
+ // URL or script text? We use URL if we have an href-attribute
+ xPropertySet->setPropertyValue("URLContent", Any(bContentOK));
+
+ xPropertySet->setPropertyValue("ScriptType", Any(sScriptType));
+}
+
+
+// measure field
+
+
+XMLMeasureFieldImportContext::XMLMeasureFieldImportContext(
+ SvXMLImport& rImport,
+ XMLTextImportHelper& rHlp) :
+ XMLTextFieldImportContext(rImport, rHlp, "Measure"),
+ mnKind( 0 )
+{
+}
+
+void XMLMeasureFieldImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ switch (nAttrToken)
+ {
+ case XML_ELEMENT(TEXT, XML_KIND):
+ if( IsXMLToken( sAttrValue, XML_VALUE ) )
+ {
+ mnKind = 0; bValid = true;
+ }
+ else if( IsXMLToken( sAttrValue, XML_UNIT ) )
+ {
+ mnKind = 1; bValid = true;
+ }
+ else if( IsXMLToken( sAttrValue, XML_GAP ) )
+ {
+ mnKind = 2; bValid = true;
+ }
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+ }
+}
+
+void XMLMeasureFieldImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ xPropertySet->setPropertyValue("Kind", Any(mnKind));
+}
+
+
+// dropdown field
+
+
+XMLDropDownFieldImportContext::XMLDropDownFieldImportContext(
+ SvXMLImport& rImport,
+ XMLTextImportHelper& rHlp) :
+ XMLTextFieldImportContext( rImport, rHlp, "DropDown" ),
+ nSelected( -1 ),
+ bNameOK( false ),
+ bHelpOK(false),
+ bHintOK(false)
+{
+ bValid = true;
+}
+
+static bool lcl_ProcessLabel(
+ const Reference<XFastAttributeList>& xAttrList,
+ OUString& rLabel,
+ bool& rIsSelected )
+{
+ bool bValid = false;
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(TEXT, XML_VALUE):
+ {
+ rLabel = aIter.toString();
+ bValid = true;
+ break;
+ }
+ case XML_ELEMENT(TEXT, XML_CURRENT_SELECTED):
+ {
+ bool bTmp(false);
+ if (::sax::Converter::convertBool( bTmp, aIter.toView() ))
+ rIsSelected = bTmp;
+ break;
+ }
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+ return bValid;
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLDropDownFieldImportContext::createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ if( nElement == XML_ELEMENT(TEXT, XML_LABEL) )
+ {
+ OUString sLabel;
+ bool bIsSelected = false;
+ if( lcl_ProcessLabel( xAttrList, sLabel, bIsSelected ) )
+ {
+ if( bIsSelected )
+ nSelected = static_cast<sal_Int32>( aLabels.size() );
+ aLabels.push_back( sLabel );
+ }
+ }
+ return new SvXMLImportContext( GetImport() );
+}
+
+void XMLDropDownFieldImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ if( nAttrToken == XML_ELEMENT(TEXT, XML_NAME))
+ {
+ sName = OUString::fromUtf8(sAttrValue);
+ bNameOK = true;
+ }
+ else if (nAttrToken == XML_ELEMENT(TEXT, XML_HELP))
+ {
+ sHelp = OUString::fromUtf8(sAttrValue);
+ bHelpOK = true;
+ }
+ else if (nAttrToken == XML_ELEMENT(TEXT, XML_HINT))
+ {
+ sHint = OUString::fromUtf8(sAttrValue);
+ bHintOK = true;
+ }
+ else
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+}
+
+void XMLDropDownFieldImportContext::PrepareField(
+ const Reference<XPropertySet>& xPropertySet)
+{
+ // create sequence
+ sal_Int32 nLength = static_cast<sal_Int32>( aLabels.size() );
+ Sequence<OUString> aSequence( nLength );
+ OUString* pSequence = aSequence.getArray();
+ for( sal_Int32 n = 0; n < nLength; n++ )
+ pSequence[n] = aLabels[n];
+
+ // now set values:
+
+ xPropertySet->setPropertyValue( "Items", Any(aSequence) );
+
+ if( nSelected >= 0 && nSelected < nLength )
+ {
+ xPropertySet->setPropertyValue( "SelectedItem", Any(pSequence[nSelected]) );
+ }
+
+ // set name
+ if( bNameOK )
+ {
+ xPropertySet->setPropertyValue( "Name", Any(sName) );
+ }
+ // set help
+ if( bHelpOK )
+ {
+ xPropertySet->setPropertyValue( "Help", Any(sHelp) );
+ }
+ // set hint
+ if( bHintOK )
+ {
+ xPropertySet->setPropertyValue( "Tooltip", Any(sHint) );
+ }
+
+}
+
+/** import header fields (<draw:header>) */
+
+XMLHeaderFieldImportContext::XMLHeaderFieldImportContext(
+ SvXMLImport& rImport, /// XML Import
+ XMLTextImportHelper& rHlp) /// Text import helper
+: XMLTextFieldImportContext(rImport, rHlp, "Header" )
+{
+ sServicePrefix = sAPI_presentation_prefix;
+ bValid = true;
+}
+
+/// process attribute values
+void XMLHeaderFieldImportContext::ProcessAttribute( sal_Int32 nAttrToken, std::string_view sAttrValue )
+{
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+}
+
+/// prepare XTextField for insertion into document
+void XMLHeaderFieldImportContext::PrepareField(const Reference<XPropertySet> &)
+{
+}
+
+/** import footer fields (<draw:footer>) */
+
+XMLFooterFieldImportContext::XMLFooterFieldImportContext(
+ SvXMLImport& rImport, /// XML Import
+ XMLTextImportHelper& rHlp) /// Text import helper
+: XMLTextFieldImportContext(rImport, rHlp, "Footer" )
+{
+ sServicePrefix = sAPI_presentation_prefix;
+ bValid = true;
+}
+
+/// process attribute values
+void XMLFooterFieldImportContext::ProcessAttribute( sal_Int32 nAttrToken, std::string_view sAttrValue)
+{
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+}
+
+/// prepare XTextField for insertion into document
+void XMLFooterFieldImportContext::PrepareField(const Reference<XPropertySet> &)
+{
+}
+
+
+/** import footer fields (<draw:date-and-time>) */
+
+XMLDateTimeFieldImportContext::XMLDateTimeFieldImportContext(
+ SvXMLImport& rImport, /// XML Import
+ XMLTextImportHelper& rHlp) /// Text import helper
+: XMLTextFieldImportContext(rImport, rHlp, "DateTime" )
+{
+ sServicePrefix = sAPI_presentation_prefix;
+ bValid = true;
+}
+
+/// process attribute values
+void XMLDateTimeFieldImportContext::ProcessAttribute( sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+}
+
+/// prepare XTextField for insertion into document
+void XMLDateTimeFieldImportContext::PrepareField(
+ const css::uno::Reference<
+ css::beans::XPropertySet> &)
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/txtftne.cxx b/xmloff/source/text/txtftne.cxx
new file mode 100644
index 0000000000..9673b15745
--- /dev/null
+++ b/xmloff/source/text/txtftne.cxx
@@ -0,0 +1,344 @@
+/* -*- 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 .
+ */
+
+
+/** @#file
+ *
+ * This file implements XMLTextParagraphExport methods to export
+ * - footnotes
+ * - endnotes
+ * - footnote configuration elements
+ * - endnote configuration elements
+ */
+
+#include <sal/config.h>
+#include <sal/log.hxx>
+
+#include <o3tl/any.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/text/XTextDocument.hpp>
+#include <com/sun/star/text/XText.hpp>
+#include <com/sun/star/text/XFootnote.hpp>
+#include <com/sun/star/text/XFootnotesSupplier.hpp>
+#include <com/sun/star/text/XEndnotesSupplier.hpp>
+#include <com/sun/star/text/FootnoteNumbering.hpp>
+#include <com/sun/star/container/XNameReplace.hpp>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/families.hxx>
+#include "XMLTextCharStyleNamesElementExport.hxx"
+#include <xmloff/XMLEventExport.hxx>
+#include <xmloff/txtparae.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::container;
+using namespace ::xmloff::token;
+
+
+void XMLTextParagraphExport::exportTextFootnote(
+ const Reference<XPropertySet> & rPropSet,
+ const OUString& rText,
+ bool bAutoStyles, bool bIsProgress )
+{
+ // get footnote and associated text
+ Any aAny = rPropSet->getPropertyValue(gsFootnote);
+ Reference<XFootnote> xFootnote;
+ aAny >>= xFootnote;
+ Reference<XText> xText(xFootnote, UNO_QUERY);
+
+ // are we an endnote?
+ Reference<XServiceInfo> xServiceInfo( xFootnote, UNO_QUERY );
+ bool bIsEndnote = xServiceInfo->supportsService(gsTextEndnoteService);
+
+ if (bAutoStyles)
+ {
+ // handle formatting of citation mark
+ Add( XmlStyleFamily::TEXT_TEXT, rPropSet );
+
+ // handle formatting within footnote
+ exportTextFootnoteHelper(xFootnote, xText, rText,
+ bAutoStyles, bIsEndnote, bIsProgress );
+ }
+ else
+ {
+ // create span (for citation mark) if necessary; footnote content
+ // will be handled via exportTextFootnoteHelper, exportText
+ bool bIsUICharStyle = false;
+ bool bHasAutoStyle = false;
+
+ OUString sStyle = FindTextStyle( rPropSet, bIsUICharStyle, bHasAutoStyle );
+
+ {
+ XMLTextCharStyleNamesElementExport aCharStylesExport(
+ GetExport(), bIsUICharStyle &&
+ m_aCharStyleNamesPropInfoCache.hasProperty(
+ rPropSet ), bHasAutoStyle,
+ rPropSet, gsCharStyleNames );
+ if( !sStyle.isEmpty() )
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
+ GetExport().EncodeStyleName( sStyle ) );
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
+ XML_SPAN, false, false );
+ exportTextFootnoteHelper(xFootnote, xText, rText,
+ bAutoStyles, bIsEndnote, bIsProgress );
+ }
+ else
+ {
+ exportTextFootnoteHelper(xFootnote, xText, rText,
+ bAutoStyles, bIsEndnote, bIsProgress );
+ }
+ }
+ }
+}
+
+
+void XMLTextParagraphExport::exportTextFootnoteHelper(
+ const Reference<XFootnote> & rFootnote,
+ const Reference<XText> & rText,
+ const OUString& rTextString,
+ bool bAutoStyles,
+ bool bIsEndnote,
+ bool bIsProgress )
+{
+ if (bAutoStyles)
+ {
+ exportText(rText, bAutoStyles, bIsProgress, true );
+ }
+ else
+ {
+ // export reference Id (for reference fields)
+ Reference<XPropertySet> xPropSet(rFootnote, UNO_QUERY);
+ Any aAny = xPropSet->getPropertyValue(gsReferenceId);
+ sal_Int32 nNumber = 0;
+ aAny >>= nNumber;
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_ID,
+ "ftn" + OUString::number(nNumber));
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NOTE_CLASS,
+ GetXMLToken( bIsEndnote ? XML_ENDNOTE
+ : XML_FOOTNOTE ) );
+
+ SvXMLElementExport aNote(GetExport(), XML_NAMESPACE_TEXT,
+ XML_NOTE, false, false);
+ {
+ // handle label vs. automatic numbering
+ OUString sLabel = rFootnote->getLabel();
+ if (!sLabel.isEmpty())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_LABEL,
+ sLabel);
+ }
+ // else: automatic numbering -> no attribute
+
+ SvXMLElementExport aCite(GetExport(), XML_NAMESPACE_TEXT,
+ XML_NOTE_CITATION, false, false);
+ GetExport().Characters(rTextString);
+ }
+
+ {
+ SvXMLElementExport aBody(GetExport(), XML_NAMESPACE_TEXT,
+ XML_NOTE_BODY, false, false);
+ exportText(rText, bAutoStyles, bIsProgress, true );
+ }
+ }
+}
+
+
+void XMLTextParagraphExport::exportTextFootnoteConfiguration()
+{
+ // footnote settings
+ Reference<XFootnotesSupplier> aFootnotesSupplier(GetExport().GetModel(),
+ UNO_QUERY);
+ Reference<XPropertySet> aFootnoteConfiguration(
+ aFootnotesSupplier->getFootnoteSettings());
+ exportTextFootnoteConfigurationHelper(aFootnoteConfiguration, false);
+
+ // endnote settings
+ Reference<XEndnotesSupplier> aEndnotesSupplier(GetExport().GetModel(),
+ UNO_QUERY);
+ Reference<XPropertySet> aEndnoteConfiguration(
+ aEndnotesSupplier->getEndnoteSettings());
+ exportTextFootnoteConfigurationHelper(aEndnoteConfiguration, true);
+}
+
+
+static void lcl_exportString(
+ SvXMLExport& rExport,
+ const Reference<XPropertySet> & rPropSet,
+ const OUString& sProperty,
+ sal_uInt16 nPrefix,
+ enum XMLTokenEnum eElement,
+ bool bEncodeName)
+{
+ SAL_WARN_IF( eElement == XML_TOKEN_INVALID, "xmloff", "need element token");
+
+ Any aAny = rPropSet->getPropertyValue(sProperty);
+ OUString sTmp;
+ aAny >>= sTmp;
+ if (!sTmp.isEmpty())
+ {
+ if( bEncodeName )
+ sTmp = rExport.EncodeStyleName( sTmp );
+ rExport.AddAttribute(nPrefix, eElement, sTmp);
+ }
+}
+
+void XMLTextParagraphExport::exportTextFootnoteConfigurationHelper(
+ const Reference<XPropertySet> & rFootnoteConfig,
+ bool bIsEndnote)
+{
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NOTE_CLASS,
+ GetXMLToken( bIsEndnote ? XML_ENDNOTE
+ : XML_FOOTNOTE ) );
+ // default/paragraph style
+ lcl_exportString( GetExport(), rFootnoteConfig,
+ gsParaStyleName,
+ XML_NAMESPACE_TEXT, XML_DEFAULT_STYLE_NAME,
+ true);
+
+ // citation style
+ lcl_exportString( GetExport(), rFootnoteConfig,
+ gsCharStyleName,
+ XML_NAMESPACE_TEXT, XML_CITATION_STYLE_NAME,
+ true);
+
+ // citation body style
+ lcl_exportString( GetExport(), rFootnoteConfig,
+ gsAnchorCharStyleName,
+ XML_NAMESPACE_TEXT, XML_CITATION_BODY_STYLE_NAME,
+ true);
+
+ // page style
+ lcl_exportString( GetExport(), rFootnoteConfig,
+ gsPageStyleName,
+ XML_NAMESPACE_TEXT, XML_MASTER_PAGE_NAME,
+ true );
+
+ // prefix
+ lcl_exportString( GetExport(), rFootnoteConfig, gsPrefix,
+ XML_NAMESPACE_STYLE, XML_NUM_PREFIX, false);
+
+ // suffix
+ lcl_exportString( GetExport(), rFootnoteConfig, gsSuffix,
+ XML_NAMESPACE_STYLE, XML_NUM_SUFFIX, false);
+
+
+ Any aAny;
+
+ // numbering style
+ OUStringBuffer sBuffer;
+ aAny = rFootnoteConfig->getPropertyValue(gsNumberingType);
+ sal_Int16 nNumbering = 0;
+ aAny >>= nNumbering;
+ GetExport().GetMM100UnitConverter().convertNumFormat( sBuffer, nNumbering);
+ GetExport().AddAttribute(XML_NAMESPACE_STYLE, XML_NUM_FORMAT,
+ sBuffer.makeStringAndClear() );
+ SvXMLUnitConverter::convertNumLetterSync( sBuffer, nNumbering);
+ if (!sBuffer.isEmpty() )
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_STYLE, XML_NUM_LETTER_SYNC,
+ sBuffer.makeStringAndClear());
+ }
+
+ // StartAt / start-value
+ aAny = rFootnoteConfig->getPropertyValue(gsStartAt);
+ sal_Int16 nOffset = 0;
+ aAny >>= nOffset;
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_START_VALUE,
+ OUString::number(nOffset));
+
+ // some properties are for footnotes only
+ if (!bIsEndnote)
+ {
+ // footnotes position
+ aAny = rFootnoteConfig->getPropertyValue(
+ gsPositionEndOfDoc);
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_FOOTNOTES_POSITION,
+ ( (*o3tl::doAccess<bool>(aAny)) ?
+ XML_DOCUMENT : XML_PAGE ) );
+
+ aAny = rFootnoteConfig->getPropertyValue(gsFootnoteCounting);
+ sal_Int16 nTmp = 0;
+ aAny >>= nTmp;
+ enum XMLTokenEnum eElement;
+ switch (nTmp)
+ {
+ case FootnoteNumbering::PER_PAGE:
+ eElement = XML_PAGE;
+ break;
+ case FootnoteNumbering::PER_CHAPTER:
+ eElement = XML_CHAPTER;
+ break;
+ case FootnoteNumbering::PER_DOCUMENT:
+ default:
+ eElement = XML_DOCUMENT;
+ break;
+ }
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT,
+ XML_START_NUMBERING_AT, eElement);
+ }
+
+ // element
+ SvXMLElementExport aFootnoteConfigElement(
+ GetExport(), XML_NAMESPACE_TEXT,
+ XML_NOTES_CONFIGURATION,
+ true, true);
+
+ // two element for footnote content
+ if (bIsEndnote)
+ return;
+
+ OUString sTmp;
+
+ // end notice / quo vadis
+ aAny = rFootnoteConfig->getPropertyValue(gsEndNotice);
+ aAny >>= sTmp;
+
+ if (!sTmp.isEmpty())
+ {
+ SvXMLElementExport aElem(GetExport(), XML_NAMESPACE_TEXT,
+ XML_FOOTNOTE_CONTINUATION_NOTICE_FORWARD,
+ true, false);
+ GetExport().Characters(sTmp);
+ }
+
+ // begin notice / ergo sum
+ aAny = rFootnoteConfig->getPropertyValue(gsBeginNotice);
+ aAny >>= sTmp;
+
+ if (!sTmp.isEmpty())
+ {
+ SvXMLElementExport aElem(GetExport(), XML_NAMESPACE_TEXT,
+ XML_FOOTNOTE_CONTINUATION_NOTICE_BACKWARD,
+ true, false);
+ GetExport().Characters(sTmp);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/txtimp.cxx b/xmloff/source/text/txtimp.cxx
new file mode 100644
index 0000000000..ac0e894742
--- /dev/null
+++ b/xmloff/source/text/txtimp.cxx
@@ -0,0 +1,2521 @@
+/* -*- 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 <memory>
+#include <optional>
+#include <tuple>
+#include <vector>
+
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
+#include <com/sun/star/text/ReferenceFieldSource.hpp>
+#include <com/sun/star/text/XChapterNumberingSupplier.hpp>
+#include <com/sun/star/text/XTextFrame.hpp>
+#include <com/sun/star/text/XTextFieldsSupplier.hpp>
+#include <com/sun/star/text/XTextFramesSupplier.hpp>
+#include <com/sun/star/text/XTextGraphicObjectsSupplier.hpp>
+#include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
+#include <com/sun/star/text/XFormField.hpp>
+#include <com/sun/star/ucb/XAnyCompareFactory.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/style/XStyle.hpp>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/txtstyli.hxx>
+#include <xmloff/xmlnumi.hxx>
+#include <xmloff/maptype.hxx>
+
+#include <sal/log.hxx>
+#include "txtparai.hxx"
+#include <xmloff/txtprmap.hxx>
+#include <xmloff/txtimppr.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <txtvfldi.hxx>
+#include <xmloff/i18nmap.hxx>
+#include "XMLTextListItemContext.hxx"
+#include "XMLTextListBlockContext.hxx"
+#include "XMLTextFrameContext.hxx"
+#include "XMLTextFrameHyperlinkContext.hxx"
+#include "XMLSectionImportContext.hxx"
+#include "XMLIndexTOCContext.hxx"
+#include <xmloff/XMLEventsImportContext.hxx>
+#include "XMLTrackedChangesImportContext.hxx"
+#include "XMLChangeImportContext.hxx"
+#include "XMLAutoMarkFileContext.hxx"
+#include <xmloff/ProgressBarHelper.hxx>
+
+#include "XMLCalculationSettingsContext.hxx"
+#include <XMLNumberStylesImport.hxx>
+#include <PageMasterStyleMap.hxx>
+#include <PageMasterPropHdlFactory.hxx>
+#include <PageMasterPropMapper.hxx>
+// XML import: reconstruction of assignment of paragraph style to outline levels (#i69629#)
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <txtlists.hxx>
+#include <xmloff/odffields.hxx>
+#include <comphelper/attributelist.hxx>
+
+using ::com::sun::star::ucb::XAnyCompare;
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::style;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::drawing;
+using namespace ::com::sun::star::xml::sax;
+using namespace ::com::sun::star::lang;
+using namespace ::xmloff::token;
+using namespace ::com::sun::star::ucb;
+
+
+// maximum allowed length of combined characters field
+#define MAX_COMBINED_CHARACTERS 6
+
+struct XMLTextImportHelper::Impl
+{
+ std::optional< std::vector<OUString> > m_xPrevFrmNames;
+ std::optional< std::vector<OUString> > m_xNextFrmNames;
+ std::unique_ptr<XMLTextListsHelper> m_xTextListsHelper;
+
+ rtl::Reference<SvXMLStylesContext> m_xAutoStyles;
+
+ rtl::Reference< SvXMLImportPropertyMapper > m_xParaImpPrMap;
+ rtl::Reference< SvXMLImportPropertyMapper > m_xTextImpPrMap;
+ rtl::Reference< SvXMLImportPropertyMapper > m_xFrameImpPrMap;
+ rtl::Reference< SvXMLImportPropertyMapper > m_xSectionImpPrMap;
+ rtl::Reference< SvXMLImportPropertyMapper > m_xRubyImpPrMap;
+
+ std::unique_ptr<SvI18NMap> m_xRenameMap;
+
+ /* Change and extend data structure:
+ - data structure contains candidates of paragraph styles, which
+ will be assigned to the outline style
+ - data structure contains more than one candidate for each list level
+ of the outline style (#i69629#)
+ */
+ std::unique_ptr< std::vector< OUString > []>
+ m_xOutlineStylesCandidates;
+
+ // start range, xml:id, RDFa stuff
+ typedef std::tuple<
+ uno::Reference<text::XTextRange>, OUString,
+ std::shared_ptr< ::xmloff::ParsedRDFaAttributes > >
+ BookmarkMapEntry_t;
+ /// start ranges for open bookmarks
+ std::map< OUString, BookmarkMapEntry_t > m_BookmarkStartRanges;
+
+ std::vector< OUString > m_BookmarkVector;
+
+ /// name of the last 'open' redline that started between paragraphs
+ OUString m_sOpenRedlineIdentifier;
+
+ // Used for frame deduplication, the name of the last frame imported directly before the current one
+ OUString msLastImportedFrameName;
+
+ std::map< OUString, bool > m_bBookmarkHidden;
+ std::map< OUString, OUString > m_sBookmarkCondition;
+
+ uno::Reference<text::XText> m_xText;
+ uno::Reference<text::XTextCursor> m_xCursor;
+ uno::Reference<text::XTextRange> m_xCursorAsRange;
+ uno::Reference<container::XNameContainer> m_xParaStyles;
+ uno::Reference<container::XNameContainer> m_xTextStyles;
+ uno::Reference<container::XNameContainer> m_xNumStyles;
+ uno::Reference<container::XNameContainer> m_xFrameStyles;
+ uno::Reference<container::XNameContainer> m_xPageStyles;
+ uno::Reference<container::XNameContainer> m_xCellStyles;
+ uno::Reference<container::XIndexReplace> m_xChapterNumbering;
+ uno::Reference<container::XNameAccess> m_xTextFrames;
+ uno::Reference<container::XNameAccess> m_xGraphics;
+ uno::Reference<container::XNameAccess> m_xObjects;
+ uno::Reference<lang::XMultiServiceFactory> m_xServiceFactory;
+
+ SvXMLImport & m_rSvXMLImport;
+
+ bool m_bInsertMode : 1;
+ bool m_bStylesOnlyMode : 1;
+ bool m_bBlockMode : 1;
+ bool m_bProgress : 1;
+ bool m_bOrganizerMode : 1;
+ bool m_bBodyContentStarted : 1;
+
+ /// Are we inside a <text:deletion> element (deleted redline section)
+ bool m_bInsideDeleteContext : 1;
+
+ typedef ::std::pair< OUString, OUString> field_name_type_t;
+ typedef ::std::pair< OUString, OUString > field_param_t;
+ typedef ::std::vector< field_param_t > field_params_t;
+ typedef ::std::tuple<field_name_type_t, field_params_t, uno::Reference<text::XFormField>, uno::Reference<text::XTextRange>> field_stack_item_t;
+ typedef ::std::stack< field_stack_item_t > field_stack_t;
+
+ field_stack_t m_FieldStack;
+
+ OUString m_sCellParaStyleDefault;
+
+ std::optional<std::map<OUString, OUString>> m_xCrossRefHeadingBookmarkMap;
+
+ Impl( uno::Reference<frame::XModel> const& rModel,
+ SvXMLImport & rImport,
+ bool const bInsertMode, bool const bStylesOnlyMode,
+ bool const bProgress, bool const bBlockMode,
+ bool const bOrganizerMode)
+ : m_xTextListsHelper( new XMLTextListsHelper() )
+ // XML import: reconstruction of assignment of paragraph style to outline levels (#i69629#)
+ , m_xServiceFactory( rModel, UNO_QUERY )
+ , m_rSvXMLImport( rImport )
+ , m_bInsertMode( bInsertMode )
+ , m_bStylesOnlyMode( bStylesOnlyMode )
+ , m_bBlockMode( bBlockMode )
+ , m_bProgress( bProgress )
+ , m_bOrganizerMode( bOrganizerMode )
+ , m_bBodyContentStarted( true )
+ , m_bInsideDeleteContext( false )
+ {
+ }
+ Impl(const Impl&) = delete;
+ Impl& operator=(const Impl&) = delete;
+
+ void InitOutlineStylesCandidates()
+ {
+ if (!m_xOutlineStylesCandidates)
+ {
+ size_t const size(m_xChapterNumbering->getCount());
+ m_xOutlineStylesCandidates.reset(
+ new ::std::vector< OUString >[size] );
+ }
+ }
+
+};
+
+
+uno::Reference< text::XText > & XMLTextImportHelper::GetText()
+{
+ return m_xImpl->m_xText;
+}
+
+uno::Reference< text::XTextCursor > & XMLTextImportHelper::GetCursor()
+{
+ return m_xImpl->m_xCursor;
+}
+
+uno::Reference< text::XTextRange > & XMLTextImportHelper::GetCursorAsRange()
+{
+ return m_xImpl->m_xCursorAsRange;
+}
+
+bool XMLTextImportHelper::IsInsertMode() const
+{
+ return m_xImpl->m_bInsertMode;
+}
+
+bool XMLTextImportHelper::IsStylesOnlyMode() const
+{
+ return m_xImpl->m_bStylesOnlyMode;
+}
+
+bool XMLTextImportHelper::IsBlockMode() const
+{
+ return m_xImpl->m_bBlockMode;
+}
+
+bool XMLTextImportHelper::IsOrganizerMode() const
+{
+ return m_xImpl->m_bOrganizerMode;
+}
+
+bool XMLTextImportHelper::IsProgress() const
+{
+ return m_xImpl->m_bProgress;
+}
+
+uno::Reference<container::XNameContainer> const&
+XMLTextImportHelper::GetParaStyles() const
+{
+ return m_xImpl->m_xParaStyles;
+}
+
+uno::Reference<container::XNameContainer> const&
+XMLTextImportHelper::GetTextStyles() const
+{
+ return m_xImpl->m_xTextStyles;
+}
+
+uno::Reference<container::XNameContainer> const&
+XMLTextImportHelper::GetNumberingStyles() const
+{
+ return m_xImpl->m_xNumStyles;
+}
+
+uno::Reference<container::XNameContainer> const&
+XMLTextImportHelper::GetFrameStyles() const
+{
+ return m_xImpl->m_xFrameStyles;
+}
+
+uno::Reference<container::XNameContainer> const&
+XMLTextImportHelper::GetPageStyles() const
+{
+ return m_xImpl->m_xPageStyles;
+}
+
+uno::Reference<container::XNameContainer> const&
+XMLTextImportHelper::GetCellStyles() const
+{
+ return m_xImpl->m_xCellStyles;
+}
+
+uno::Reference<container::XIndexReplace> const&
+XMLTextImportHelper::GetChapterNumbering() const
+{
+ return m_xImpl->m_xChapterNumbering;
+}
+
+rtl::Reference< SvXMLImportPropertyMapper > const&
+XMLTextImportHelper::GetParaImportPropertySetMapper() const
+{
+ return m_xImpl->m_xParaImpPrMap;
+}
+
+rtl::Reference< SvXMLImportPropertyMapper > const&
+XMLTextImportHelper::GetTextImportPropertySetMapper() const
+{
+ return m_xImpl->m_xTextImpPrMap;
+}
+
+rtl::Reference< SvXMLImportPropertyMapper > const&
+XMLTextImportHelper::GetSectionImportPropertySetMapper() const
+{
+ return m_xImpl->m_xSectionImpPrMap;
+}
+
+rtl::Reference< SvXMLImportPropertyMapper > const&
+XMLTextImportHelper::GetRubyImportPropertySetMapper() const
+{
+ return m_xImpl->m_xRubyImpPrMap;
+}
+
+void XMLTextImportHelper::SetInsideDeleteContext(bool const bNew)
+{
+ m_xImpl->m_bInsideDeleteContext = bNew;
+}
+
+bool XMLTextImportHelper::IsInsideDeleteContext() const
+{
+ return m_xImpl->m_bInsideDeleteContext;
+}
+
+SvXMLImport & XMLTextImportHelper::GetXMLImport()
+{
+ return m_xImpl->m_rSvXMLImport;
+}
+
+XMLTextListsHelper & XMLTextImportHelper::GetTextListHelper()
+{
+ return *m_xImpl->m_xTextListsHelper;
+}
+
+namespace
+{
+ class FieldParamImporter
+ {
+ public:
+ typedef std::pair<OUString,OUString> field_param_t;
+ typedef std::vector<field_param_t> field_params_t;
+ FieldParamImporter(const field_params_t* const pInParams, Reference<XNameContainer> const & xOutParams)
+ : m_pInParams(pInParams)
+ , m_xOutParams(xOutParams)
+ { };
+ void Import();
+
+ private:
+ const field_params_t* const m_pInParams;
+ Reference<XNameContainer> m_xOutParams;
+ };
+
+ void FieldParamImporter::Import()
+ {
+ ::std::vector<OUString> vListEntries;
+ ::std::map<OUString, Any> vOutParams;
+ for(const auto& rCurrent : *m_pInParams)
+ {
+ if(rCurrent.first == ODF_FORMDROPDOWN_RESULT)
+ {
+ // sal_Int32
+ vOutParams[rCurrent.first] <<= rCurrent.second.toInt32();
+ }
+ else if(rCurrent.first == ODF_FORMCHECKBOX_RESULT)
+ {
+ // bool
+ vOutParams[rCurrent.first] <<= rCurrent.second.toBoolean();
+ }
+ else if(rCurrent.first == ODF_FORMDROPDOWN_LISTENTRY)
+ {
+ // sequence
+ vListEntries.push_back(rCurrent.second);
+ }
+ else
+ vOutParams[rCurrent.first] <<= rCurrent.second;
+ }
+ if(!vListEntries.empty())
+ {
+ Sequence<OUString> vListEntriesSeq(vListEntries.size());
+ copy(vListEntries.begin(), vListEntries.end(), vListEntriesSeq.getArray());
+ vOutParams[ODF_FORMDROPDOWN_LISTENTRY] <<= vListEntriesSeq;
+ }
+ for(const auto& rCurrent : vOutParams)
+ {
+ try
+ {
+ m_xOutParams->insertByName(rCurrent.first, rCurrent.second);
+ }
+ catch(const ElementExistException&)
+ {
+ SAL_INFO("xmloff.text", "duplicate fieldmark param");
+ }
+ }
+ }
+}
+
+XMLTextImportHelper::XMLTextImportHelper(
+ uno::Reference<frame::XModel> const& rModel,
+ SvXMLImport& rImport,
+ bool const bInsertMode, bool const bStylesOnlyMode,
+ bool const bProgress, bool const bBlockMode,
+ bool const bOrganizerMode)
+ : m_xImpl( new Impl(rModel, rImport, bInsertMode, bStylesOnlyMode,
+ bProgress, bBlockMode, bOrganizerMode) )
+ , m_xBackpatcherImpl( MakeBackpatcherImpl() )
+{
+ static constexpr OUString s_PropNameDefaultListId = u"DefaultListId"_ustr;
+
+ Reference< XChapterNumberingSupplier > xCNSupplier( rModel, UNO_QUERY );
+
+ if (xCNSupplier.is())
+ {
+ // note: m_xChapterNumbering is accessed to import some fields
+ m_xImpl->m_xChapterNumbering = xCNSupplier->getChapterNumberingRules();
+ // the AutoCorrect document doesn't have a proper outline numbering
+ if (!IsBlockMode() && m_xImpl->m_xChapterNumbering.is())
+ {
+ Reference< XPropertySet > const xNumRuleProps(
+ m_xImpl->m_xChapterNumbering, UNO_QUERY);
+ if ( xNumRuleProps.is() )
+ {
+ Reference< XPropertySetInfo > xNumRulePropSetInfo(
+ xNumRuleProps->getPropertySetInfo());
+ if (xNumRulePropSetInfo.is() &&
+ xNumRulePropSetInfo->hasPropertyByName(
+ s_PropNameDefaultListId))
+ {
+ OUString sListId;
+ xNumRuleProps->getPropertyValue(s_PropNameDefaultListId)
+ >>= sListId;
+ assert( !sListId.isEmpty() &&
+ "no default list id found at chapter numbering rules instance. Serious defect." );
+ if ( !sListId.isEmpty() )
+ {
+ Reference< XNamed > const xChapterNumNamed(
+ m_xImpl->m_xChapterNumbering, UNO_QUERY);
+ if ( xChapterNumNamed.is() )
+ {
+ m_xImpl->m_xTextListsHelper->KeepListAsProcessed(
+ sListId,
+ xChapterNumNamed->getName(),
+ OUString() );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ Reference< XStyleFamiliesSupplier > xFamiliesSupp( rModel, UNO_QUERY );
+// SAL_WARN_IF( !xFamiliesSupp.is(), "xmloff", "no chapter numbering supplier" ); for clipboard there may be documents without styles
+
+ if( xFamiliesSupp.is() )
+ {
+ Reference< XNameAccess > xFamilies(xFamiliesSupp->getStyleFamilies());
+
+ static constexpr OUString aParaStyles(u"ParagraphStyles"_ustr);
+ if( xFamilies->hasByName( aParaStyles ) )
+ {
+ m_xImpl->m_xParaStyles.set(xFamilies->getByName(aParaStyles),
+ UNO_QUERY);
+ }
+
+ static constexpr OUString aCharStyles(u"CharacterStyles"_ustr);
+ if( xFamilies->hasByName( aCharStyles ) )
+ {
+ m_xImpl->m_xTextStyles.set(xFamilies->getByName(aCharStyles),
+ UNO_QUERY);
+ }
+
+ static constexpr OUString aNumStyles(u"NumberingStyles"_ustr);
+ if( xFamilies->hasByName( aNumStyles ) )
+ {
+ m_xImpl->m_xNumStyles.set(xFamilies->getByName(aNumStyles),
+ UNO_QUERY);
+ }
+
+ static constexpr OUString aFrameStyles(u"FrameStyles"_ustr);
+ if( xFamilies->hasByName( aFrameStyles ) )
+ {
+ m_xImpl->m_xFrameStyles.set(xFamilies->getByName(aFrameStyles),
+ UNO_QUERY);
+ }
+
+ static constexpr OUString aPageStyles(u"PageStyles"_ustr);
+ if( xFamilies->hasByName( aPageStyles ) )
+ {
+ m_xImpl->m_xPageStyles.set(xFamilies->getByName(aPageStyles),
+ UNO_QUERY);
+ }
+
+ static constexpr OUString aCellStyles(u"CellStyles"_ustr);
+ if( xFamilies->hasByName( aCellStyles ) )
+ {
+ m_xImpl->m_xCellStyles.set(xFamilies->getByName(aCellStyles),
+ UNO_QUERY);
+ }
+ }
+
+ Reference < XTextFramesSupplier > xTFS( rModel, UNO_QUERY );
+ if( xTFS.is() )
+ {
+ m_xImpl->m_xTextFrames.set(xTFS->getTextFrames());
+ }
+
+ Reference < XTextGraphicObjectsSupplier > xTGOS( rModel, UNO_QUERY );
+ if( xTGOS.is() )
+ {
+ m_xImpl->m_xGraphics.set(xTGOS->getGraphicObjects());
+ }
+
+ Reference < XTextEmbeddedObjectsSupplier > xTEOS( rModel, UNO_QUERY );
+ if( xTEOS.is() )
+ {
+ m_xImpl->m_xObjects.set(xTEOS->getEmbeddedObjects());
+ }
+
+ XMLPropertySetMapper *pPropMapper =
+ new XMLTextPropertySetMapper( TextPropMap::PARA, false );
+ m_xImpl->m_xParaImpPrMap =
+ new XMLTextImportPropertyMapper( pPropMapper, rImport );
+
+ pPropMapper = new XMLTextPropertySetMapper( TextPropMap::TEXT, false );
+ m_xImpl->m_xTextImpPrMap =
+ new XMLTextImportPropertyMapper( pPropMapper, rImport );
+
+ pPropMapper = new XMLTextPropertySetMapper( TextPropMap::FRAME, false );
+ m_xImpl->m_xFrameImpPrMap =
+ new XMLTextImportPropertyMapper( pPropMapper, rImport );
+
+ pPropMapper = new XMLTextPropertySetMapper( TextPropMap::SECTION, false );
+ m_xImpl->m_xSectionImpPrMap =
+ new XMLTextImportPropertyMapper( pPropMapper, rImport );
+
+ pPropMapper = new XMLTextPropertySetMapper( TextPropMap::RUBY, false );
+ m_xImpl->m_xRubyImpPrMap =
+ new SvXMLImportPropertyMapper( pPropMapper, rImport );
+}
+
+XMLTextImportHelper::~XMLTextImportHelper()
+{
+}
+
+void XMLTextImportHelper::dispose()
+{
+ if (m_xImpl->m_xAutoStyles)
+ m_xImpl->m_xAutoStyles->dispose();
+}
+
+SvXMLImportPropertyMapper *XMLTextImportHelper::CreateShapeExtPropMapper(SvXMLImport& rImport)
+{
+ XMLPropertySetMapper *pPropMapper =
+ new XMLTextPropertySetMapper( TextPropMap::FRAME, false );
+ return new XMLTextImportPropertyMapper( pPropMapper, rImport );
+}
+
+SvXMLImportPropertyMapper *XMLTextImportHelper::CreateParaExtPropMapper(SvXMLImport& rImport)
+{
+ XMLPropertySetMapper *pPropMapper =
+ new XMLTextPropertySetMapper( TextPropMap::SHAPE_PARA, false );
+ return new XMLTextImportPropertyMapper( pPropMapper, rImport );
+}
+
+SvXMLImportPropertyMapper *XMLTextImportHelper::CreateParaDefaultExtPropMapper(SvXMLImport& rImport)
+{
+ XMLPropertySetMapper* pPropMapper =
+ new XMLTextPropertySetMapper( TextPropMap::SHAPE_PARA, false );
+ SvXMLImportPropertyMapper* pImportMapper = new XMLTextImportPropertyMapper( pPropMapper, rImport );
+
+ pPropMapper =
+ new XMLTextPropertySetMapper( TextPropMap::TEXT_ADDITIONAL_DEFAULTS, false );
+ pImportMapper->ChainImportMapper( new XMLTextImportPropertyMapper( pPropMapper, rImport ) );
+
+ return pImportMapper;
+}
+
+SvXMLImportPropertyMapper*
+ XMLTextImportHelper::CreateTableDefaultExtPropMapper(
+ SvXMLImport& rImport )
+{
+ XMLPropertySetMapper *pPropMapper =
+ new XMLTextPropertySetMapper( TextPropMap::TABLE_DEFAULTS, false );
+ return new SvXMLImportPropertyMapper( pPropMapper, rImport );
+}
+
+SvXMLImportPropertyMapper*
+ XMLTextImportHelper::CreateTableRowDefaultExtPropMapper(
+ SvXMLImport& rImport )
+{
+ XMLPropertySetMapper *pPropMapper =
+ new XMLTextPropertySetMapper( TextPropMap::TABLE_ROW_DEFAULTS, false );
+ return new SvXMLImportPropertyMapper( pPropMapper, rImport );
+}
+
+SvXMLImportPropertyMapper*
+ XMLTextImportHelper::CreateTableCellExtPropMapper(
+ SvXMLImport& rImport )
+{
+ XMLPropertySetMapper *pPropMapper =
+ new XMLTextPropertySetMapper( TextPropMap::CELL, false );
+ return new XMLTextImportPropertyMapper( pPropMapper, rImport );
+}
+
+SvXMLImportPropertyMapper*
+XMLTextImportHelper::CreateDrawingPageExtPropMapper(SvXMLImport& rImport)
+{
+ rtl::Reference<XMLPropertyHandlerFactory> const pFactory(new XMLPageMasterPropHdlFactory);
+ XMLPropertySetMapper *const pPropMapper(
+ new XMLPropertySetMapper(g_XMLPageMasterDrawingPageStyleMap, pFactory, false));
+ return new SvXMLImportPropertyMapper(pPropMapper, rImport);
+}
+
+void XMLTextImportHelper::SetCursor( const Reference < XTextCursor > & rCursor )
+{
+ m_xImpl->m_xCursor.set(rCursor);
+ m_xImpl->m_xText.set(rCursor->getText());
+ m_xImpl->m_xCursorAsRange = rCursor;
+}
+
+void XMLTextImportHelper::ResetCursor()
+{
+ m_xImpl->m_xCursor.clear();
+ m_xImpl->m_xText.clear();
+ m_xImpl->m_xCursorAsRange.clear();
+}
+
+
+bool XMLTextImportHelper::HasFrameByName( const OUString& rName ) const
+{
+ return (m_xImpl->m_xTextFrames.is() &&
+ m_xImpl->m_xTextFrames->hasByName(rName))
+ || (m_xImpl->m_xGraphics.is() &&
+ m_xImpl->m_xGraphics->hasByName(rName))
+ || (m_xImpl->m_xObjects.is() &&
+ m_xImpl->m_xObjects->hasByName(rName));
+}
+
+bool XMLTextImportHelper::IsDuplicateFrame(const OUString& sName, sal_Int32 nX, sal_Int32 nY, sal_Int32 nWidth, sal_Int32 nHeight) const
+{
+ if (HasFrameByName(sName))
+ {
+ uno::Reference<beans::XPropertySet> xOtherFrame;
+ if(m_xImpl->m_xTextFrames.is() && m_xImpl->m_xTextFrames->hasByName(sName))
+ xOtherFrame.set(m_xImpl->m_xTextFrames->getByName(sName), uno::UNO_QUERY);
+ else if(m_xImpl->m_xGraphics.is() && m_xImpl->m_xGraphics->hasByName(sName))
+ xOtherFrame.set(m_xImpl->m_xGraphics->getByName(sName), uno::UNO_QUERY);
+ else if (m_xImpl->m_xObjects.is() && m_xImpl->m_xObjects->hasByName(sName))
+ xOtherFrame.set(m_xImpl->m_xObjects->getByName(sName), uno::UNO_QUERY);
+
+ Reference< XPropertySetInfo > xPropSetInfo = xOtherFrame->getPropertySetInfo();
+ if(xPropSetInfo->hasPropertyByName("Width"))
+ {
+ sal_Int32 nOtherWidth = 0;
+ xOtherFrame->getPropertyValue("Width") >>= nOtherWidth;
+ if(nWidth != nOtherWidth)
+ return false;
+ }
+
+ if (xPropSetInfo->hasPropertyByName("Height"))
+ {
+ sal_Int32 nOtherHeight = 0;
+ xOtherFrame->getPropertyValue("Height") >>= nOtherHeight;
+ if (nHeight != nOtherHeight)
+ return false;
+ }
+
+ if (xPropSetInfo->hasPropertyByName("HoriOrientPosition"))
+ {
+ sal_Int32 nOtherX = 0;
+ xOtherFrame->getPropertyValue("HoriOrientPosition") >>= nOtherX;
+ if (nX != nOtherX)
+ return false;
+ }
+
+ if (xPropSetInfo->hasPropertyByName("VertOrientPosition"))
+ {
+ sal_Int32 nOtherY = 0;
+ xOtherFrame->getPropertyValue("VertOrientPosition") >>= nOtherY;
+ if (nY != nOtherY)
+ return false;
+ }
+
+ // In some case, position is not defined for frames, so check whether the two frames follow each other (are anchored to the same position)
+ return m_xImpl->msLastImportedFrameName == sName;
+ }
+ return false;
+}
+
+void XMLTextImportHelper::StoreLastImportedFrameName(const OUString& rName)
+{
+ m_xImpl->msLastImportedFrameName = rName;
+}
+
+void XMLTextImportHelper::ClearLastImportedTextFrameName()
+{
+ m_xImpl->msLastImportedFrameName.clear();
+}
+
+void XMLTextImportHelper::InsertString( const OUString& rChars )
+{
+ assert(m_xImpl->m_xText.is());
+ assert(m_xImpl->m_xCursorAsRange.is());
+ if (m_xImpl->m_xText.is())
+ {
+ m_xImpl->m_xText->insertString(m_xImpl->m_xCursorAsRange,
+ rChars, false);
+ }
+}
+
+void XMLTextImportHelper::InsertString( std::u16string_view rChars,
+ bool& rIgnoreLeadingSpace )
+{
+ assert(m_xImpl->m_xText.is());
+ assert(m_xImpl->m_xCursorAsRange.is());
+ if (!m_xImpl->m_xText.is())
+ return;
+
+ sal_Int32 nLen = rChars.size();
+ OUStringBuffer sChars( nLen );
+
+ for( sal_Int32 i=0; i < nLen; i++ )
+ {
+ sal_Unicode c = rChars[i];
+ switch( c )
+ {
+ case 0x20:
+ case 0x09:
+ case 0x0a:
+ case 0x0d:
+ if( !rIgnoreLeadingSpace )
+ sChars.append( u' ' );
+ rIgnoreLeadingSpace = true;
+ break;
+ default:
+ rIgnoreLeadingSpace = false;
+ sChars.append( c );
+ break;
+ }
+ }
+ m_xImpl->m_xText->insertString(m_xImpl->m_xCursorAsRange,
+ sChars.makeStringAndClear(), false);
+}
+
+void XMLTextImportHelper::InsertControlCharacter( sal_Int16 nControl )
+{
+ assert(m_xImpl->m_xText.is());
+ assert(m_xImpl->m_xCursorAsRange.is());
+ if (m_xImpl->m_xText.is())
+ {
+ m_xImpl->m_xText->insertControlCharacter(
+ m_xImpl->m_xCursorAsRange, nControl, false);
+ }
+}
+
+void XMLTextImportHelper::InsertTextContent(
+ Reference < XTextContent > const & xContent )
+{
+ assert(m_xImpl->m_xText.is());
+ assert(m_xImpl->m_xCursorAsRange.is());
+ if (m_xImpl->m_xText.is())
+ {
+ // note: this may throw IllegalArgumentException and callers handle it
+ m_xImpl->m_xText->insertTextContent( m_xImpl->m_xCursorAsRange, xContent, false);
+ }
+}
+
+void XMLTextImportHelper::DeleteParagraph()
+{
+ assert(m_xImpl->m_xText.is());
+ assert(m_xImpl->m_xCursor.is());
+ assert(m_xImpl->m_xCursorAsRange.is());
+
+ bool bDelete = true;
+ Reference < XEnumerationAccess > const xEnumAccess(
+ m_xImpl->m_xCursor, UNO_QUERY);
+ if( xEnumAccess.is() )
+ {
+ Reference < XEnumeration > xEnum(xEnumAccess->createEnumeration());
+ SAL_WARN_IF(!xEnum->hasMoreElements(), "xmloff.text",
+ "empty text enumeration");
+ if( xEnum->hasMoreElements() )
+ {
+ Reference < XComponent > xComp( xEnum->nextElement(), UNO_QUERY );
+ assert(xComp.is());
+ if( xComp.is() )
+ {
+ xComp->dispose();
+ bDelete = false;
+ }
+ }
+ }
+ if( bDelete )
+ {
+ if (m_xImpl->m_xCursor->goLeft( 1, true ))
+ {
+ m_xImpl->m_xText->insertString(m_xImpl->m_xCursorAsRange,
+ "", true);
+ }
+ }
+}
+
+OUString XMLTextImportHelper::ConvertStarFonts( const OUString& rChars,
+ const OUString& rStyleName,
+ sal_uInt8& rFlags,
+ bool bPara,
+ SvXMLImport& rImport ) const
+{
+ OUStringBuffer sChars( rChars );
+ bool bConverted = false;
+ for( sal_Int32 j=0; j<rChars.getLength(); j++ )
+ {
+ sal_Unicode c = rChars[j];
+ if( c >= 0xf000 && c <= 0xf0ff )
+ {
+ if( (rFlags & CONV_STAR_FONT_FLAGS_VALID) == 0 )
+ {
+ XMLTextStyleContext *pStyle = nullptr;
+ XmlStyleFamily nFamily = bPara ? XmlStyleFamily::TEXT_PARAGRAPH
+ : XmlStyleFamily::TEXT_TEXT;
+ if (!rStyleName.isEmpty() && m_xImpl->m_xAutoStyles.is())
+ {
+ const SvXMLStyleContext* pTempStyle =
+ m_xImpl->m_xAutoStyles->
+ FindStyleChildContext( nFamily, rStyleName,
+ true );
+ pStyle = const_cast<XMLTextStyleContext*>( dynamic_cast< const XMLTextStyleContext* >(pTempStyle));
+ }
+
+ if( pStyle )
+ {
+ sal_Int32 nCount = pStyle->GetProperties_().size();
+ if( nCount )
+ {
+ rtl::Reference < SvXMLImportPropertyMapper > xImpPrMap =
+ m_xImpl->m_xAutoStyles->GetImportPropertyMapper(nFamily);
+ if( xImpPrMap.is() )
+ {
+ rtl::Reference<XMLPropertySetMapper> rPropMapper =
+ xImpPrMap->getPropertySetMapper();
+ for( sal_Int32 i=0; i < nCount; i++ )
+ {
+ const XMLPropertyState& rProp = pStyle->GetProperties_()[i];
+ sal_Int32 nIdx = rProp.mnIndex;
+ sal_uInt32 nContextId = rPropMapper->GetEntryContextId(nIdx);
+ if( CTF_FONTFAMILYNAME == nContextId )
+ {
+ rFlags &= ~(CONV_FROM_STAR_BATS|CONV_FROM_STAR_MATH);
+ OUString sFontName;
+ rProp.maValue >>= sFontName;
+ if( sFontName.equalsIgnoreAsciiCase( "StarBats" ) )
+ rFlags |= CONV_FROM_STAR_BATS;
+ else if( sFontName.equalsIgnoreAsciiCase( "StarMath" ) )
+ rFlags |= CONV_FROM_STAR_MATH;
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ rFlags |= CONV_STAR_FONT_FLAGS_VALID;
+ }
+ if( (rFlags & CONV_FROM_STAR_BATS ) != 0 )
+ {
+ sChars[j] = rImport.ConvStarBatsCharToStarSymbol( c );
+ bConverted = true;
+ }
+ else if( (rFlags & CONV_FROM_STAR_MATH ) != 0 )
+ {
+ sChars[j] = rImport.ConvStarMathCharToStarSymbol( c );
+ bConverted = true;
+ }
+ }
+ }
+
+ return bConverted ? sChars.makeStringAndClear() : rChars;
+}
+
+/* Helper method to determine, if a paragraph style has a list style (inclusive
+ an empty one) inherits a list style (inclusive an empty one) from one of its parents (#i69629#)
+*/
+/* Apply special case, that found list style equals the chapter numbering, also
+ to the found list styles of the parent styles. (#i73973#)
+*/
+static bool lcl_HasListStyle( const OUString& sStyleName,
+ const Reference < XNameContainer >& xParaStyles,
+ SvXMLImport const & rImport,
+ const OUString& sNumberingStyleName,
+ std::u16string_view sOutlineStyleName )
+{
+ bool bRet( false );
+
+ if ( !xParaStyles->hasByName( sStyleName ) )
+ {
+ // error case
+ return true;
+ }
+
+ Reference< XPropertyState > xPropState( xParaStyles->getByName( sStyleName ),
+ UNO_QUERY );
+ if ( !xPropState.is() )
+ {
+ // error case
+ return false;
+ }
+
+ if ( xPropState->getPropertyState( sNumberingStyleName ) == PropertyState_DIRECT_VALUE )
+ {
+ // list style found
+ bRet = true;
+ // special case: the set list style equals the chapter numbering
+ Reference< XPropertySet > xPropSet( xPropState, UNO_QUERY );
+ if ( xPropSet.is() )
+ {
+ OUString sListStyle;
+ xPropSet->getPropertyValue( sNumberingStyleName ) >>= sListStyle;
+ if ( !sListStyle.isEmpty() &&
+ sListStyle == sOutlineStyleName )
+ {
+ bRet = false;
+ }
+ }
+ }
+ else
+ {
+ // Tools.Outline settings lost on Save (#i77708#)
+ sal_Int32 nUPD( 0 );
+ sal_Int32 nBuild( 0 );
+ // Don't use UPD for versioning: xmloff/source/text/txtstyli.cxx and txtimp.cxx (#i86058#)
+ const bool bBuildIdFound = rImport.getBuildIds( nUPD, nBuild );
+ // search list style at parent
+ Reference<XStyle> xStyle( xPropState, UNO_QUERY );
+ while ( xStyle.is() )
+ {
+ OUString aParentStyle( xStyle->getParentStyle() );
+ if ( !aParentStyle.isEmpty() )
+ {
+ aParentStyle =
+ rImport.GetStyleDisplayName( XmlStyleFamily::TEXT_PARAGRAPH,
+ aParentStyle );
+ }
+ if ( aParentStyle.isEmpty() || !xParaStyles->hasByName( aParentStyle ) )
+ {
+ // no list style found
+ break;
+ }
+ else
+ {
+ xPropState.set( xParaStyles->getByName( aParentStyle ),
+ UNO_QUERY );
+ if ( !xPropState.is() )
+ {
+ // error case
+ return true;
+ }
+ if ( xPropState->getPropertyState( sNumberingStyleName ) == PropertyState_DIRECT_VALUE )
+ {
+ // list style found
+ bRet = true;
+ // Special case: the found list style equals the chapter numbering (#i73973#)
+ Reference< XPropertySet > xPropSet( xPropState, UNO_QUERY );
+ if ( xPropSet.is() )
+ {
+ OUString sListStyle;
+ xPropSet->getPropertyValue( sNumberingStyleName ) >>= sListStyle;
+ if ( !sListStyle.isEmpty() &&
+ sListStyle == sOutlineStyleName )
+ {
+ bRet = false;
+ }
+ // Special handling for text documents from OOo version prior OOo 2.4 (#i77708#)
+ /* Check explicitly on certain versions and on import of
+ text documents in OpenOffice.org file format (#i86058#)
+ */
+ else if ( sListStyle.isEmpty() &&
+ ( rImport.IsTextDocInOOoFileFormat() ||
+ ( bBuildIdFound &&
+ ( ( nUPD == 641 ) || ( nUPD == 645 ) || // prior OOo 2.0
+ ( nUPD == 680 && nBuild <= 9238 ) ) ) ) ) // OOo 2.0 - OOo 2.3.1
+ {
+ bRet = false;
+ }
+ }
+ break;
+ }
+ else
+ {
+ // search list style at parent
+ Reference<XStyle> xParentStyle(xPropState, UNO_QUERY);
+ if (xStyle == xParentStyle)
+ {
+ // error case
+ return true;
+ }
+ xStyle = xParentStyle;
+ }
+ }
+ }
+ }
+
+ return bRet;
+}
+
+namespace {
+
+auto IsPropertySet(uno::Reference<container::XNameContainer> const& rxParaStyles,
+ uno::Reference<beans::XPropertySet> const& rxPropSet,
+ OUString const& rProperty)
+{
+ uno::Reference<beans::XPropertyState> const xPropState(rxPropSet, uno::UNO_QUERY);
+ // note: this is true only if it is set in automatic style
+ if (xPropState->getPropertyState(rProperty) == beans::PropertyState_DIRECT_VALUE)
+ {
+ return true;
+ }
+ // check if it is set by any parent common style
+ OUString style;
+ rxPropSet->getPropertyValue("ParaStyleName") >>= style;
+ while (!style.isEmpty() && rxParaStyles.is() && rxParaStyles->hasByName(style))
+ {
+ uno::Reference<style::XStyle> const xStyle(rxParaStyles->getByName(style), uno::UNO_QUERY);
+ assert(xStyle.is());
+ uno::Reference<beans::XPropertyState> const xStyleProps(xStyle, uno::UNO_QUERY);
+ if (xStyleProps->getPropertyState(rProperty) == beans::PropertyState_DIRECT_VALUE)
+ {
+ return true;
+ }
+ style = xStyle->getParentStyle();
+ }
+ return false;
+};
+
+} // namespace
+
+OUString XMLTextImportHelper::SetStyleAndAttrs(
+ SvXMLImport & rImport,
+ const Reference < XTextCursor >& rCursor,
+ const OUString& rStyleName,
+ bool bPara,
+ bool bOutlineLevelAttrFound,
+ sal_Int8 nOutlineLevel,
+ // Numberings/Bullets in table not visible after save/reload (#i80724#)
+ bool bSetListAttrs,
+ bool bOutlineContentVisible)
+{
+ static constexpr OUString s_NumberingRules = u"NumberingRules"_ustr;
+ static constexpr OUString s_NumberingIsNumber = u"NumberingIsNumber"_ustr;
+ static constexpr OUString s_NumberingLevel = u"NumberingLevel"_ustr;
+ static constexpr OUString s_ParaIsNumberingRestart = u"ParaIsNumberingRestart"_ustr;
+ static constexpr OUString s_NumberingStartValue = u"NumberingStartValue"_ustr;
+ static constexpr OUString s_PropNameListId = u"ListId"_ustr;
+ static constexpr OUString s_PageDescName = u"PageDescName"_ustr;
+ static constexpr OUString s_OutlineLevel = u"OutlineLevel"_ustr;
+
+ const XmlStyleFamily nFamily = bPara ? XmlStyleFamily::TEXT_PARAGRAPH
+ : XmlStyleFamily::TEXT_TEXT;
+ XMLTextStyleContext *pStyle = nullptr;
+ OUString sStyleName( rStyleName );
+ if (!sStyleName.isEmpty() && m_xImpl->m_xAutoStyles.is())
+ {
+ const SvXMLStyleContext* pTempStyle =
+ m_xImpl->m_xAutoStyles->FindStyleChildContext( nFamily, sStyleName, true );
+ pStyle = const_cast<XMLTextStyleContext*>(dynamic_cast< const XMLTextStyleContext* >(pTempStyle));
+ }
+ if( pStyle )
+ sStyleName = pStyle->GetParentName();
+
+ Reference < XPropertySet > xPropSet( rCursor, UNO_QUERY );
+ Reference< XPropertySetInfo > xPropSetInfo(
+ xPropSet->getPropertySetInfo());
+
+ // style
+ if( !sStyleName.isEmpty() )
+ {
+ sStyleName = rImport.GetStyleDisplayName( nFamily, sStyleName );
+ const OUString rPropName = bPara ? OUString("ParaStyleName") : OUString("CharStyleName");
+ const Reference < XNameContainer > & rStyles = bPara
+ ? m_xImpl->m_xParaStyles
+ : m_xImpl->m_xTextStyles;
+ if( rStyles.is() &&
+ xPropSetInfo->hasPropertyByName( rPropName ) &&
+ rStyles->hasByName( sStyleName ) )
+ {
+ xPropSet->setPropertyValue( rPropName, Any(sStyleName) );
+ }
+ else
+ sStyleName.clear();
+ }
+
+ /* The outline level needs to be only applied as list level, if the heading
+ is not inside a list and if it by default applies the outline style. (#i70748#)
+ */
+ bool bApplyOutlineLevelAsListLevel( false );
+ // Numberings/Bullets in table not visible after save/reload (#i80724#)
+ if (bSetListAttrs && bPara
+ && xPropSetInfo->hasPropertyByName( s_NumberingRules))
+ {
+ // Set numbering rules
+ Reference< XIndexReplace > const xNumRules(
+ xPropSet->getPropertyValue(s_NumberingRules), UNO_QUERY);
+
+ XMLTextListBlockContext * pListBlock(nullptr);
+ XMLTextListItemContext * pListItem(nullptr);
+ XMLNumberedParaContext * pNumberedParagraph(nullptr);
+ GetTextListHelper().ListContextTop(
+ pListBlock, pListItem, pNumberedParagraph);
+
+ assert(!(pListBlock && pNumberedParagraph) && "XMLTextImportHelper::"
+ "SetStyleAndAttrs: both list and numbered-paragraph???");
+
+ Reference < XIndexReplace > xNewNumRules;
+ sal_Int8 nLevel(-1);
+ OUString sListId;
+ sal_Int16 nStartValue(-1);
+ bool bNumberingIsNumber(true);
+ // Assure that list style of automatic paragraph style is applied at paragraph. (#i101349#)
+ bool bApplyNumRules(pStyle && pStyle->IsListStyleSet());
+ bool bApplyNumRulesFix(false);
+
+ if (pListBlock) {
+ // the xNumRules is always created, even without a list-style-name
+ if (!bApplyNumRules
+ && (pListBlock->HasListStyleName()
+ || (pListItem != nullptr && pListItem->HasNumRulesOverride())))
+ {
+ bApplyNumRules = true; // tdf#114287
+ bApplyNumRulesFix = rImport.isGeneratorVersionOlderThan(SvXMLImport::AOO_4x, SvXMLImport::LO_76);
+ }
+
+ if (!pListItem) {
+ bNumberingIsNumber = false; // list-header
+ }
+
+ // consider text:style-override property of <text:list-item>
+ xNewNumRules.set(
+ (pListItem != nullptr && pListItem->HasNumRulesOverride())
+ ? pListItem->GetNumRulesOverride()
+ : pListBlock->GetNumRules() );
+ nLevel = static_cast<sal_Int8>(pListBlock->GetLevel());
+
+ if ( pListItem && pListItem->HasStartValue() ) {
+ nStartValue = pListItem->GetStartValue();
+ }
+
+ // Inconsistent behavior regarding lists (#i92811#)
+ sListId = m_xImpl->m_xTextListsHelper->GetListIdForListBlock(
+ *pListBlock);
+ }
+ else if (pNumberedParagraph)
+ {
+ xNewNumRules.set(pNumberedParagraph->GetNumRules());
+ nLevel = static_cast<sal_Int8>(pNumberedParagraph->GetLevel());
+ sListId = pNumberedParagraph->GetListId();
+ nStartValue = pNumberedParagraph->GetStartValue();
+ }
+
+
+ if (pListBlock || pNumberedParagraph)
+ {
+ if (!bApplyNumRules || bApplyNumRulesFix)
+ {
+ bool bSameNumRules = xNewNumRules == xNumRules;
+ if( !bSameNumRules && xNewNumRules.is() && xNumRules.is() )
+ {
+ // If the interface pointers are different, then this does
+ // not mean that the num rules are different. Further tests
+ // are required then. However, if only one num rule is
+ // set, no tests are required of course.
+ Reference< XNamed > xNewNamed( xNewNumRules, UNO_QUERY );
+ Reference< XNamed > xNamed( xNumRules, UNO_QUERY );
+ if( xNewNamed.is() && xNamed.is() )
+ {
+ bSameNumRules = xNewNamed->getName() == xNamed->getName();
+ }
+ else
+ {
+ Reference< XAnyCompare > xNumRuleCompare( xNumRules, UNO_QUERY );
+ if( xNumRuleCompare.is() )
+ {
+ bSameNumRules = (xNumRuleCompare->compare( Any(xNumRules), Any(xNewNumRules) ) == 0);
+ }
+ }
+ }
+ if (!bApplyNumRules)
+ {
+ bApplyNumRules = !bSameNumRules;
+ }
+ if (!bSameNumRules)
+ {
+ bApplyNumRulesFix = false;
+ }
+ }
+
+ if ( bApplyNumRules )
+ {
+ // #102607# This may except when xNewNumRules contains
+ // a Writer-NumRule-Implementation bug gets applied to
+ // a shape. Since this may occur inside a document
+ // (e.g. when edited), this must be handled
+ // gracefully.
+ try
+ {
+ xPropSet->setPropertyValue(
+ s_NumberingRules, Any(xNewNumRules) );
+ if (bApplyNumRulesFix)
+ { // tdf#156146 override list margins for bug compatibility
+ if (IsPropertySet(m_xImpl->m_xParaStyles, xPropSet, "ParaLeftMargin"))
+ {
+ uno::Any const left(xPropSet->getPropertyValue("ParaLeftMargin"));
+ xPropSet->setPropertyValue("ParaLeftMargin", left);
+ }
+ if (IsPropertySet(m_xImpl->m_xParaStyles, xPropSet, "ParaFirstLineIndent"))
+ {
+ uno::Any const first(xPropSet->getPropertyValue("ParaFirstLineIndent"));
+ xPropSet->setPropertyValue("ParaFirstLineIndent", first);
+ }
+ }
+ }
+ catch(const Exception&)
+ {
+ ; // I would really like to use a warning here,
+ // but I can't access the XMLErrorHandler from
+ // here.
+ }
+ }
+
+ if (!bNumberingIsNumber &&
+ xPropSetInfo->hasPropertyByName(s_NumberingIsNumber))
+ {
+ xPropSet->setPropertyValue(s_NumberingIsNumber, Any(false));
+ }
+
+ xPropSet->setPropertyValue( s_NumberingLevel, Any(nLevel) );
+
+ if( pListBlock && pListBlock->IsRestartNumbering() )
+ {
+ // TODO: property missing
+ if (xPropSetInfo->hasPropertyByName(s_ParaIsNumberingRestart))
+ {
+ xPropSet->setPropertyValue(s_ParaIsNumberingRestart,
+ Any(true) );
+ }
+ pListBlock->ResetRestartNumbering();
+ }
+
+ if ( 0 <= nStartValue &&
+ xPropSetInfo->hasPropertyByName(s_NumberingStartValue))
+ {
+ xPropSet->setPropertyValue(s_NumberingStartValue,
+ Any(nStartValue));
+ }
+
+ if (xPropSetInfo->hasPropertyByName(s_PropNameListId))
+ {
+ if (!sListId.isEmpty()) {
+ xPropSet->setPropertyValue(s_PropNameListId,
+ Any(sListId) );
+ }
+ }
+
+ GetTextListHelper().SetListItem( nullptr );
+ }
+ else
+ {
+ /* If the paragraph is not in a list but its style, remove it from
+ the list. Do not remove it, if the list of the style is
+ the chapter numbering rule.
+ */
+ if( xNumRules.is() )
+ {
+ bool bRemove( true );
+ // Special handling for document from OOo 2.x (#i70748#)
+ sal_Int32 nUPD( 0 );
+ sal_Int32 nBuild( 0 );
+ const bool bBuildIdFound = rImport.getBuildIds( nUPD, nBuild );
+ if ( ( bBuildIdFound && nUPD == 680 ) ||
+ !pStyle || !pStyle->IsListStyleSet() )
+ {
+ if (m_xImpl->m_xChapterNumbering.is())
+ {
+ Reference< XNamed > xNumNamed( xNumRules, UNO_QUERY );
+ Reference< XNamed > const xChapterNumNamed (
+ m_xImpl->m_xChapterNumbering, UNO_QUERY);
+ if ( xNumNamed.is() && xChapterNumNamed.is() &&
+ xNumNamed->getName() == xChapterNumNamed->getName() )
+ {
+ bRemove = false;
+ // RFE: inserting headings into text documents (#i70748#)
+ bApplyOutlineLevelAsListLevel = true;
+ }
+ }
+ }
+ else
+ {
+ SAL_INFO_IF(!pStyle->GetListStyle().isEmpty(),
+ "xmloff.text",
+ "automatic paragraph style with list style name, but paragraph not in list???");
+ }
+ if ( bRemove )
+ {
+ xPropSet->setPropertyValue( s_NumberingRules, Any() );
+ }
+ }
+ }
+ }
+
+ // hard paragraph properties
+ if( pStyle )
+ {
+ pStyle->FillPropertySet( xPropSet );
+ if( bPara && pStyle->HasMasterPageName() &&
+ xPropSetInfo->hasPropertyByName(s_PageDescName))
+ {
+ OUString sDisplayName(
+ rImport.GetStyleDisplayName(
+ XmlStyleFamily::MASTER_PAGE,
+ pStyle->GetMasterPageName()) );
+ if( sDisplayName.isEmpty() ||
+ (m_xImpl->m_xPageStyles.is() &&
+ m_xImpl->m_xPageStyles->hasByName( sDisplayName)))
+ {
+ xPropSet->setPropertyValue(s_PageDescName,
+ Any(sDisplayName));
+ }
+ }
+ if( bPara && !pStyle->GetDropCapStyleName().isEmpty() &&
+ m_xImpl->m_xTextStyles.is())
+ {
+ OUString sDisplayName(
+ rImport.GetStyleDisplayName(
+ XmlStyleFamily::TEXT_TEXT,
+ pStyle->GetDropCapStyleName()) );
+ if (m_xImpl->m_xTextStyles->hasByName(sDisplayName) &&
+ xPropSetInfo->hasPropertyByName("DropCapCharStyleName"))
+ {
+ xPropSet->setPropertyValue("DropCapCharStyleName", Any(sDisplayName));
+ }
+ }
+
+ // combined characters special treatment
+ if (!bPara && pStyle->HasCombinedCharactersLetter())
+ {
+ // insert combined characters text field
+ if (m_xImpl->m_xServiceFactory.is())
+ {
+ uno::Reference<beans::XPropertySet> const xTmp(
+ m_xImpl->m_xServiceFactory->createInstance(
+ "com.sun.star.text.TextField.CombinedCharacters"), UNO_QUERY);
+ if( xTmp.is() )
+ {
+ // fix cursor if larger than possible for
+ // combined characters field
+ if (rCursor->getString().getLength() >
+ MAX_COMBINED_CHARACTERS)
+ {
+ rCursor->gotoRange(rCursor->getStart(), false);
+ rCursor->goRight(MAX_COMBINED_CHARACTERS, true);
+ }
+
+ // set field value (the combined character string)
+ xTmp->setPropertyValue("Content",
+ Any(rCursor->getString()));
+
+ // insert the field over it's original text
+ Reference<XTextContent> xTextContent(xTmp, UNO_QUERY);
+ if (m_xImpl->m_xText.is() && rCursor.is())
+ {
+ // #i107225# the combined characters need to be inserted first
+ // the selected text has to be removed afterwards
+ m_xImpl->m_xText->insertTextContent( rCursor->getStart(), xTextContent, true );
+
+ if( !rCursor->getString().isEmpty() )
+ {
+ try
+ {
+ uno::Reference< text::XTextCursor > xCrsr = rCursor->getText()->createTextCursorByRange( rCursor->getStart() );
+ xCrsr->goLeft( 1, true );
+ uno::Reference< beans::XPropertySet> xCrsrProperties( xCrsr, uno::UNO_QUERY_THROW );
+ //the hard properties of the removed text need to be applied to the combined characters field
+ pStyle->FillPropertySet( xCrsrProperties );
+ xCrsr->collapseToEnd();
+ xCrsr->gotoRange( rCursor->getEnd(), true );
+ xCrsr->setString( OUString() );
+ }
+ catch(const uno::Exception&)
+ {
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // outline level; set after list style has been set
+ // Complete re-worked and corrected: (#i53198#)
+ // - set outline level at paragraph
+ // - set numbering level at paragraph, if none is already set
+ // - assure that style is marked as an outline style for the corresponding
+ // outline level.
+ // - DO NOT set type of numbering rule to outline.
+ // - DO NOT set numbering rule directly at the paragraph.
+
+ // Some minor rework and adjust access to paragraph styles (#i70748#)
+ if ( bPara )
+ {
+ // Headings not numbered anymore in 3.1 (#i103817#)
+ sal_Int16 nCurrentOutlineLevelInheritedFromParagraphStyle = 0;
+ const bool bHasOutlineLevelProp(
+ xPropSetInfo->hasPropertyByName(s_OutlineLevel));
+ if ( bHasOutlineLevelProp )
+ {
+ xPropSet->getPropertyValue(s_OutlineLevel)
+ >>= nCurrentOutlineLevelInheritedFromParagraphStyle;
+ }
+ if ( nOutlineLevel > 0 )
+ {
+ if ( bHasOutlineLevelProp )
+ {
+ // In case that the value equals the value of its paragraph style
+ // attribute outline level, the paragraph attribute value is left unset
+ if ( nCurrentOutlineLevelInheritedFromParagraphStyle != nOutlineLevel )
+ {
+ xPropSet->setPropertyValue( s_OutlineLevel,
+ Any( static_cast<sal_Int16>(nOutlineLevel) ) );
+ }
+ }
+ if (!bOutlineContentVisible)
+ {
+ uno::Sequence<beans::PropertyValue> aGrabBag;
+ xPropSet->getPropertyValue("ParaInteropGrabBag") >>= aGrabBag;
+ sal_Int32 length = aGrabBag.getLength();
+ aGrabBag.realloc(length + 1);
+ auto pGrabBag = aGrabBag.getArray();
+ pGrabBag[length].Name = "OutlineContentVisibleAttr";
+ pGrabBag[length].Value <<= bool(bOutlineContentVisible);
+ xPropSet->setPropertyValue("ParaInteropGrabBag", uno::Any(aGrabBag));
+ }
+ // RFE: inserting headings into text documents (#i70748#)
+ if ( bApplyOutlineLevelAsListLevel )
+ {
+ sal_Int16 nNumLevel = -1;
+ xPropSet->getPropertyValue( s_NumberingLevel ) >>= nNumLevel;
+ if ( nNumLevel == -1 ||
+ nNumLevel != (nOutlineLevel - 1) )
+ {
+ xPropSet->setPropertyValue( s_NumberingLevel,
+ Any( static_cast<sal_Int8>(nOutlineLevel - 1) ) );
+ }
+ }
+ /* Correction: (#i69629#)
+ - for text document from version OOo 2.0.4/SO 8 PU4 and earlier
+ the paragraph style of a heading should be assigned to the
+ corresponding list level of the outline style.
+ - for other text documents the paragraph style of a heading is only
+ a candidate for an assignment to the list level of the outline
+ style, if it has no direct list style property and (if exists) the
+ automatic paragraph style has also no direct list style set.
+ */
+ if (m_xImpl->m_xParaStyles.is() && m_xImpl->m_xParaStyles->hasByName(sStyleName))
+ {
+ bool bOutlineStyleCandidate( false );
+
+ sal_Int32 nUPD( 0 );
+ sal_Int32 nBuild( 0 );
+ const bool bBuildIdFound = rImport.getBuildIds( nUPD, nBuild );
+ // Lost outline numbering in master document (#i73509#)
+ // Check explicitly on certain versions (#i86058#)
+ if ( rImport.IsTextDocInOOoFileFormat() ||
+ ( bBuildIdFound &&
+ ( nUPD == 645 || nUPD == 641 ) ) )
+ {
+ bOutlineStyleCandidate = true;
+ }
+ else if ( nUPD == 680 && nBuild <= 9073 ) /* BuildId of OOo 2.0.4/SO8 PU4 */
+ {
+ bOutlineStyleCandidate = bOutlineLevelAttrFound;
+ }
+ if ( bOutlineStyleCandidate )
+ {
+ AddOutlineStyleCandidate( nOutlineLevel, sStyleName );
+ }
+ // Assure that heading applies the outline style (#i103817#)
+ if ( ( !pStyle || !pStyle->IsListStyleSet() ) &&
+ !bOutlineStyleCandidate &&
+ m_xImpl->m_xChapterNumbering.is())
+ {
+ if ( !lcl_HasListStyle( sStyleName,
+ m_xImpl->m_xParaStyles, GetXMLImport(),
+ u"NumberingStyleName"_ustr,
+ u"" ) )
+ {
+ // heading not in a list --> apply outline style
+ xPropSet->setPropertyValue( s_NumberingRules,
+ Any(m_xImpl->m_xChapterNumbering) );
+ xPropSet->setPropertyValue( s_NumberingLevel,
+ Any(static_cast<sal_Int8>(nOutlineLevel - 1)));
+ }
+ }
+ }
+ }
+ //handle for text:p,if the paragraphstyle outlinelevel is set to[1~10]
+ else if( bHasOutlineLevelProp )
+ {
+ if ( nCurrentOutlineLevelInheritedFromParagraphStyle != 0 )
+ {
+ xPropSet->setPropertyValue(s_OutlineLevel,
+ Any( sal_Int16(0) ));
+ }
+ }
+ }
+
+ return sStyleName;
+}
+
+void XMLTextImportHelper::FindOutlineStyleName( OUString& rStyleName,
+ sal_Int8 nOutlineLevel )
+{
+ // style name empty?
+ if( !rStyleName.isEmpty() )
+ return;
+
+ // Empty? Then we need o do stuff. Let's do error checking first.
+ if (m_xImpl->m_xChapterNumbering.is() &&
+ ( nOutlineLevel > 0 ) &&
+ (nOutlineLevel <= m_xImpl->m_xChapterNumbering->getCount()))
+ {
+ nOutlineLevel--; // for the remainder, the level's are 0-based
+
+ // empty style name: look-up previously used name
+
+ // if we don't have a previously used name, we'll use the default
+ m_xImpl->InitOutlineStylesCandidates();
+ if (m_xImpl->m_xOutlineStylesCandidates[nOutlineLevel].empty())
+ {
+ // no other name used previously? Then use default
+
+ // iterate over property value sequence to find the style name
+ Sequence<PropertyValue> aProperties;
+ m_xImpl->m_xChapterNumbering->getByIndex( nOutlineLevel )
+ >>= aProperties;
+ auto pProp = std::find_if(std::cbegin(aProperties), std::cend(aProperties),
+ [](const PropertyValue& rProp) { return rProp.Name == "HeadingStyleName"; });
+ if (pProp != std::cend(aProperties))
+ {
+ OUString aOutlineStyle;
+ pProp->Value >>= aOutlineStyle;
+ m_xImpl->m_xOutlineStylesCandidates[nOutlineLevel]
+ .push_back( aOutlineStyle );
+ }
+ }
+
+ // finally, we'll use the previously used style name for this
+ // format (or the default we've just put into that style)
+ // take last added one (#i71249#)
+ rStyleName =
+ m_xImpl->m_xOutlineStylesCandidates[nOutlineLevel].back();
+ }
+ // else: nothing we can do, so we'll leave it empty
+ // else: we already had a style name, so we let it pass.
+}
+
+void XMLTextImportHelper::AddOutlineStyleCandidate( const sal_Int8 nOutlineLevel,
+ const OUString& rStyleName )
+{
+ if (!rStyleName.isEmpty()
+ && m_xImpl->m_xChapterNumbering.is()
+ && (nOutlineLevel > 0)
+ && (nOutlineLevel <= m_xImpl->m_xChapterNumbering->getCount()))
+ {
+ m_xImpl->InitOutlineStylesCandidates();
+ m_xImpl->m_xOutlineStylesCandidates[nOutlineLevel-1].push_back(
+ rStyleName);
+ }
+}
+
+void XMLTextImportHelper::SetOutlineStyles( bool bSetEmptyLevels )
+{
+ if (!(m_xImpl->m_xOutlineStylesCandidates != nullptr || bSetEmptyLevels) ||
+ !m_xImpl->m_xChapterNumbering.is() ||
+ IsInsertMode())
+ return;
+
+ bool bChooseLastOne( false );
+ {
+ if ( GetXMLImport().IsTextDocInOOoFileFormat() )
+ {
+ bChooseLastOne = true;
+ }
+ else
+ {
+ sal_Int32 nUPD( 0 );
+ sal_Int32 nBuild( 0 );
+ if ( GetXMLImport().getBuildIds( nUPD, nBuild ) )
+ {
+ // check explicitly on certain versions
+ bChooseLastOne = ( nUPD == 641 ) || ( nUPD == 645 ) || // prior OOo 2.0
+ ( nUPD == 680 && nBuild <= 9073 ); // OOo 2.0 - OOo 2.0.4
+ }
+ }
+ }
+
+ OUString sOutlineStyleName;
+ {
+ Reference<XPropertySet> xChapterNumRule(
+ m_xImpl->m_xChapterNumbering, UNO_QUERY);
+ xChapterNumRule->getPropertyValue("Name") >>= sOutlineStyleName;
+ }
+
+ const sal_Int32 nCount = m_xImpl->m_xChapterNumbering->getCount();
+ /* First collect all paragraph styles chosen for assignment to each
+ list level of the outline style, then perform the intrinsic assignment.
+ Reason: The assignment of a certain paragraph style to a list level
+ of the outline style causes side effects on the children
+ paragraph styles in Writer. (#i106218#)
+ */
+ ::std::vector<OUString> sChosenStyles(nCount);
+ for( sal_Int32 i=0; i < nCount; ++i )
+ {
+ if ( bSetEmptyLevels ||
+ (m_xImpl->m_xOutlineStylesCandidates &&
+ !m_xImpl->m_xOutlineStylesCandidates[i].empty()))
+ {
+ // determine, which candidate is one to be assigned to the list
+ // level of the outline style
+ if (m_xImpl->m_xOutlineStylesCandidates &&
+ !m_xImpl->m_xOutlineStylesCandidates[i].empty())
+ {
+ if ( bChooseLastOne )
+ {
+ sChosenStyles[i] =
+ m_xImpl->m_xOutlineStylesCandidates[i].back();
+ }
+ else
+ {
+ for (size_t j = 0;
+ j < m_xImpl->m_xOutlineStylesCandidates[i].size();
+ ++j)
+ {
+ if (!lcl_HasListStyle(
+ m_xImpl->m_xOutlineStylesCandidates[i][j],
+ m_xImpl->m_xParaStyles,
+ GetXMLImport(),
+ "NumberingStyleName",
+ sOutlineStyleName))
+ {
+ sChosenStyles[i] =
+ m_xImpl->m_xOutlineStylesCandidates[i][j];
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ // Trashed outline numbering in ODF 1.1 text document created by OOo 3.x (#i106218#)
+ Sequence < PropertyValue > aProps( 1 );
+ PropertyValue *pProps = aProps.getArray();
+ pProps->Name = "HeadingStyleName";
+ for ( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ // Paragraph style assignments in Outline of template lost from second level on (#i107610#)
+ if ( bSetEmptyLevels || !sChosenStyles[i].isEmpty() )
+ {
+ pProps->Value <<= sChosenStyles[i];
+ m_xImpl->m_xChapterNumbering->replaceByIndex(i,
+ Any( aProps ));
+ }
+ }
+
+}
+
+void XMLTextImportHelper::SetHyperlink(
+ SvXMLImport const & rImport,
+ const Reference < XTextCursor >& rCursor,
+ const OUString& rHRef,
+ const OUString& rName,
+ const OUString& rTargetFrameName,
+ const OUString& rStyleName,
+ const OUString& rVisitedStyleName,
+ XMLEventsImportContext* pEvents)
+{
+ static constexpr OUString s_HyperLinkURL = u"HyperLinkURL"_ustr;
+ static constexpr OUString s_HyperLinkName = u"HyperLinkName"_ustr;
+ static constexpr OUString s_HyperLinkTarget = u"HyperLinkTarget"_ustr;
+ static constexpr OUString s_UnvisitedCharStyleName = u"UnvisitedCharStyleName"_ustr;
+ static constexpr OUString s_VisitedCharStyleName = u"VisitedCharStyleName"_ustr;
+ static constexpr OUString s_HyperLinkEvents = u"HyperLinkEvents"_ustr;
+
+ Reference < XPropertySet > xPropSet( rCursor, UNO_QUERY );
+ Reference < XPropertySetInfo > xPropSetInfo(
+ xPropSet->getPropertySetInfo());
+ if (!xPropSetInfo.is() || !xPropSetInfo->hasPropertyByName(s_HyperLinkURL))
+ return;
+
+ xPropSet->setPropertyValue(s_HyperLinkURL, Any(rHRef));
+
+ if (xPropSetInfo->hasPropertyByName(s_HyperLinkName))
+ {
+ xPropSet->setPropertyValue(s_HyperLinkName, Any(rName));
+ }
+
+ if (xPropSetInfo->hasPropertyByName(s_HyperLinkTarget))
+ {
+ xPropSet->setPropertyValue(s_HyperLinkTarget,
+ Any(rTargetFrameName));
+ }
+
+ if ( (pEvents != nullptr) &&
+ xPropSetInfo->hasPropertyByName(s_HyperLinkEvents))
+ {
+ // The API treats events at hyperlinks differently from most
+ // other properties: You have to set a name replace with the
+ // events in it. The easiest way to do this is to 1) get
+ // events, 2) set new ones, and 3) then put events back.
+ uno::Reference<XNameReplace> const xReplace(
+ xPropSet->getPropertyValue(s_HyperLinkEvents), UNO_QUERY);
+ if (xReplace.is())
+ {
+ // set events
+ pEvents->SetEvents(xReplace);
+
+ // put events
+ xPropSet->setPropertyValue(s_HyperLinkEvents, Any(xReplace));
+ }
+ }
+
+ if (!m_xImpl->m_xTextStyles.is())
+ return;
+
+ OUString sDisplayName(
+ rImport.GetStyleDisplayName(
+ XmlStyleFamily::TEXT_TEXT, rStyleName ) );
+ if( !sDisplayName.isEmpty() &&
+ xPropSetInfo->hasPropertyByName(s_UnvisitedCharStyleName) &&
+ m_xImpl->m_xTextStyles->hasByName(sDisplayName))
+ {
+ xPropSet->setPropertyValue(s_UnvisitedCharStyleName,
+ Any(sDisplayName));
+ }
+
+ sDisplayName =
+ rImport.GetStyleDisplayName(
+ XmlStyleFamily::TEXT_TEXT, rVisitedStyleName );
+ if( !sDisplayName.isEmpty() &&
+ xPropSetInfo->hasPropertyByName(s_VisitedCharStyleName) &&
+ m_xImpl->m_xTextStyles->hasByName(sDisplayName))
+ {
+ xPropSet->setPropertyValue(s_VisitedCharStyleName,
+ Any(sDisplayName));
+ }
+}
+
+void XMLTextImportHelper::SetRuby(
+ SvXMLImport const & rImport,
+ const Reference < XTextCursor >& rCursor,
+ const OUString& rStyleName,
+ const OUString& rTextStyleName,
+ const OUString& rText )
+{
+ Reference<XPropertySet> xPropSet(rCursor, UNO_QUERY);
+
+ OUString sRubyText("RubyText");
+
+ // if we have one Ruby property, we assume all of them are present
+ if (!xPropSet.is() ||
+ !xPropSet->getPropertySetInfo()->hasPropertyByName( sRubyText ))
+ return;
+
+ // the ruby text
+ xPropSet->setPropertyValue(sRubyText, Any(rText));
+
+ // the ruby style (ruby-adjust)
+ if (!rStyleName.isEmpty() && m_xImpl->m_xAutoStyles.is())
+ {
+ const SvXMLStyleContext* pTempStyle =
+ m_xImpl->m_xAutoStyles->FindStyleChildContext( XmlStyleFamily::TEXT_RUBY,
+ rStyleName, true );
+ XMLPropStyleContext *pStyle = const_cast<XMLPropStyleContext*>(dynamic_cast< const XMLPropStyleContext* >(pTempStyle));
+
+ if (nullptr != pStyle)
+ pStyle->FillPropertySet( xPropSet );
+ }
+
+ // the ruby text character style
+ if (m_xImpl->m_xTextStyles.is())
+ {
+ OUString sDisplayName(
+ rImport.GetStyleDisplayName(
+ XmlStyleFamily::TEXT_TEXT, rTextStyleName ) );
+ if( (!sDisplayName.isEmpty()) &&
+ m_xImpl->m_xTextStyles->hasByName( sDisplayName ))
+ {
+ xPropSet->setPropertyValue("RubyCharStyleName", Any(sDisplayName));
+ }
+ }
+}
+
+void XMLTextImportHelper::SetAutoStyles( SvXMLStylesContext *pStyles )
+{
+ m_xImpl->m_xAutoStyles = pStyles;
+}
+
+SvXMLImportContext *XMLTextImportHelper::CreateTextChildContext(
+ SvXMLImport& rImport,
+ sal_Int32 nElement,
+ const Reference< XFastAttributeList > & xAttrList,
+ XMLTextType eType )
+{
+ SvXMLImportContext *pContext = nullptr;
+
+ bool bContent = true;
+ switch( nElement )
+ {
+ case XML_ELEMENT(TEXT, XML_H):
+ case XML_ELEMENT(TEXT, XML_P):
+ case XML_ELEMENT(LO_EXT, XML_P):
+ pContext = new XMLParaContext( rImport,
+ nElement,
+ xAttrList );
+ if (m_xImpl->m_bProgress && XMLTextType::Shape != eType)
+ {
+ rImport.GetProgressBarHelper()->Increment();
+ }
+ break;
+ // #i52127#
+ case XML_ELEMENT(TEXT, XML_NUMBERED_PARAGRAPH):
+ pContext = new XMLNumberedParaContext(
+ rImport, nElement, xAttrList );
+ break;
+ case XML_ELEMENT(TEXT, XML_LIST):
+ pContext = new XMLTextListBlockContext( rImport, *this,
+ xAttrList );
+ break;
+ case XML_ELEMENT(TABLE,XML_TABLE):
+ case XML_ELEMENT(LO_EXT, XML_TABLE):
+ if( XMLTextType::Body == eType ||
+ XMLTextType::TextBox == eType ||
+ XMLTextType::Section == eType ||
+ XMLTextType::HeaderFooter == eType ||
+ XMLTextType::ChangedRegion == eType ||
+ XMLTextType::Cell == eType )
+ pContext = CreateTableChildContext( rImport, nElement, xAttrList );
+ break;
+ case XML_ELEMENT(TEXT, XML_SEQUENCE_DECLS):
+ if ((XMLTextType::Body == eType && m_xImpl->m_bBodyContentStarted) ||
+ XMLTextType::HeaderFooter == eType )
+ {
+ pContext = new XMLVariableDeclsImportContext(
+ rImport, *this, VarTypeSequence);
+ bContent = false;
+ }
+ break;
+ case XML_ELEMENT(TEXT, XML_VARIABLE_DECLS):
+ if ((XMLTextType::Body == eType && m_xImpl->m_bBodyContentStarted) ||
+ XMLTextType::HeaderFooter == eType )
+ {
+ pContext = new XMLVariableDeclsImportContext(
+ rImport, *this, VarTypeSimple);
+ bContent = false;
+ }
+ break;
+ case XML_ELEMENT(TEXT, XML_USER_FIELD_DECLS):
+ if ((XMLTextType::Body == eType && m_xImpl->m_bBodyContentStarted)||
+ XMLTextType::HeaderFooter == eType )
+ {
+ pContext = new XMLVariableDeclsImportContext(
+ rImport, *this, VarTypeUserField);
+ bContent = false;
+ }
+ break;
+ case XML_ELEMENT(TEXT, XML_DDE_CONNECTION_DECLS):
+ if ((XMLTextType::Body == eType && m_xImpl->m_bBodyContentStarted) ||
+ XMLTextType::HeaderFooter == eType )
+ {
+ pContext = new XMLDdeFieldDeclsImportContext(rImport);
+ bContent = false;
+ }
+ break;
+ case XML_ELEMENT(DRAW, XML_FRAME):
+ if ((XMLTextType::Body == eType && m_xImpl->m_bBodyContentStarted) ||
+ XMLTextType::TextBox == eType ||
+ XMLTextType::ChangedRegion == eType )
+ {
+ TextContentAnchorType eAnchorType =
+ XMLTextType::TextBox == eType ? TextContentAnchorType_AT_FRAME
+ : TextContentAnchorType_AT_PAGE;
+ pContext = new XMLTextFrameContext( rImport, xAttrList,
+ eAnchorType );
+ bContent = false;
+ }
+ break;
+ case XML_ELEMENT(DRAW, XML_A):
+ if ((XMLTextType::Body == eType && m_xImpl->m_bBodyContentStarted) ||
+ XMLTextType::TextBox == eType ||
+ XMLTextType::ChangedRegion == eType)
+ {
+ TextContentAnchorType eAnchorType =
+ XMLTextType::TextBox == eType ? TextContentAnchorType_AT_FRAME
+ : TextContentAnchorType_AT_PAGE;
+ pContext = new XMLTextFrameHyperlinkContext( rImport, nElement,
+ xAttrList,
+ eAnchorType );
+ bContent = false;
+ }
+ break;
+ case XML_ELEMENT(TEXT, XML_INDEX_TITLE):
+ case XML_ELEMENT(TEXT, XML_SECTION):
+ pContext = new XMLSectionImportContext( rImport );
+ break;
+ case XML_ELEMENT(TEXT, XML_TABLE_OF_CONTENT):
+ case XML_ELEMENT(TEXT, XML_OBJECT_INDEX):
+ case XML_ELEMENT(TEXT, XML_TABLE_INDEX):
+ case XML_ELEMENT(TEXT, XML_ILLUSTRATION_INDEX):
+ case XML_ELEMENT(TEXT, XML_USER_INDEX):
+ case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX):
+ case XML_ELEMENT(TEXT, XML_BIBLIOGRAPHY):
+ if( XMLTextType::Shape != eType )
+ pContext = new XMLIndexTOCContext( rImport, nElement );
+ break;
+ case XML_ELEMENT(TEXT, XML_TRACKED_CHANGES):
+ pContext = new XMLTrackedChangesImportContext( rImport );
+ bContent = false;
+ break;
+ case XML_ELEMENT(TEXT, XML_CHANGE):
+ case XML_ELEMENT(TEXT, XML_CHANGE_START):
+ case XML_ELEMENT(TEXT, XML_CHANGE_END):
+ pContext = new XMLChangeImportContext(
+ rImport,
+ ((nElement == XML_ELEMENT(TEXT, XML_CHANGE_END))
+ ? XMLChangeImportContext::Element::END
+ : (nElement == XML_ELEMENT(TEXT, XML_CHANGE_START))
+ ? XMLChangeImportContext::Element::START
+ : XMLChangeImportContext::Element::POINT),
+ true);
+ break;
+ case XML_ELEMENT(OFFICE, XML_FORMS):
+ pContext = xmloff::OFormLayerXMLImport::createOfficeFormsContext(rImport);
+ bContent = false;
+ break;
+ case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_AUTO_MARK_FILE):
+ if( XMLTextType::Body == eType )
+ {
+ pContext = new XMLAutoMarkFileContext(rImport);
+ }
+ bContent = false;
+ break;
+ case XML_ELEMENT(TABLE, XML_CALCULATION_SETTINGS):
+ pContext = new XMLCalculationSettingsContext ( rImport, nElement, xAttrList);
+ bContent = false;
+ break;
+
+ default:
+ if ((XMLTextType::Body == eType && m_xImpl->m_bBodyContentStarted) ||
+ XMLTextType::TextBox == eType ||
+ XMLTextType::ChangedRegion == eType )
+ {
+ Reference < XShapes > xShapes;
+ pContext = XMLShapeImportHelper::CreateGroupChildContext(
+ rImport, nElement, xAttrList, xShapes );
+ bContent = false;
+ }
+ }
+
+ // handle open redlines
+ if ( (XML_ELEMENT(TEXT, XML_CHANGE) != nElement) &&
+ (XML_ELEMENT(TEXT, XML_CHANGE_END) != nElement) &&
+ (XML_ELEMENT(TEXT, XML_CHANGE_START) != nElement) )
+ {
+// ResetOpenRedlineId();
+ }
+
+ if( XMLTextType::Body == eType && bContent )
+ {
+ m_xImpl->m_bBodyContentStarted = false;
+ }
+
+ if( nElement != XML_ELEMENT(DRAW, XML_FRAME) )
+ ClearLastImportedTextFrameName();
+
+ if (!pContext)
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+
+ return pContext;
+}
+
+SvXMLImportContext *XMLTextImportHelper::CreateTableChildContext(
+ SvXMLImport&,
+ sal_Int32 /*nElement*/,
+ const Reference< XFastAttributeList > & )
+{
+ return nullptr;
+}
+
+/// get data style key for use with NumberFormat property
+sal_Int32 XMLTextImportHelper::GetDataStyleKey(const OUString& sStyleName,
+ bool* pIsSystemLanguage )
+{
+ if (!m_xImpl->m_xAutoStyles.is())
+ return -1;
+
+ const SvXMLStyleContext* pStyle =
+ m_xImpl->m_xAutoStyles->FindStyleChildContext( XmlStyleFamily::DATA_STYLE,
+ sStyleName, true );
+
+ // get appropriate context
+
+
+ // first check if it's an Impress and draw only number format
+ // this is needed since it's also a SvXMLNumFormatContext,
+ // that was needed to support them for controls in impress/draw also
+ const SdXMLNumberFormatImportContext* pSdNumStyle = dynamic_cast<const SdXMLNumberFormatImportContext*>( pStyle );
+ if( pSdNumStyle )
+ {
+ return pSdNumStyle->GetDrawKey();
+ }
+ else
+ {
+ SvXMLNumFormatContext* pNumStyle = const_cast<SvXMLNumFormatContext*>(dynamic_cast<const SvXMLNumFormatContext*>( pStyle ) );
+ if( pNumStyle )
+ {
+ if( pIsSystemLanguage != nullptr )
+ *pIsSystemLanguage = pNumStyle->IsSystemLanguage();
+
+ // return key
+ return pNumStyle->GetKey();
+ }
+ }
+ return -1;
+}
+
+const SvxXMLListStyleContext *XMLTextImportHelper::FindAutoListStyle( const OUString& rName ) const
+{
+ const SvxXMLListStyleContext *pStyle = nullptr;
+ if (m_xImpl->m_xAutoStyles.is())
+ {
+ const SvXMLStyleContext* pTempStyle =
+ m_xImpl->m_xAutoStyles->FindStyleChildContext( XmlStyleFamily::TEXT_LIST, rName,
+ true );
+ pStyle = dynamic_cast< const SvxXMLListStyleContext* >(pTempStyle);
+ }
+
+ return pStyle;
+}
+
+XMLPropStyleContext *XMLTextImportHelper::FindAutoFrameStyle( const OUString& rName ) const
+{
+ XMLPropStyleContext *pStyle = nullptr;
+ if (m_xImpl->m_xAutoStyles.is())
+ {
+ const SvXMLStyleContext* pTempStyle =
+ m_xImpl->m_xAutoStyles->FindStyleChildContext( XmlStyleFamily::SD_GRAPHICS_ID, rName,
+ true );
+ pStyle = const_cast<XMLPropStyleContext*>(dynamic_cast< const XMLPropStyleContext* >(pTempStyle));
+ }
+
+ return pStyle;
+}
+
+XMLPropStyleContext* XMLTextImportHelper::FindSectionStyle(
+ const OUString& rName ) const
+{
+ XMLPropStyleContext* pStyle = nullptr;
+ if (m_xImpl->m_xAutoStyles.is())
+ {
+ const SvXMLStyleContext* pTempStyle =
+ m_xImpl->m_xAutoStyles->FindStyleChildContext(
+ XmlStyleFamily::TEXT_SECTION,
+ rName, true );
+ pStyle = const_cast<XMLPropStyleContext*>(dynamic_cast< const XMLPropStyleContext* >(pTempStyle));
+ }
+
+ return pStyle;
+}
+
+XMLPropStyleContext* XMLTextImportHelper::FindPageMaster(
+ const OUString& rName ) const
+{
+ XMLPropStyleContext* pStyle = nullptr;
+ if (m_xImpl->m_xAutoStyles.is())
+ {
+ const SvXMLStyleContext* pTempStyle =
+ m_xImpl->m_xAutoStyles->FindStyleChildContext(
+ XmlStyleFamily::PAGE_MASTER,
+ rName, true );
+ pStyle = const_cast<XMLPropStyleContext*>(dynamic_cast< const XMLPropStyleContext* >(pTempStyle));
+ }
+
+ return pStyle;
+}
+
+XMLPropStyleContext* XMLTextImportHelper::FindAutoCharStyle(const OUString& rName) const
+{
+ if (!m_xImpl->m_xAutoStyles)
+ return nullptr;
+ auto pStyle
+ = m_xImpl->m_xAutoStyles->FindStyleChildContext(XmlStyleFamily::TEXT_TEXT, rName, true);
+ return dynamic_cast<XMLPropStyleContext*>(const_cast<SvXMLStyleContext*>(pStyle));
+}
+
+XMLPropStyleContext * XMLTextImportHelper::FindDrawingPage(OUString const& rName) const
+{
+ if (!m_xImpl->m_xAutoStyles.is())
+ {
+ return nullptr;
+ }
+ SvXMLStyleContext const* pStyle(
+ m_xImpl->m_xAutoStyles->FindStyleChildContext(
+ XmlStyleFamily::SD_DRAWINGPAGE_ID, rName, true));
+ assert(pStyle == nullptr || dynamic_cast<XMLPropStyleContext const*>(pStyle) != nullptr);
+ return const_cast<XMLPropStyleContext*>(static_cast<XMLPropStyleContext const*>(pStyle));
+}
+
+void XMLTextImportHelper::PushListContext()
+{
+ GetTextListHelper().PushListContext(static_cast<XMLTextListBlockContext*>(nullptr));
+}
+
+void XMLTextImportHelper::PopListContext()
+{
+ GetTextListHelper().PopListContext();
+}
+
+
+SvI18NMap& XMLTextImportHelper::GetRenameMap()
+{
+ if (!m_xImpl->m_xRenameMap)
+ {
+ m_xImpl->m_xRenameMap.reset( new SvI18NMap );
+ }
+ return *m_xImpl->m_xRenameMap;
+}
+
+void XMLTextImportHelper::InsertBookmarkStartRange(
+ const OUString & sName,
+ const Reference<XTextRange> & rRange,
+ OUString const& i_rXmlId,
+ std::shared_ptr< ::xmloff::ParsedRDFaAttributes > & i_rpRDFaAttributes)
+{
+ m_xImpl->m_BookmarkStartRanges[sName] =
+ std::make_tuple(rRange, i_rXmlId, i_rpRDFaAttributes);
+ m_xImpl->m_BookmarkVector.push_back(sName);
+}
+
+bool XMLTextImportHelper::FindAndRemoveBookmarkStartRange(
+ const OUString & sName,
+ Reference<XTextRange> & o_rRange,
+ OUString & o_rXmlId,
+ std::shared_ptr< ::xmloff::ParsedRDFaAttributes > & o_rpRDFaAttributes)
+{
+ if (m_xImpl->m_BookmarkStartRanges.count(sName))
+ {
+ Impl::BookmarkMapEntry_t & rEntry =
+ (*m_xImpl->m_BookmarkStartRanges.find(sName)).second;
+ o_rRange.set(std::get<0>(rEntry));
+ o_rXmlId = std::get<1>(rEntry);
+ o_rpRDFaAttributes = std::get<2>(rEntry);
+ m_xImpl->m_BookmarkStartRanges.erase(sName);
+ auto it = std::find(m_xImpl->m_BookmarkVector.begin(), m_xImpl->m_BookmarkVector.end(), sName);
+ if (it!=m_xImpl->m_BookmarkVector.end())
+ {
+ m_xImpl->m_BookmarkVector.erase(it);
+ }
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+void XMLTextImportHelper::pushFieldCtx( const OUString& name, const OUString& type )
+{
+ m_xImpl->m_FieldStack.push(Impl::field_stack_item_t(
+ Impl::field_name_type_t(name, type), Impl::field_params_t(), uno::Reference<text::XFormField>{}, GetCursor()->getStart()));
+}
+
+uno::Reference<text::XFormField>
+XMLTextImportHelper::popFieldCtx()
+{
+ uno::Reference<text::XFormField> xRet;
+ if ( !m_xImpl->m_FieldStack.empty() )
+ {
+ xRet = std::get<2>(m_xImpl->m_FieldStack.top());
+ m_xImpl->m_FieldStack.pop();
+ }
+ else
+ {
+ SAL_INFO("xmloff.text", "unexpected fieldmark end");
+ }
+ return xRet;
+}
+
+void XMLTextImportHelper::addFieldParam( const OUString& name, const OUString& value )
+{
+ assert(!m_xImpl->m_FieldStack.empty());
+ Impl::field_stack_item_t & FieldStackItem(m_xImpl->m_FieldStack.top());
+ std::get<1>(FieldStackItem).emplace_back( name, value );
+}
+
+::std::pair<OUString, OUString> XMLTextImportHelper::getCurrentFieldType() const
+{
+ assert(!m_xImpl->m_FieldStack.empty());
+ return std::get<0>(m_xImpl->m_FieldStack.top());
+}
+
+uno::Reference<text::XTextRange> XMLTextImportHelper::getCurrentFieldStart() const
+{
+ assert(!m_xImpl->m_FieldStack.empty());
+ return std::get<3>(m_xImpl->m_FieldStack.top());
+}
+
+bool XMLTextImportHelper::hasCurrentFieldSeparator() const
+{
+ assert(!m_xImpl->m_FieldStack.empty());
+ return std::get<2>(m_xImpl->m_FieldStack.top()).is();
+}
+
+bool XMLTextImportHelper::hasCurrentFieldCtx() const
+{
+ return !m_xImpl->m_FieldStack.empty();
+}
+
+void XMLTextImportHelper::setCurrentFieldParamsTo(css::uno::Reference< css::text::XFormField> const &xFormField)
+{
+ assert(!m_xImpl->m_FieldStack.empty());
+ if (xFormField.is())
+ {
+ FieldParamImporter(&std::get<1>(m_xImpl->m_FieldStack.top()),
+ xFormField->getParameters()).Import();
+ std::get<2>(m_xImpl->m_FieldStack.top()) = xFormField;
+ }
+}
+
+
+void XMLTextImportHelper::ConnectFrameChains(
+ const OUString& rFrmName,
+ const OUString& rNextFrmName,
+ const Reference < XPropertySet >& rFrmPropSet )
+{
+ if( rFrmName.isEmpty() )
+ return;
+
+ if( !rNextFrmName.isEmpty() )
+ {
+ OUString sNextFrmName(GetRenameMap().Get( XML_TEXT_RENAME_TYPE_FRAME,
+ rNextFrmName ));
+ if (m_xImpl->m_xTextFrames.is()
+ && m_xImpl->m_xTextFrames->hasByName(sNextFrmName))
+ {
+ rFrmPropSet->setPropertyValue("ChainNextName",
+ Any(sNextFrmName));
+ }
+ else
+ {
+ if (!m_xImpl->m_xPrevFrmNames)
+ {
+ m_xImpl->m_xPrevFrmNames.emplace();
+ m_xImpl->m_xNextFrmNames.emplace();
+ }
+ m_xImpl->m_xPrevFrmNames->push_back(rFrmName);
+ m_xImpl->m_xNextFrmNames->push_back(sNextFrmName);
+ }
+ }
+ if (!m_xImpl->m_xPrevFrmNames || m_xImpl->m_xPrevFrmNames->empty())
+ return;
+
+ for(std::vector<OUString>::iterator i = m_xImpl->m_xPrevFrmNames->begin(), j = m_xImpl->m_xNextFrmNames->begin(); i != m_xImpl->m_xPrevFrmNames->end() && j != m_xImpl->m_xNextFrmNames->end(); ++i, ++j)
+ {
+ if((*j) == rFrmName)
+ {
+ // The previous frame must exist, because it existing than
+ // inserting the entry
+ rFrmPropSet->setPropertyValue("ChainPrevName", Any(*i));
+
+ i = m_xImpl->m_xPrevFrmNames->erase(i);
+ j = m_xImpl->m_xNextFrmNames->erase(j);
+
+ // There cannot be more than one previous frames
+ break;
+ }
+ }
+}
+
+bool XMLTextImportHelper::IsInFrame() const
+{
+ static constexpr OUString s_TextFrame = u"TextFrame"_ustr;
+
+ bool bIsInFrame = false;
+
+ // are we currently in a text frame? yes, if the cursor has a
+ // TextFrame property and it's non-NULL
+ Reference<XPropertySet> xPropSet(const_cast<XMLTextImportHelper*>(this)->GetCursor(), UNO_QUERY);
+ if (xPropSet.is())
+ {
+ if (xPropSet->getPropertySetInfo()->hasPropertyByName(s_TextFrame))
+ {
+ uno::Reference<XTextFrame> const xFrame(
+ xPropSet->getPropertyValue(s_TextFrame), UNO_QUERY);
+
+ if (xFrame.is())
+ {
+ bIsInFrame = true;
+ }
+ }
+ }
+
+ return bIsInFrame;
+}
+
+bool XMLTextImportHelper::IsInHeaderFooter() const
+{
+ return false;
+}
+
+Reference< XPropertySet> XMLTextImportHelper::createAndInsertOLEObject(
+ SvXMLImport&,
+ const OUString& /*rHRef*/,
+ const OUString& /*rStyleName*/,
+ const OUString& /*rTblName*/,
+ sal_Int32 /*nWidth*/, sal_Int32 /*nHeight*/ )
+{
+ Reference< XPropertySet> xPropSet;
+ return xPropSet;
+}
+
+Reference< XPropertySet> XMLTextImportHelper::createAndInsertOOoLink(
+ SvXMLImport&,
+ const OUString& /*rHRef*/,
+ const OUString& /*rStyleName*/,
+ const OUString& /*rTblName*/,
+ sal_Int32 /*nWidth*/, sal_Int32 /*nHeight*/ )
+{
+ Reference< XPropertySet> xPropSet;
+ return xPropSet;
+}
+
+Reference< XPropertySet> XMLTextImportHelper::createAndInsertApplet(
+ const OUString& /*rCode*/,
+ const OUString& /*rName*/,
+ bool /*bMayScript*/,
+ const OUString& /*rHRef*/,
+ sal_Int32 /*nWidth*/, sal_Int32 /*nHeight*/ )
+{
+ Reference< XPropertySet> xPropSet;
+ return xPropSet;
+}
+Reference< XPropertySet> XMLTextImportHelper::createAndInsertPlugin(
+ const OUString& /*rMimeType*/,
+ const OUString& /*rHRef*/,
+ sal_Int32 /*nWidth*/, sal_Int32 /*nHeight*/ )
+{
+ Reference< XPropertySet> xPropSet;
+ return xPropSet;
+}
+Reference< XPropertySet> XMLTextImportHelper::createAndInsertFloatingFrame(
+ const OUString& /*rName*/,
+ const OUString& /*rHRef*/,
+ const OUString& /*rStyleName*/,
+ sal_Int32 /*nWidth*/, sal_Int32 /*nHeight*/ )
+{
+ Reference< XPropertySet> xPropSet;
+ return xPropSet;
+}
+
+void XMLTextImportHelper::endAppletOrPlugin(
+ const Reference < XPropertySet> &,
+ std::map < const OUString, OUString > &)
+{
+}
+// redline helper: dummy implementation to be overridden in sw/filter/xml
+void XMLTextImportHelper::RedlineAdd( const OUString& /*rType*/,
+ const OUString& /*rId*/,
+ const OUString& /*rAuthor*/,
+ const OUString& /*rComment*/,
+ const util::DateTime& /*rDateTime*/,
+ const OUString& /*rMovedID*/,
+ bool /*bMergeLastPara*/)
+{
+ // dummy implementation: do nothing
+}
+
+Reference<XTextCursor> XMLTextImportHelper::RedlineCreateText(
+ Reference<XTextCursor> & /*rOldCursor*/,
+ const OUString& /*rId*/)
+{
+ // dummy implementation: do nothing
+ Reference<XTextCursor> xRet;
+ return xRet;
+}
+
+void XMLTextImportHelper::RedlineSetCursor(
+ const OUString& /*rId*/,
+ bool /*bStart*/,
+ bool /*bIsOutsideOfParagraph*/)
+{
+ // dummy implementation: do nothing
+}
+
+void XMLTextImportHelper::RedlineAdjustStartNodeCursor()
+{
+ // dummy implementation: do nothing
+}
+
+void XMLTextImportHelper::SetShowChanges( bool )
+{
+ // dummy implementation: do nothing
+}
+
+void XMLTextImportHelper::SetRecordChanges( bool )
+{
+ // dummy implementation: do nothing
+}
+void XMLTextImportHelper::SetChangesProtectionKey(const Sequence<sal_Int8> &)
+{
+ // dummy implementation: do nothing
+}
+
+
+OUString const & XMLTextImportHelper::GetOpenRedlineId() const
+{
+ return m_xImpl->m_sOpenRedlineIdentifier;
+}
+
+void XMLTextImportHelper::SetOpenRedlineId( OUString const & rId)
+{
+ m_xImpl->m_sOpenRedlineIdentifier = rId;
+}
+
+void XMLTextImportHelper::ResetOpenRedlineId()
+{
+ SetOpenRedlineId("");
+}
+
+void
+XMLTextImportHelper::SetCellParaStyleDefault(OUString const& rNewValue)
+{
+ m_xImpl->m_sCellParaStyleDefault = rNewValue;
+}
+
+OUString const& XMLTextImportHelper::GetCellParaStyleDefault() const
+{
+ return m_xImpl->m_sCellParaStyleDefault;
+}
+
+void XMLTextImportHelper::AddCrossRefHeadingMapping(OUString const& rFrom, OUString const& rTo)
+{
+ if (!m_xImpl->m_xCrossRefHeadingBookmarkMap)
+ {
+ m_xImpl->m_xCrossRefHeadingBookmarkMap.emplace();
+ }
+ m_xImpl->m_xCrossRefHeadingBookmarkMap->insert(std::make_pair(rFrom, rTo));
+}
+
+// tdf#94804: hack to map cross reference fields that reference duplicate marks
+// note that we can't really check meta:generator for this since the file might
+// be round-tripped by different versions preserving duplicates => always map
+void XMLTextImportHelper::MapCrossRefHeadingFieldsHorribly()
+{
+ if (!m_xImpl->m_xCrossRefHeadingBookmarkMap)
+ {
+ return;
+ }
+
+ uno::Reference<text::XTextFieldsSupplier> const xFieldsSupplier(
+ m_xImpl->m_rSvXMLImport.GetModel(), uno::UNO_QUERY);
+ if (!xFieldsSupplier.is())
+ {
+ return;
+ }
+ uno::Reference<container::XEnumerationAccess> const xFieldsEA(
+ xFieldsSupplier->getTextFields());
+ uno::Reference<container::XEnumeration> const xFields(
+ xFieldsEA->createEnumeration());
+ while (xFields->hasMoreElements())
+ {
+ uno::Reference<lang::XServiceInfo> const xFieldInfo(
+ xFields->nextElement(), uno::UNO_QUERY);
+ if (!xFieldInfo->supportsService("com.sun.star.text.textfield.GetReference"))
+ {
+ continue;
+ }
+ uno::Reference<beans::XPropertySet> const xField(
+ xFieldInfo, uno::UNO_QUERY);
+ sal_uInt16 nType(0);
+ xField->getPropertyValue("ReferenceFieldSource") >>= nType;
+ if (text::ReferenceFieldSource::BOOKMARK != nType)
+ {
+ continue;
+ }
+ OUString name;
+ xField->getPropertyValue("SourceName") >>= name;
+ auto const iter(m_xImpl->m_xCrossRefHeadingBookmarkMap->find(name));
+ if (iter == m_xImpl->m_xCrossRefHeadingBookmarkMap->end())
+ {
+ continue;
+ }
+ xField->setPropertyValue("SourceName", uno::Any(iter->second));
+ }
+}
+
+void XMLTextImportHelper::setBookmarkAttributes(OUString const& bookmark, bool hidden, OUString const& condition)
+{
+ m_xImpl->m_bBookmarkHidden[bookmark] = hidden;
+ m_xImpl->m_sBookmarkCondition[bookmark] = condition;
+}
+
+bool XMLTextImportHelper::getBookmarkHidden(OUString const& bookmark) const
+{
+ return m_xImpl->m_bBookmarkHidden[bookmark];
+}
+
+const OUString& XMLTextImportHelper::getBookmarkCondition(OUString const& bookmark) const
+{
+ return m_xImpl->m_sBookmarkCondition[bookmark];
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/txtimppr.cxx b/xmloff/source/text/txtimppr.cxx
new file mode 100644
index 0000000000..e1da4578a1
--- /dev/null
+++ b/xmloff/source/text/txtimppr.cxx
@@ -0,0 +1,848 @@
+/* -*- 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 <memory>
+#include <sal/config.h>
+
+#include <o3tl/any.hxx>
+#include <osl/thread.h>
+#include <com/sun/star/awt/FontFamily.hpp>
+#include <com/sun/star/awt/FontPitch.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/table/BorderLine2.hpp>
+#include <com/sun/star/text/VertOrientation.hpp>
+#include <com/sun/star/text/SizeType.hpp>
+#include <xmloff/XMLFontStylesContext.hxx>
+#include <xmloff/txtprmap.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/txtimppr.hxx>
+#include <xmloff/maptype.hxx>
+
+#define XML_LINE_LEFT 0
+#define XML_LINE_RIGHT 1
+#define XML_LINE_TOP 2
+#define XML_LINE_BOTTOM 3
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::table;
+using namespace ::com::sun::star::text;
+
+bool XMLTextImportPropertyMapper::handleSpecialItem(
+ XMLPropertyState& rProperty,
+ ::std::vector< XMLPropertyState >& rProperties,
+ const OUString& rValue,
+ const SvXMLUnitConverter& rUnitConverter,
+ const SvXMLNamespaceMap& rNamespaceMap ) const
+{
+ bool bRet = false;
+ sal_Int32 nIndex = rProperty.mnIndex;
+ switch( getPropertySetMapper()->GetEntryContextId( nIndex ) )
+ {
+ case CTF_FONTNAME:
+ case CTF_FONTNAME_CJK:
+ case CTF_FONTNAME_CTL:
+ if( GetImport().GetFontDecls() != nullptr )
+ {
+ assert((
+ ( CTF_FONTFAMILYNAME ==
+ getPropertySetMapper()->GetEntryContextId(nIndex+1) &&
+ CTF_FONTSTYLENAME ==
+ getPropertySetMapper()->GetEntryContextId(nIndex+2) &&
+ CTF_FONTFAMILY ==
+ getPropertySetMapper()->GetEntryContextId(nIndex+3) &&
+ CTF_FONTPITCH ==
+ getPropertySetMapper()->GetEntryContextId(nIndex+4) &&
+ CTF_FONTCHARSET ==
+ getPropertySetMapper()->GetEntryContextId(nIndex+5) ) ||
+ ( CTF_FONTFAMILYNAME_CJK ==
+ getPropertySetMapper()->GetEntryContextId(nIndex+1) &&
+ CTF_FONTSTYLENAME_CJK ==
+ getPropertySetMapper()->GetEntryContextId(nIndex+2) &&
+ CTF_FONTFAMILY_CJK ==
+ getPropertySetMapper()->GetEntryContextId(nIndex+3) &&
+ CTF_FONTPITCH_CJK ==
+ getPropertySetMapper()->GetEntryContextId(nIndex+4) &&
+ CTF_FONTCHARSET_CJK ==
+ getPropertySetMapper()->GetEntryContextId(nIndex+5) ) ||
+ ( CTF_FONTFAMILYNAME_CTL ==
+ getPropertySetMapper()->GetEntryContextId(nIndex+1) &&
+ CTF_FONTSTYLENAME_CTL ==
+ getPropertySetMapper()->GetEntryContextId(nIndex+2) &&
+ CTF_FONTFAMILY_CTL ==
+ getPropertySetMapper()->GetEntryContextId(nIndex+3) &&
+ CTF_FONTPITCH_CTL ==
+ getPropertySetMapper()->GetEntryContextId(nIndex+4) &&
+ CTF_FONTCHARSET_CTL ==
+ getPropertySetMapper()->GetEntryContextId(nIndex+5) )
+ ) && "illegal property map" );
+
+ GetImport().GetFontDecls()->FillProperties(
+ rValue, rProperties,
+ rProperty.mnIndex+1, rProperty.mnIndex+2,
+ rProperty.mnIndex+3, rProperty.mnIndex+4,
+ rProperty.mnIndex+5 );
+ bRet = false; // the property hasn't been filled
+ }
+ break;
+
+ // If we want to do StarMath/StarSymbol font conversion, then we'll
+ // want these special items to be treated just like regular ones...
+ // For the Writer, we'll catch and convert them in _FillPropertySet;
+ // the other apps probably don't care. For the other apps, we just
+ // imitate the default non-special-item mechanism.
+ case CTF_FONTFAMILYNAME:
+ case CTF_FONTFAMILYNAME_CJK:
+ case CTF_FONTFAMILYNAME_CTL:
+ bRet = getPropertySetMapper()->importXML( rValue, rProperty,
+ rUnitConverter );
+ break;
+
+ case CTF_TEXT_DISPLAY:
+ bRet = getPropertySetMapper()->importXML( rValue, rProperty,
+ rUnitConverter );
+ if( SvXMLImport::OOo_2x == GetImport().getGeneratorVersion() )
+ {
+ bool bHidden = false;
+ rProperty.maValue >>= bHidden;
+ bHidden = !bHidden;
+ rProperty.maValue <<= bHidden;
+ }
+ break;
+ default:
+ bRet = SvXMLImportPropertyMapper::handleSpecialItem( rProperty,
+ rProperties, rValue, rUnitConverter, rNamespaceMap );
+ break;
+ }
+
+ return bRet;
+}
+
+XMLTextImportPropertyMapper::XMLTextImportPropertyMapper(
+ const rtl::Reference< XMLPropertySetMapper >& rMapper,
+ SvXMLImport& rImp ) :
+ SvXMLImportPropertyMapper( rMapper, rImp ),
+ m_nSizeTypeIndex( -2 ),
+ m_nWidthTypeIndex( -2 )
+{
+}
+
+XMLTextImportPropertyMapper::~XMLTextImportPropertyMapper()
+{
+}
+
+void XMLTextImportPropertyMapper::FontFinished(
+ XMLPropertyState *pFontFamilyNameState,
+ XMLPropertyState *pFontStyleNameState,
+ XMLPropertyState *pFontFamilyState,
+ XMLPropertyState *pFontPitchState,
+ XMLPropertyState *pFontCharsetState )
+{
+ if( pFontFamilyNameState && pFontFamilyNameState->mnIndex != -1 )
+ {
+ OUString sName;
+ pFontFamilyNameState->maValue >>= sName;
+ if( sName.isEmpty() )
+ pFontFamilyNameState->mnIndex = -1;
+ }
+ if( !pFontFamilyNameState || pFontFamilyNameState->mnIndex == -1 )
+ {
+ if( pFontStyleNameState )
+ pFontStyleNameState->mnIndex = -1;
+ if( pFontFamilyState )
+ pFontFamilyState->mnIndex = -1;
+ if( pFontPitchState )
+ pFontPitchState->mnIndex = -1;
+ if( pFontCharsetState )
+ pFontCharsetState->mnIndex = -1;
+ }
+}
+
+/** since the properties "CharFontFamilyName", "CharFontStyleName", "CharFontFamily",
+ "CharFontPitch" and "CharFontSet" and their CJK and CTL counterparts are only
+ usable as a union, we add defaults to all values that are not set as long as we
+ have an "CharFontFamilyName"
+
+ #99928# CL */
+void XMLTextImportPropertyMapper::FontDefaultsCheck(
+ XMLPropertyState const * pFontFamilyName,
+ XMLPropertyState const * pFontStyleName,
+ XMLPropertyState const * pFontFamily,
+ XMLPropertyState const * pFontPitch,
+ XMLPropertyState const * pFontCharSet,
+ std::optional<XMLPropertyState>* ppNewFontStyleName,
+ std::optional<XMLPropertyState>* ppNewFontFamily,
+ std::optional<XMLPropertyState>* ppNewFontPitch,
+ std::optional<XMLPropertyState>* ppNewFontCharSet ) const
+{
+ if( pFontFamilyName )
+ {
+ Any aAny;
+
+ if( !pFontStyleName )
+ {
+ aAny <<= OUString();
+ #if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
+ sal_Int16 nTmp = getPropertySetMapper()->GetEntryContextId(
+ pFontFamilyName->mnIndex + 1 );
+ assert(nTmp == CTF_FONTSTYLENAME || nTmp == CTF_FONTSTYLENAME_CJK || nTmp == CTF_FONTSTYLENAME_CTL);
+ #endif
+ ppNewFontStyleName->emplace( pFontFamilyName->mnIndex + 1, aAny );
+ }
+
+ if( !pFontFamily )
+ {
+ aAny <<= sal_Int16(css::awt::FontFamily::DONTKNOW);
+
+ #if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
+ sal_Int16 nTmp = getPropertySetMapper()->GetEntryContextId(
+ pFontFamilyName->mnIndex + 2 );
+ assert(nTmp == CTF_FONTFAMILY || nTmp == CTF_FONTFAMILY_CJK || nTmp == CTF_FONTFAMILY_CTL);
+ #endif
+ ppNewFontFamily->emplace( pFontFamilyName->mnIndex + 2, aAny );
+ }
+
+ if( !pFontPitch )
+ {
+ aAny <<= sal_Int16(css::awt::FontPitch::DONTKNOW);
+ #if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
+ sal_Int16 nTmp = getPropertySetMapper()->GetEntryContextId(
+ pFontFamilyName->mnIndex + 3 );
+ assert(nTmp == CTF_FONTPITCH || nTmp == CTF_FONTPITCH_CJK || nTmp == CTF_FONTPITCH_CTL);
+ #endif
+ ppNewFontPitch->emplace( pFontFamilyName->mnIndex + 3, aAny );
+ }
+
+ if( !pFontCharSet )
+ {
+ aAny <<= static_cast<sal_Int16>(osl_getThreadTextEncoding());
+ #if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
+ sal_Int16 nTmp = getPropertySetMapper()->GetEntryContextId(
+ pFontFamilyName->mnIndex + 4 );
+ assert(nTmp == CTF_FONTCHARSET || nTmp == CTF_FONTCHARSET_CJK || nTmp == CTF_FONTCHARSET_CTL);
+ #endif
+ ppNewFontCharSet->emplace( pFontFamilyName->mnIndex + 4, aAny );
+ }
+ }
+
+ (void) this; // avoid loplugin:staticmethods
+}
+
+namespace {
+//fdo#58730 The [UL|LR]Space class has a deficiency where "100%" also serves as
+//a flag that the value is an absolute value so we can't truly handle an
+//up/lower space property which wants to specify its 200% upper but 100% lower
+//of its parent (try typing 100% vs 200% into the edit style dialog and revisit
+//your style). So on xml load that ends up meaning 200%, 0 lower. This is a
+//crock.
+
+//On import clear 100% all-margins relative sizes.
+bool
+isNotDefaultRelSize(const XMLPropertyState* pRelState, const rtl::Reference<XMLPropertySetMapper>& rPrMap)
+{
+ if (rPrMap->GetEntryContextId(pRelState->mnIndex) == CTF_PARAMARGINALL_REL)
+ {
+ sal_Int32 nTemp = 0;
+ pRelState->maValue >>= nTemp;
+ return nTemp != 100;
+ }
+ return true;
+}
+
+/**
+ * Separate compressed border attributes.
+ * During export, border attributes are compressed if there are equal to all four side.
+ * Since Writer hasn't the same compressed attributes, but has distinct ones for all
+ * four side, we have to duplicate the compressed attribute during import.
+**/
+void lcl_SeparateBorder(
+ sal_uInt16 nIndex, XMLPropertyState const * pAllBorderDistance,
+ XMLPropertyState* pBorderDistances[4], XMLPropertyState* pNewBorderDistances[4],
+ XMLPropertyState const * pAllBorder, XMLPropertyState* pBorders[4],
+ XMLPropertyState* pNewBorders[4], XMLPropertyState* pAllBorderWidth,
+ XMLPropertyState* pBorderWidths[4]
+#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
+ , const rtl::Reference< XMLPropertySetMapper >& rMapper
+#endif
+)
+{
+ if( pAllBorderDistance && !pBorderDistances[nIndex] )
+ {
+#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
+ sal_Int16 nTmp = rMapper->GetEntryContextId(
+ pAllBorderDistance->mnIndex + nIndex + 1 );
+ if (CTF_CHARALLBORDERDISTANCE ==
+ rMapper->GetEntryContextId(pAllBorderDistance->mnIndex))
+ {
+ assert(nTmp >= CTF_CHARLEFTBORDERDISTANCE &&
+ nTmp <= CTF_CHARBOTTOMBORDERDISTANCE);
+ }
+ else
+ {
+ assert(nTmp >= CTF_LEFTBORDERDISTANCE &&
+ nTmp <= CTF_BOTTOMBORDERDISTANCE);
+ }
+#endif
+ pNewBorderDistances[nIndex] =
+ new XMLPropertyState( pAllBorderDistance->mnIndex + nIndex + 1,
+ pAllBorderDistance->maValue );
+ pBorderDistances[nIndex] = pNewBorderDistances[nIndex];
+ }
+ if( pAllBorder && !pBorders[nIndex] )
+ {
+#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
+ sal_Int16 nTmp = rMapper->GetEntryContextId(
+ pAllBorder->mnIndex + nIndex + 1 );
+ if (CTF_CHARALLBORDER ==
+ rMapper->GetEntryContextId(pAllBorder->mnIndex))
+ {
+ assert(nTmp >= CTF_CHARLEFTBORDER && nTmp <= CTF_CHARBOTTOMBORDER);
+ }
+ else
+ {
+ assert(nTmp >= CTF_LEFTBORDER && nTmp <= CTF_BOTTOMBORDER);
+ }
+#endif
+ pNewBorders[nIndex] = new XMLPropertyState( pAllBorder->mnIndex + nIndex + 1,
+ pAllBorder->maValue );
+ pBorders[nIndex] = pNewBorders[nIndex];
+ }
+ if( !pBorderWidths[nIndex] )
+ pBorderWidths[nIndex] = pAllBorderWidth;
+ else
+ pBorderWidths[nIndex]->mnIndex = -1;
+
+ if( !(pBorders[nIndex] && pBorderWidths[nIndex]) )
+ return;
+
+ table::BorderLine2 aBorderLine;
+ pBorders[nIndex]->maValue >>= aBorderLine;
+
+ table::BorderLine2 aBorderLineWidth;
+ pBorderWidths[nIndex]->maValue >>= aBorderLineWidth;
+
+ aBorderLine.OuterLineWidth = aBorderLineWidth.OuterLineWidth;
+ aBorderLine.InnerLineWidth = aBorderLineWidth.InnerLineWidth;
+ aBorderLine.LineDistance = aBorderLineWidth.LineDistance;
+ aBorderLine.LineWidth = aBorderLineWidth.LineWidth;
+
+ pBorders[nIndex]->maValue <<= aBorderLine;
+}
+
+}
+
+void XMLTextImportPropertyMapper::finished(
+ ::std::vector< XMLPropertyState >& rProperties,
+ sal_Int32 /*nStartIndex*/, sal_Int32 /*nEndIndex*/ ) const
+{
+ bool bHasAnyHeight = false;
+ bool bHasAnyMinHeight = false;
+ bool bHasAnyWidth = false;
+ bool bHasAnyMinWidth = false;
+
+ XMLPropertyState* pFontFamilyName = nullptr;
+ XMLPropertyState* pFontStyleName = nullptr;
+ XMLPropertyState* pFontFamily = nullptr;
+ XMLPropertyState* pFontPitch = nullptr;
+ XMLPropertyState* pFontCharSet = nullptr;
+ std::optional<XMLPropertyState> pNewFontStyleName;
+ std::optional<XMLPropertyState> pNewFontFamily;
+ std::optional<XMLPropertyState> pNewFontPitch;
+ std::optional<XMLPropertyState> pNewFontCharSet;
+ XMLPropertyState* pFontFamilyNameCJK = nullptr;
+ XMLPropertyState* pFontStyleNameCJK = nullptr;
+ XMLPropertyState* pFontFamilyCJK = nullptr;
+ XMLPropertyState* pFontPitchCJK = nullptr;
+ XMLPropertyState* pFontCharSetCJK = nullptr;
+ std::optional<XMLPropertyState> pNewFontStyleNameCJK;
+ std::optional<XMLPropertyState> pNewFontFamilyCJK;
+ std::optional<XMLPropertyState> pNewFontPitchCJK;
+ std::optional<XMLPropertyState> pNewFontCharSetCJK;
+ XMLPropertyState* pFontFamilyNameCTL = nullptr;
+ XMLPropertyState* pFontStyleNameCTL = nullptr;
+ XMLPropertyState* pFontFamilyCTL = nullptr;
+ XMLPropertyState* pFontPitchCTL = nullptr;
+ XMLPropertyState* pFontCharSetCTL = nullptr;
+ std::optional<XMLPropertyState> pNewFontStyleNameCTL;
+ std::optional<XMLPropertyState> pNewFontFamilyCTL;
+ std::optional<XMLPropertyState> pNewFontPitchCTL;
+ std::optional<XMLPropertyState> pNewFontCharSetCTL;
+ XMLPropertyState* pAllBorderDistance = nullptr;
+ XMLPropertyState* pBorderDistances[4] = { nullptr, nullptr, nullptr, nullptr };
+ XMLPropertyState* pNewBorderDistances[4] = { nullptr, nullptr, nullptr, nullptr };
+ XMLPropertyState* pAllBorder = nullptr;
+ XMLPropertyState* pBorders[4] = { nullptr, nullptr, nullptr, nullptr };
+ XMLPropertyState* pNewBorders[4] = { nullptr, nullptr, nullptr, nullptr };
+ XMLPropertyState* pAllBorderWidth = nullptr;
+ XMLPropertyState* pBorderWidths[4] = { nullptr, nullptr, nullptr, nullptr };
+ XMLPropertyState* pCharAllBorderDistance = nullptr;
+ XMLPropertyState* pCharBorderDistances[4] = { nullptr, nullptr, nullptr, nullptr };
+ XMLPropertyState* pCharNewBorderDistances[4] = { nullptr, nullptr, nullptr, nullptr };
+ XMLPropertyState* pCharAllBorder = nullptr;
+ XMLPropertyState* pCharBorders[4] = { nullptr, nullptr, nullptr, nullptr };
+ XMLPropertyState* pCharNewBorders[4] = { nullptr, nullptr, nullptr, nullptr };
+ XMLPropertyState* pCharAllBorderWidth = nullptr;
+ XMLPropertyState* pCharBorderWidths[4] = { nullptr, nullptr, nullptr, nullptr };
+ XMLPropertyState* pVertOrient = nullptr;
+ XMLPropertyState* pVertOrientRelAsChar = nullptr;
+ XMLPropertyState* pBackTransparency = nullptr; // transparency in %
+ XMLPropertyState* pBackTransparent = nullptr; // transparency as boolean
+ XMLPropertyState* pAllParaMargin = nullptr;
+ XMLPropertyState* pParaMargins[4] = { nullptr, nullptr, nullptr, nullptr };
+ ::std::optional<XMLPropertyState> pNewParaMargins[4];
+ XMLPropertyState* pAllMargin = nullptr;
+ XMLPropertyState* pMargins[4] = { nullptr, nullptr, nullptr, nullptr };
+ ::std::optional<XMLPropertyState> pNewMargins[4];
+ XMLPropertyState* pFillStyle(nullptr);
+ XMLPropertyState* pFillColor(nullptr);
+
+ for( auto& rProperty : rProperties )
+ {
+ XMLPropertyState* property = &rProperty;
+ if( -1 == property->mnIndex )
+ continue;
+
+ switch( getPropertySetMapper()->GetEntryContextId( property->mnIndex ) )
+ {
+ case CTF_FONTFAMILYNAME: pFontFamilyName = property; break;
+ case CTF_FONTSTYLENAME: pFontStyleName = property; break;
+ case CTF_FONTFAMILY: pFontFamily = property; break;
+ case CTF_FONTPITCH: pFontPitch = property; break;
+ case CTF_FONTCHARSET: pFontCharSet = property; break;
+
+ case CTF_FONTFAMILYNAME_CJK: pFontFamilyNameCJK = property; break;
+ case CTF_FONTSTYLENAME_CJK: pFontStyleNameCJK = property; break;
+ case CTF_FONTFAMILY_CJK: pFontFamilyCJK = property; break;
+ case CTF_FONTPITCH_CJK: pFontPitchCJK = property; break;
+ case CTF_FONTCHARSET_CJK: pFontCharSetCJK = property; break;
+
+ case CTF_FONTFAMILYNAME_CTL: pFontFamilyNameCTL = property; break;
+ case CTF_FONTSTYLENAME_CTL: pFontStyleNameCTL = property; break;
+ case CTF_FONTFAMILY_CTL: pFontFamilyCTL = property; break;
+ case CTF_FONTPITCH_CTL: pFontPitchCTL = property; break;
+ case CTF_FONTCHARSET_CTL: pFontCharSetCTL = property; break;
+
+ case CTF_ALLBORDERDISTANCE: pAllBorderDistance = property; break;
+ case CTF_LEFTBORDERDISTANCE: pBorderDistances[XML_LINE_LEFT] = property; break;
+ case CTF_RIGHTBORDERDISTANCE: pBorderDistances[XML_LINE_RIGHT] = property; break;
+ case CTF_TOPBORDERDISTANCE: pBorderDistances[XML_LINE_TOP] = property; break;
+ case CTF_BOTTOMBORDERDISTANCE: pBorderDistances[XML_LINE_BOTTOM] = property; break;
+ case CTF_ALLBORDER: pAllBorder = property; break;
+ case CTF_LEFTBORDER: pBorders[XML_LINE_LEFT] = property; break;
+ case CTF_RIGHTBORDER: pBorders[XML_LINE_RIGHT] = property; break;
+ case CTF_TOPBORDER: pBorders[XML_LINE_TOP] = property; break;
+ case CTF_BOTTOMBORDER: pBorders[XML_LINE_BOTTOM] = property; break;
+ case CTF_ALLBORDERWIDTH: pAllBorderWidth = property; break;
+ case CTF_LEFTBORDERWIDTH: pBorderWidths[XML_LINE_LEFT] = property; break;
+ case CTF_RIGHTBORDERWIDTH: pBorderWidths[XML_LINE_RIGHT] = property; break;
+ case CTF_TOPBORDERWIDTH: pBorderWidths[XML_LINE_TOP] = property; break;
+ case CTF_BOTTOMBORDERWIDTH: pBorderWidths[XML_LINE_BOTTOM] = property; break;
+
+ case CTF_CHARALLBORDERDISTANCE: pCharAllBorderDistance = property; break;
+ case CTF_CHARLEFTBORDERDISTANCE: pCharBorderDistances[XML_LINE_LEFT] = property; break;
+ case CTF_CHARRIGHTBORDERDISTANCE: pCharBorderDistances[XML_LINE_RIGHT] = property; break;
+ case CTF_CHARTOPBORDERDISTANCE: pCharBorderDistances[XML_LINE_TOP] = property; break;
+ case CTF_CHARBOTTOMBORDERDISTANCE: pCharBorderDistances[XML_LINE_BOTTOM] = property; break;
+ case CTF_CHARALLBORDER: pCharAllBorder = property; break;
+ case CTF_CHARLEFTBORDER: pCharBorders[XML_LINE_LEFT] = property; break;
+ case CTF_CHARRIGHTBORDER: pCharBorders[XML_LINE_RIGHT] = property; break;
+ case CTF_CHARTOPBORDER: pCharBorders[XML_LINE_TOP] = property; break;
+ case CTF_CHARBOTTOMBORDER: pCharBorders[XML_LINE_BOTTOM] = property; break;
+ case CTF_CHARALLBORDERWIDTH: pCharAllBorderWidth = property; break;
+ case CTF_CHARLEFTBORDERWIDTH: pCharBorderWidths[XML_LINE_LEFT] = property; break;
+ case CTF_CHARRIGHTBORDERWIDTH: pCharBorderWidths[XML_LINE_RIGHT] = property; break;
+ case CTF_CHARTOPBORDERWIDTH: pCharBorderWidths[XML_LINE_TOP] = property; break;
+ case CTF_CHARBOTTOMBORDERWIDTH: pCharBorderWidths[XML_LINE_BOTTOM] = property; break;
+
+ case CTF_ANCHORTYPE: break;
+ case CTF_VERTICALPOS: pVertOrient = property; break;
+ case CTF_VERTICALREL_ASCHAR: pVertOrientRelAsChar = property; break;
+
+ case CTF_FRAMEHEIGHT_MIN_ABS:
+ case CTF_FRAMEHEIGHT_MIN_REL:
+// case CTF_SYNCHEIGHT_MIN:
+ bHasAnyMinHeight = true;
+ [[fallthrough]];
+ case CTF_FRAMEHEIGHT_ABS:
+ case CTF_FRAMEHEIGHT_REL:
+// case CTF_SYNCHEIGHT:
+ bHasAnyHeight = true; break;
+ case CTF_FRAMEWIDTH_MIN_ABS:
+ case CTF_FRAMEWIDTH_MIN_REL:
+ bHasAnyMinWidth = true;
+ [[fallthrough]];
+ case CTF_FRAMEWIDTH_ABS:
+ case CTF_FRAMEWIDTH_REL:
+ bHasAnyWidth = true; break;
+ case CTF_BACKGROUND_TRANSPARENCY: pBackTransparency = property; break;
+ case CTF_BACKGROUND_TRANSPARENT: pBackTransparent = property; break;
+ case CTF_FILLSTYLE: pFillStyle = property; break;
+ case CTF_FILLCOLOR: pFillColor = property; break;
+ case CTF_PARAMARGINALL:
+ case CTF_PARAMARGINALL_REL:
+ pAllParaMargin = property; break;
+ case CTF_PARALEFTMARGIN:
+ case CTF_PARALEFTMARGIN_REL:
+ pParaMargins[XML_LINE_LEFT] = property; break;
+ case CTF_PARARIGHTMARGIN:
+ case CTF_PARARIGHTMARGIN_REL:
+ pParaMargins[XML_LINE_RIGHT] = property; break;
+ case CTF_PARATOPMARGIN:
+ case CTF_PARATOPMARGIN_REL:
+ pParaMargins[XML_LINE_TOP] = property; break;
+ case CTF_PARABOTTOMMARGIN:
+ case CTF_PARABOTTOMMARGIN_REL:
+ pParaMargins[XML_LINE_BOTTOM] = property; break;
+ case CTF_MARGINALL:
+ pAllMargin = property; break;
+ case CTF_MARGINLEFT:
+ pMargins[XML_LINE_LEFT] = property; break;
+ case CTF_MARGINRIGHT:
+ pMargins[XML_LINE_RIGHT] = property; break;
+ case CTF_MARGINTOP:
+ pMargins[XML_LINE_TOP] = property; break;
+ case CTF_MARGINBOTTOM:
+ pMargins[XML_LINE_BOTTOM] = property; break;
+ }
+ }
+
+ if( pFontFamilyName || pFontStyleName || pFontFamily ||
+ pFontPitch || pFontCharSet )
+ FontFinished( pFontFamilyName, pFontStyleName, pFontFamily,
+ pFontPitch, pFontCharSet );
+ if( pFontFamilyNameCJK || pFontStyleNameCJK || pFontFamilyCJK ||
+ pFontPitchCJK || pFontCharSetCJK )
+ FontFinished( pFontFamilyNameCJK, pFontStyleNameCJK, pFontFamilyCJK,
+ pFontPitchCJK, pFontCharSetCJK );
+ if( pFontFamilyNameCTL || pFontStyleNameCTL || pFontFamilyCTL ||
+ pFontPitchCTL || pFontCharSetCTL )
+ FontFinished( pFontFamilyNameCTL, pFontStyleNameCTL, pFontFamilyCTL,
+ pFontPitchCTL, pFontCharSetCTL );
+
+ for (sal_uInt16 i = 0; i < 4; i++)
+ {
+ if (pAllParaMargin && !pParaMargins[i]
+ && isNotDefaultRelSize(pAllParaMargin, getPropertySetMapper()))
+ {
+#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
+ sal_Int16 nTmp = getPropertySetMapper()->GetEntryContextId(
+ pAllParaMargin->mnIndex + (2*i) + 2 );
+ assert(nTmp >= CTF_PARALEFTMARGIN &&
+ nTmp <= CTF_PARABOTTOMMARGIN_REL);
+#endif
+ pNewParaMargins[i].emplace(
+ pAllParaMargin->mnIndex + (2*i) + 2, pAllParaMargin->maValue);
+ }
+ if (pAllMargin && !pMargins[i])
+ {
+#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
+ sal_Int16 nTmp = getPropertySetMapper()->GetEntryContextId(
+ pAllMargin->mnIndex + i + 1 );
+ assert(nTmp >= CTF_MARGINLEFT && nTmp <= CTF_MARGINBOTTOM);
+#endif
+ pNewMargins[i].emplace(
+ pAllMargin->mnIndex + i + 1, pAllMargin->maValue);
+ }
+
+ lcl_SeparateBorder(
+ i, pAllBorderDistance, pBorderDistances, pNewBorderDistances,
+ pAllBorder, pBorders, pNewBorders,
+ pAllBorderWidth, pBorderWidths
+#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
+ , getPropertySetMapper()
+#endif
+ );
+
+ lcl_SeparateBorder(
+ i, pCharAllBorderDistance, pCharBorderDistances,
+ pCharNewBorderDistances, pCharAllBorder, pCharBorders,
+ pCharNewBorders, pCharAllBorderWidth, pCharBorderWidths
+#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
+ , getPropertySetMapper()
+#endif
+ );
+ }
+
+ if (pAllParaMargin)
+ {
+ pAllParaMargin->mnIndex = -1;
+ }
+ if (pAllMargin)
+ {
+ pAllMargin->mnIndex = -1;
+ }
+
+ if( pAllBorderDistance )
+ pAllBorderDistance->mnIndex = -1;
+
+ if( pAllBorder )
+ pAllBorder->mnIndex = -1;
+
+ if( pAllBorderWidth )
+ pAllBorderWidth->mnIndex = -1;
+
+ if( pCharAllBorderDistance )
+ pCharAllBorderDistance->mnIndex = -1;
+
+ if( pCharAllBorder )
+ pCharAllBorder->mnIndex = -1;
+
+ if( pCharAllBorderWidth )
+ pCharAllBorderWidth->mnIndex = -1;
+
+ if( pVertOrient && pVertOrientRelAsChar )
+ {
+ sal_Int16 nVertOrient;
+ pVertOrient->maValue >>= nVertOrient;
+ sal_Int16 nVertOrientRel = 0;
+ pVertOrientRelAsChar->maValue >>= nVertOrientRel;
+ switch( nVertOrient )
+ {
+ case VertOrientation::TOP:
+ nVertOrient = nVertOrientRel;
+ break;
+ case VertOrientation::CENTER:
+ switch( nVertOrientRel )
+ {
+ case VertOrientation::CHAR_TOP:
+ nVertOrient = VertOrientation::CHAR_CENTER;
+ break;
+ case VertOrientation::LINE_TOP:
+ nVertOrient = VertOrientation::LINE_CENTER;
+ break;
+ }
+ break;
+ case VertOrientation::BOTTOM:
+ switch( nVertOrientRel )
+ {
+ case VertOrientation::CHAR_TOP:
+ nVertOrient = VertOrientation::CHAR_BOTTOM;
+ break;
+ case VertOrientation::LINE_TOP:
+ nVertOrient = VertOrientation::LINE_BOTTOM;
+ break;
+ }
+ break;
+ }
+ pVertOrient->maValue <<= nVertOrient;
+ pVertOrientRelAsChar->mnIndex = -1;
+ }
+
+ FontDefaultsCheck( pFontFamilyName,
+ pFontStyleName, pFontFamily, pFontPitch, pFontCharSet,
+ &pNewFontStyleName, &pNewFontFamily, &pNewFontPitch, &pNewFontCharSet );
+
+ FontDefaultsCheck( pFontFamilyNameCJK,
+ pFontStyleNameCJK, pFontFamilyCJK, pFontPitchCJK, pFontCharSetCJK,
+ &pNewFontStyleNameCJK, &pNewFontFamilyCJK, &pNewFontPitchCJK, &pNewFontCharSetCJK );
+
+ FontDefaultsCheck( pFontFamilyNameCTL,
+ pFontStyleNameCTL, pFontFamilyCTL, pFontPitchCTL, pFontCharSetCTL,
+ &pNewFontStyleNameCTL, &pNewFontFamilyCTL, &pNewFontPitchCTL, &pNewFontCharSetCTL );
+
+ if (pFillStyle && !pFillColor && pBackTransparent
+ && drawing::FillStyle_SOLID == pFillStyle->maValue.get<drawing::FillStyle>()
+ && pBackTransparent->maValue.get<bool>())
+ {
+ // fo:background="transparent", draw:fill="solid" without draw:fill-color
+ // prevent getSvxBrushItemFromSourceSet from adding bogus default color
+ pFillStyle->mnIndex = -1;
+ }
+
+ // #i5775# don't overwrite %transparency with binary transparency
+ if( ( pBackTransparency != nullptr ) && ( pBackTransparent != nullptr ) )
+ {
+ if( ! *o3tl::doAccess<bool>(pBackTransparent->maValue) )
+ pBackTransparent->mnIndex = -1;
+ }
+
+
+ // insert newly created properties. This invalidates all iterators!
+ // Most of the pXXX variables in this method are iterators and will be
+ // invalidated!!!
+
+ if( pNewFontStyleName )
+ {
+ rProperties.push_back( *pNewFontStyleName );
+ pNewFontStyleName.reset();
+ }
+
+ if( pNewFontFamily )
+ {
+ rProperties.push_back( *pNewFontFamily );
+ pNewFontFamily.reset();
+ }
+
+ if( pNewFontPitch )
+ {
+ rProperties.push_back( *pNewFontPitch );
+ pNewFontPitch.reset();
+ }
+
+ if( pNewFontCharSet )
+ {
+ rProperties.push_back( *pNewFontCharSet );
+ pNewFontCharSet.reset();
+ }
+
+ if( pNewFontStyleNameCJK )
+ {
+ rProperties.push_back( *pNewFontStyleNameCJK );
+ pNewFontStyleNameCJK.reset();
+ }
+
+ if( pNewFontFamilyCJK )
+ {
+ rProperties.push_back( *pNewFontFamilyCJK );
+ pNewFontFamilyCJK.reset();
+ }
+
+ if( pNewFontPitchCJK )
+ {
+ rProperties.push_back( *pNewFontPitchCJK );
+ pNewFontPitchCJK.reset();
+ }
+
+ if( pNewFontCharSetCJK )
+ {
+ rProperties.push_back( *pNewFontCharSetCJK );
+ pNewFontCharSetCJK.reset();
+ }
+
+ if( pNewFontStyleNameCTL)
+ {
+ rProperties.push_back( *pNewFontStyleNameCTL );
+ pNewFontStyleNameCTL.reset();
+ }
+
+ if( pNewFontFamilyCTL )
+ {
+ rProperties.push_back( *pNewFontFamilyCTL );
+ pNewFontFamilyCTL.reset();
+ }
+
+ if( pNewFontPitchCTL )
+ {
+ rProperties.push_back( *pNewFontPitchCTL );
+ pNewFontPitchCTL.reset();
+ }
+
+ if( pNewFontCharSetCTL )
+ {
+ rProperties.push_back( *pNewFontCharSetCTL );
+ pNewFontCharSetCTL.reset();
+ }
+
+ for (sal_uInt16 i=0; i<4; i++)
+ {
+ if (pNewParaMargins[i])
+ {
+ rProperties.push_back(*pNewParaMargins[i]);
+ }
+ if (pNewMargins[i])
+ {
+ rProperties.push_back(*pNewMargins[i]);
+ }
+ if( pNewBorderDistances[i] )
+ {
+ rProperties.push_back( *pNewBorderDistances[i] );
+ delete pNewBorderDistances[i];
+ }
+ if( pNewBorders[i] )
+ {
+ rProperties.push_back( *pNewBorders[i] );
+ delete pNewBorders[i];
+ }
+ if( pCharNewBorderDistances[i] )
+ {
+ rProperties.push_back( *pCharNewBorderDistances[i] );
+ delete pCharNewBorderDistances[i];
+ }
+ if( pCharNewBorders[i] )
+ {
+ rProperties.push_back( *pCharNewBorders[i] );
+ delete pCharNewBorders[i];
+ }
+ }
+
+ if( bHasAnyHeight )
+ {
+ if( m_nSizeTypeIndex == -2 )
+ {
+ const_cast < XMLTextImportPropertyMapper * > ( this )
+ ->m_nSizeTypeIndex = -1;
+ sal_Int32 nPropCount = getPropertySetMapper()->GetEntryCount();
+ for( sal_Int32 j=0; j < nPropCount; j++ )
+ {
+ if( CTF_SIZETYPE == getPropertySetMapper()
+ ->GetEntryContextId( j ) )
+ {
+ const_cast < XMLTextImportPropertyMapper * > ( this )
+ ->m_nSizeTypeIndex = j;
+ break;
+ }
+ }
+ }
+ if( m_nSizeTypeIndex != -1 )
+ {
+ XMLPropertyState aSizeTypeState( m_nSizeTypeIndex );
+ aSizeTypeState.maValue <<= static_cast<sal_Int16>( bHasAnyMinHeight
+ ? SizeType::MIN
+ : SizeType::FIX);
+ rProperties.push_back( aSizeTypeState );
+ }
+ }
+
+ if( !bHasAnyWidth )
+ return;
+
+ if( m_nWidthTypeIndex == -2 )
+ {
+ const_cast < XMLTextImportPropertyMapper * > ( this )
+ ->m_nWidthTypeIndex = -1;
+ sal_Int32 nCount = getPropertySetMapper()->GetEntryCount();
+ for( sal_Int32 j=0; j < nCount; j++ )
+ {
+ if( CTF_FRAMEWIDTH_TYPE == getPropertySetMapper()
+ ->GetEntryContextId( j ) )
+ {
+ const_cast < XMLTextImportPropertyMapper * > ( this )
+ ->m_nWidthTypeIndex = j;
+ break;
+ }
+ }
+ }
+ if( m_nWidthTypeIndex != -1 )
+ {
+ XMLPropertyState aSizeTypeState( m_nWidthTypeIndex );
+ aSizeTypeState.maValue <<= static_cast<sal_Int16>( bHasAnyMinWidth
+ ? SizeType::MIN
+ : SizeType::FIX);
+ rProperties.push_back( aSizeTypeState );
+ }
+
+ // DO NOT USE ITERATORS/POINTERS INTO THE rProperties-VECTOR AFTER
+ // THIS LINE. All iterators into the rProperties-vector, especially all
+ // pXXX-type variables set in the first switch statement of this method,
+ // may have been invalidated by the above push_back() calls!
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/txtlists.cxx b/xmloff/source/text/txtlists.cxx
new file mode 100644
index 0000000000..9b3b46f175
--- /dev/null
+++ b/xmloff/source/text/txtlists.cxx
@@ -0,0 +1,499 @@
+/* -*- 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 <txtlists.hxx>
+#include <comphelper/random.hxx>
+
+#include <o3tl/safeint.hxx>
+#include <tools/datetime.hxx>
+#include <tools/long.hxx>
+#include <sal/log.hxx>
+
+#include <xmloff/txtimp.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmlnumi.hxx>
+
+#include <com/sun/star/style/XStyle.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include "XMLTextListItemContext.hxx"
+#include "XMLTextListBlockContext.hxx"
+#include "txtparai.hxx"
+
+
+using namespace ::com::sun::star;
+
+
+XMLTextListsHelper::XMLTextListsHelper()
+ // Inconsistent behavior regarding lists (#i92811#)
+{
+}
+
+void XMLTextListsHelper::PushListContext(
+ XMLTextListBlockContext *i_pListBlock)
+{
+ mListStack.emplace(i_pListBlock,
+ static_cast<XMLTextListItemContext*>(nullptr),
+ static_cast<XMLNumberedParaContext*>(nullptr));
+}
+
+void XMLTextListsHelper::PushListContext(
+ XMLNumberedParaContext *i_pNumberedParagraph)
+{
+ mListStack.emplace(
+ static_cast<XMLTextListBlockContext*>(nullptr),
+ static_cast<XMLTextListItemContext*>(nullptr), i_pNumberedParagraph);
+}
+
+void XMLTextListsHelper::PopListContext()
+{
+ assert(mListStack.size());
+ if ( !mListStack.empty())
+ mListStack.pop();
+}
+
+void XMLTextListsHelper::ListContextTop(
+ XMLTextListBlockContext*& o_pListBlockContext,
+ XMLTextListItemContext*& o_pListItemContext,
+ XMLNumberedParaContext*& o_pNumberedParagraphContext )
+{
+ if ( !mListStack.empty() ) {
+ o_pListBlockContext =
+ static_cast<XMLTextListBlockContext*>(std::get<0>(mListStack.top()).get());
+ o_pListItemContext =
+ static_cast<XMLTextListItemContext *>(std::get<1>(mListStack.top()).get());
+ o_pNumberedParagraphContext =
+ static_cast<XMLNumberedParaContext *>(std::get<2>(mListStack.top()).get());
+ }
+}
+
+void XMLTextListsHelper::SetListItem( XMLTextListItemContext *i_pListItem )
+{
+ // may be cleared by ListBlockContext for upper list...
+ if (i_pListItem) {
+ assert(mListStack.size());
+ assert(std::get<0>(mListStack.top()).is() &&
+ "internal error: SetListItem: mListStack has no ListBlock");
+ assert(!std::get<1>(mListStack.top()).is() &&
+ "error: SetListItem: list item already exists");
+ }
+ if ( !mListStack.empty() ) {
+ std::get<1>(mListStack.top()) = i_pListItem;
+ }
+}
+
+// Handling for parameter <sListStyleDefaultListId> (#i92811#)
+void XMLTextListsHelper::KeepListAsProcessed( const OUString& sListId,
+ const OUString& sListStyleName,
+ const OUString& sContinueListId,
+ const OUString& sListStyleDefaultListId )
+{
+ if ( IsListProcessed( sListId ) )
+ {
+ assert(false &&
+ "<XMLTextListsHelper::KeepListAsProcessed(..)> - list id already added" );
+ return;
+ }
+
+ if ( !mpProcessedLists )
+ {
+ mpProcessedLists = std::make_unique<tMapForLists>();
+ }
+
+ ::std::pair< OUString, OUString >
+ aListData( sListStyleName, sContinueListId );
+ (*mpProcessedLists)[ sListId ] = aListData;
+
+ msLastProcessedListId = sListId;
+ msListStyleOfLastProcessedList = sListStyleName;
+
+ // Remember what is the last list id of this list style.
+ if (!mpStyleNameLastListIds)
+ {
+ mpStyleNameLastListIds = std::make_unique<std::map<OUString, OUString>>();
+ }
+ (*mpStyleNameLastListIds)[sListStyleName] = sListId;
+
+ // Inconsistent behavior regarding lists (#i92811#)
+ if ( sListStyleDefaultListId.isEmpty())
+ return;
+
+ if ( !mpMapListIdToListStyleDefaultListId )
+ {
+ mpMapListIdToListStyleDefaultListId = std::make_unique<tMapForLists>();
+ }
+
+ if ( mpMapListIdToListStyleDefaultListId->find( sListStyleName ) ==
+ mpMapListIdToListStyleDefaultListId->end() )
+ {
+ ::std::pair< OUString, OUString >
+ aListIdMapData( sListId, sListStyleDefaultListId );
+ (*mpMapListIdToListStyleDefaultListId)[ sListStyleName ] =
+ aListIdMapData;
+ }
+}
+
+bool XMLTextListsHelper::IsListProcessed( const OUString& sListId ) const
+{
+ if ( !mpProcessedLists )
+ {
+ return false;
+ }
+
+ return mpProcessedLists->find( sListId ) != mpProcessedLists->end();
+}
+
+OUString XMLTextListsHelper::GetListStyleOfProcessedList(
+ const OUString& sListId ) const
+{
+ if ( mpProcessedLists )
+ {
+ tMapForLists::const_iterator aIter = mpProcessedLists->find( sListId );
+ if ( aIter != mpProcessedLists->end() )
+ {
+ return (*aIter).second.first;
+ }
+ }
+
+ return OUString();
+}
+
+OUString XMLTextListsHelper::GetContinueListIdOfProcessedList(
+ const OUString& sListId ) const
+{
+ if ( mpProcessedLists )
+ {
+ tMapForLists::const_iterator aIter = mpProcessedLists->find( sListId );
+ if ( aIter != mpProcessedLists->end() )
+ {
+ return (*aIter).second.second;
+ }
+ }
+
+ return OUString();
+}
+
+
+OUString XMLTextListsHelper::GenerateNewListId() const
+{
+ static bool bHack = (getenv("LIBO_ONEWAY_STABLE_ODF_EXPORT") != nullptr);
+ OUString sTmpStr( "list" );
+
+ if (bHack)
+ {
+ static sal_Int64 nIdCounter = SAL_CONST_INT64(5000000000);
+ sTmpStr += OUString::number(nIdCounter++);
+ }
+ else
+ {
+ // Value of xml:id in element <text:list> has to be a valid ID type (#i92478#)
+ DateTime aDateTime( DateTime::SYSTEM );
+ sal_Int64 n = aDateTime.GetTime();
+ n += aDateTime.GetDateUnsigned();
+ n += comphelper::rng::uniform_int_distribution(0, std::numeric_limits<int>::max());
+ // Value of xml:id in element <text:list> has to be a valid ID type (#i92478#)
+ sTmpStr += OUString::number( n );
+ }
+
+ OUString sNewListId( sTmpStr );
+ if ( mpProcessedLists )
+ {
+ tools::Long nHitCount = 0;
+ while ( mpProcessedLists->find( sNewListId ) != mpProcessedLists->end() )
+ {
+ ++nHitCount;
+ sNewListId = sTmpStr + OUString::number( nHitCount );
+ }
+ }
+
+ return sNewListId;
+}
+
+// Provide list id for a certain list block for import (#i92811#)
+OUString XMLTextListsHelper::GetListIdForListBlock( XMLTextListBlockContext const & rListBlock )
+{
+ OUString sListBlockListId( rListBlock.GetContinueListId() );
+ if ( sListBlockListId.isEmpty() )
+ {
+ sListBlockListId = rListBlock.GetListId();
+ }
+
+ if ( mpMapListIdToListStyleDefaultListId )
+ {
+ if ( !sListBlockListId.isEmpty() )
+ {
+ const OUString sListStyleName =
+ GetListStyleOfProcessedList( sListBlockListId );
+
+ tMapForLists::const_iterator aIter =
+ mpMapListIdToListStyleDefaultListId->find( sListStyleName );
+ if ( aIter != mpMapListIdToListStyleDefaultListId->end() )
+ {
+ if ( (*aIter).second.first == sListBlockListId )
+ {
+ sListBlockListId = (*aIter).second.second;
+ }
+ }
+ }
+ }
+
+ return sListBlockListId;
+}
+
+void XMLTextListsHelper::StoreLastContinuingList( const OUString& sListId,
+ const OUString& sContinuingListId )
+{
+ if ( !mpContinuingLists )
+ {
+ mpContinuingLists = std::make_unique<tMapForContinuingLists>();
+ }
+
+ (*mpContinuingLists)[ sListId ] = sContinuingListId;
+}
+
+OUString XMLTextListsHelper::GetLastContinuingListId(
+ const OUString& sListId ) const
+{
+ if ( mpContinuingLists )
+ {
+ tMapForContinuingLists::const_iterator aIter =
+ mpContinuingLists->find( sListId );
+ if ( aIter != mpContinuingLists->end() )
+ {
+ return (*aIter).second;
+ }
+ }
+
+ return sListId;
+}
+
+void XMLTextListsHelper::PushListOnStack( const OUString& sListId,
+ const OUString& sListStyleName )
+{
+ if ( !mpListStack )
+ {
+ mpListStack = std::make_unique<tStackForLists>();
+ }
+ ::std::pair< OUString, OUString >
+ aListData( sListId, sListStyleName );
+ mpListStack->push_back( aListData );
+}
+void XMLTextListsHelper::PopListFromStack()
+{
+ if ( mpListStack &&
+ !mpListStack->empty() )
+ {
+ mpListStack->pop_back();
+ }
+}
+
+bool XMLTextListsHelper::EqualsToTopListStyleOnStack( std::u16string_view sListId ) const
+{
+ return mpListStack && sListId == mpListStack->back().second;
+}
+
+OUString
+XMLTextListsHelper::GetNumberedParagraphListId(
+ const sal_uInt16 i_Level,
+ std::u16string_view i_StyleName)
+{
+ if (i_StyleName.empty()) {
+ SAL_INFO("xmloff.text", "invalid numbered-paragraph: no style-name");
+ }
+ if (!i_StyleName.empty()
+ && (i_Level < mLastNumberedParagraphs.size())
+ && (mLastNumberedParagraphs[i_Level].first == i_StyleName) )
+ {
+ assert(!mLastNumberedParagraphs[i_Level].second.isEmpty() &&
+ "internal error: numbered-paragraph style-name but no list-id?");
+ return mLastNumberedParagraphs[i_Level].second;
+ } else {
+ return GenerateNewListId();
+ }
+}
+
+static void
+ClampLevel(uno::Reference<container::XIndexReplace> const& i_xNumRules,
+ sal_Int16 & io_rLevel)
+{
+ assert(i_xNumRules.is());
+ if (i_xNumRules.is()) {
+ const sal_Int32 nLevelCount( i_xNumRules->getCount() );
+ if ( io_rLevel >= nLevelCount ) {
+ io_rLevel = sal::static_int_cast< sal_Int16 >(nLevelCount-1);
+ }
+ }
+}
+
+uno::Reference<container::XIndexReplace>
+XMLTextListsHelper::EnsureNumberedParagraph(
+ SvXMLImport & i_rImport,
+ const OUString& i_ListId,
+ sal_Int16 & io_rLevel, const OUString& i_StyleName)
+{
+ assert(!i_ListId.isEmpty());
+ assert(io_rLevel >= 0);
+ NumParaList_t & rNPList( mNPLists[i_ListId] );
+ const OUString none; // default
+ if ( rNPList.empty() ) {
+ // create default list style for top level
+ sal_Int16 lev(0);
+ rNPList.emplace_back(none,
+ MakeNumRule(i_rImport, nullptr, none, none, lev) );
+ }
+ // create num rule first because this might clamp the level...
+ uno::Reference<container::XIndexReplace> xNumRules;
+ if ((0 == io_rLevel) || rNPList.empty() || !i_StyleName.isEmpty()) {
+ // no parent to inherit from, or explicit style given => new numrules!
+ // index of parent: level - 1, but maybe that does not exist
+ const size_t parent( std::min(static_cast<size_t>(io_rLevel),
+ rNPList.size()) - 1 );
+ xNumRules = MakeNumRule(i_rImport,
+ io_rLevel > 0 ? rNPList[parent].second : nullptr,
+ io_rLevel > 0 ? rNPList[parent].first : none,
+ i_StyleName, io_rLevel);
+ } else {
+ // no style given, but has a parent => reuse parent numrules!
+ ClampLevel(rNPList.back().second, io_rLevel);
+ }
+ if (static_cast<sal_uInt16>(io_rLevel) + 1U > rNPList.size()) {
+ // new level: need to enlarge
+ for (size_t i = rNPList.size();
+ i < o3tl::make_unsigned(io_rLevel); ++i)
+ {
+ NumParaList_t::value_type const rule(rNPList.back());
+ rNPList.push_back(rule);
+ }
+ NumParaList_t::value_type const rule(rNPList.back());
+ rNPList.push_back(xNumRules.is()
+ ? ::std::make_pair(i_StyleName, xNumRules)
+ : rule);
+ } else {
+ // old level: no need to enlarge; possibly shrink
+ if (xNumRules.is()) {
+ rNPList[io_rLevel] = std::make_pair(i_StyleName, xNumRules);
+ }
+ if (static_cast<sal_uInt16>(io_rLevel) + 1U < rNPList.size()) {
+ rNPList.erase(rNPList.begin() + io_rLevel + 1, rNPList.end());
+ }
+ }
+ // remember the list id
+ if (mLastNumberedParagraphs.size() <= o3tl::make_unsigned(io_rLevel)) {
+ mLastNumberedParagraphs.resize(io_rLevel+1);
+ }
+ mLastNumberedParagraphs[io_rLevel] = std::make_pair(i_StyleName, i_ListId);
+ return rNPList.back().second;
+}
+
+/** extracted from the XMLTextListBlockContext constructor */
+uno::Reference<container::XIndexReplace>
+XMLTextListsHelper::MakeNumRule(
+ SvXMLImport & i_rImport,
+ const uno::Reference<container::XIndexReplace>& i_rNumRule,
+ std::u16string_view i_ParentStyleName,
+ const OUString& i_StyleName,
+ sal_Int16 & io_rLevel,
+ bool* o_pRestartNumbering,
+ bool* io_pSetDefaults)
+{
+ uno::Reference<container::XIndexReplace> xNumRules(i_rNumRule);
+ if ( !i_StyleName.isEmpty() && i_StyleName != i_ParentStyleName )
+ {
+ const OUString sDisplayStyleName(
+ i_rImport.GetStyleDisplayName( XmlStyleFamily::TEXT_LIST,
+ i_StyleName) );
+ const uno::Reference < container::XNameContainer >& rNumStyles(
+ i_rImport.GetTextImport()->GetNumberingStyles() );
+ if( rNumStyles.is() && rNumStyles->hasByName( sDisplayStyleName ) )
+ {
+ uno::Reference < style::XStyle > xStyle;
+ uno::Any any = rNumStyles->getByName( sDisplayStyleName );
+ any >>= xStyle;
+
+ uno::Reference< beans::XPropertySet > xPropSet( xStyle,
+ uno::UNO_QUERY );
+ any = xPropSet->getPropertyValue("NumberingRules");
+ any >>= xNumRules;
+ }
+ else
+ {
+ const SvxXMLListStyleContext *pListStyle(
+ i_rImport.GetTextImport()->FindAutoListStyle( i_StyleName ) );
+ if( pListStyle )
+ {
+ xNumRules = pListStyle->GetNumRules();
+ if( !xNumRules.is() )
+ {
+ pListStyle->CreateAndInsertAuto();
+ xNumRules = pListStyle->GetNumRules();
+ }
+ }
+ }
+ }
+
+ bool bSetDefaults(io_pSetDefaults && *io_pSetDefaults);
+ if ( !xNumRules.is() )
+ {
+ // If no style name has been specified for this style and for any
+ // parent or if no num rule with the specified name exists,
+ // create a new one.
+
+ xNumRules =
+ SvxXMLListStyleContext::CreateNumRule( i_rImport.GetModel() );
+ SAL_INFO_IF(xNumRules.is(), "xmloff.core", "cannot create numrules");
+ if ( !xNumRules.is() )
+ return xNumRules;
+
+ // Because it is a new num rule, numbering must not be restarted.
+ if (o_pRestartNumbering) *o_pRestartNumbering = false;
+ bSetDefaults = true;
+ if (io_pSetDefaults) *io_pSetDefaults = bSetDefaults;
+ }
+
+ ClampLevel(xNumRules, io_rLevel);
+
+ if ( bSetDefaults )
+ {
+ // Because there is no list style sheet for this style, a default
+ // format must be set for any level of this num rule.
+ SvxXMLListStyleContext::SetDefaultStyle( xNumRules, io_rLevel,
+ false );
+ }
+
+ return xNumRules;
+}
+
+OUString XMLTextListsHelper::GetLastIdOfStyleName(const OUString& sListStyleName) const
+{
+ if (!mpStyleNameLastListIds)
+ {
+ return {};
+ }
+
+ auto it = mpStyleNameLastListIds->find(sListStyleName);
+ if (it == mpStyleNameLastListIds->end())
+ {
+ return {};
+ }
+
+ return it->second;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/txtparae.cxx b/xmloff/source/text/txtparae.cxx
new file mode 100644
index 0000000000..f55ee10558
--- /dev/null
+++ b/xmloff/source/text/txtparae.cxx
@@ -0,0 +1,4351 @@
+/* -*- 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 <o3tl/any.hxx>
+#include <xmloff/unointerfacetouniqueidentifiermapper.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/types.h>
+#include <sal/log.hxx>
+#include <osl/diagnose.h>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+#include <com/sun/star/container/XEnumeration.hpp>
+#include <com/sun/star/container/XIndexReplace.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/beans/UnknownPropertyException.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <com/sun/star/text/XTextDocument.hpp>
+#include <com/sun/star/text/XTextSectionsSupplier.hpp>
+#include <com/sun/star/text/XTextTablesSupplier.hpp>
+#include <com/sun/star/text/XNumberingRulesSupplier.hpp>
+#include <com/sun/star/text/XChapterNumberingSupplier.hpp>
+#include <com/sun/star/text/XTextTable.hpp>
+#include <com/sun/star/text/XText.hpp>
+#include <com/sun/star/text/XTextContent.hpp>
+#include <com/sun/star/text/XTextRange.hpp>
+#include <com/sun/star/text/XTextField.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/container/XContentEnumerationAccess.hpp>
+#include <com/sun/star/text/XTextFrame.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/text/SizeType.hpp>
+#include <com/sun/star/text/HoriOrientation.hpp>
+#include <com/sun/star/text/VertOrientation.hpp>
+#include <com/sun/star/text/TextContentAnchorType.hpp>
+#include <com/sun/star/text/XTextFramesSupplier.hpp>
+#include <com/sun/star/text/XTextGraphicObjectsSupplier.hpp>
+#include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
+#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
+#include <com/sun/star/document/XEmbeddedObjectSupplier.hpp>
+#include <com/sun/star/document/XEventsSupplier.hpp>
+#include <com/sun/star/document/XRedlinesSupplier.hpp>
+#include <com/sun/star/text/XFormField.hpp>
+#include <com/sun/star/text/XTextSection.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/style/XAutoStylesSupplier.hpp>
+#include <com/sun/star/style/XAutoStyleFamily.hpp>
+#include <com/sun/star/text/XTextFieldsSupplier.hpp>
+#include <com/sun/star/drawing/XControlShape.hpp>
+#include <com/sun/star/util/DateTime.hpp>
+
+#include <sax/tools/converter.hxx>
+
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmlaustp.hxx>
+#include <xmloff/families.hxx>
+#include "txtexppr.hxx"
+#include <xmloff/xmluconv.hxx>
+#include "XMLAnchorTypePropHdl.hxx"
+#include <xexptran.hxx>
+#include <xmloff/ProgressBarHelper.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <txtflde.hxx>
+#include <xmloff/txtprmap.hxx>
+#include <XMLImageMapExport.hxx>
+#include "XMLTextNumRuleInfo.hxx"
+#include <xmloff/XMLTextListAutoStylePool.hxx>
+#include <xmloff/txtparae.hxx>
+#include "XMLSectionExport.hxx"
+#include "XMLIndexMarkExport.hxx"
+#include <xmloff/XMLEventExport.hxx>
+#include "XMLRedlineExport.hxx"
+#include <MultiPropertySetHelper.hxx>
+#include <xmloff/formlayerexport.hxx>
+#include "XMLTextCharStyleNamesElementExport.hxx"
+#include <xmloff/odffields.hxx>
+#include <xmloff/maptype.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <com/sun/star/document/XStorageBasedDocument.hpp>
+#include <txtlists.hxx>
+#include <com/sun/star/rdf/XMetadatable.hpp>
+#include <list>
+#include <unordered_map>
+#include <memory>
+#include <vector>
+#include <algorithm>
+#include <iterator>
+#include <officecfg/Office/Common.hxx>
+#include <o3tl/safeint.hxx>
+#include <comphelper/scopeguard.hxx>
+#include <comphelper/sequenceashashmap.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::style;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::drawing;
+using namespace ::com::sun::star::document;
+using namespace ::com::sun::star::graphic;
+using namespace ::xmloff;
+using namespace ::xmloff::token;
+
+// Implement Title/Description Elements UI (#i73249#)
+constexpr OUString gsTitle(u"Title"_ustr);
+constexpr OUString gsDescription(u"Description"_ustr);
+constexpr OUStringLiteral gsAnchorPageNo(u"AnchorPageNo");
+constexpr OUStringLiteral gsAnchorType(u"AnchorType");
+constexpr OUString gsBookmark(u"Bookmark"_ustr);
+constexpr OUString gsChainNextName(u"ChainNextName"_ustr);
+constexpr OUString gsContourPolyPolygon(u"ContourPolyPolygon"_ustr);
+constexpr OUStringLiteral gsDocumentIndexMark(u"DocumentIndexMark");
+constexpr OUStringLiteral gsFrame(u"Frame");
+constexpr OUStringLiteral gsGraphicFilter(u"GraphicFilter");
+constexpr OUStringLiteral gsGraphicRotation(u"GraphicRotation");
+constexpr OUString gsHeight(u"Height"_ustr);
+constexpr OUStringLiteral gsHoriOrient(u"HoriOrient");
+constexpr OUStringLiteral gsHoriOrientPosition(u"HoriOrientPosition");
+constexpr OUString gsHyperLinkName(u"HyperLinkName"_ustr);
+constexpr OUString gsHyperLinkTarget(u"HyperLinkTarget"_ustr);
+constexpr OUString gsHyperLinkURL(u"HyperLinkURL"_ustr);
+constexpr OUString gsIsAutomaticContour(u"IsAutomaticContour"_ustr);
+constexpr OUString gsIsCollapsed(u"IsCollapsed"_ustr);
+constexpr OUString gsIsPixelContour(u"IsPixelContour"_ustr);
+constexpr OUString gsIsStart(u"IsStart"_ustr);
+constexpr OUString gsIsSyncHeightToWidth(u"IsSyncHeightToWidth"_ustr);
+constexpr OUString gsIsSyncWidthToHeight(u"IsSyncWidthToHeight"_ustr);
+constexpr OUString gsNumberingRules(u"NumberingRules"_ustr);
+constexpr OUString gsParaConditionalStyleName(u"ParaConditionalStyleName"_ustr);
+constexpr OUStringLiteral gsParagraphService(u"com.sun.star.text.Paragraph");
+constexpr OUStringLiteral gsRedline(u"Redline");
+constexpr OUString gsReferenceMark(u"ReferenceMark"_ustr);
+constexpr OUString gsRelativeHeight(u"RelativeHeight"_ustr);
+constexpr OUString gsRelativeWidth(u"RelativeWidth"_ustr);
+constexpr OUStringLiteral gsRuby(u"Ruby");
+constexpr OUStringLiteral gsRubyCharStyleName(u"RubyCharStyleName");
+constexpr OUStringLiteral gsRubyText(u"RubyText");
+constexpr OUString gsServerMap(u"ServerMap"_ustr);
+constexpr OUString gsShapeService(u"com.sun.star.drawing.Shape"_ustr);
+constexpr OUString gsSizeType(u"SizeType"_ustr);
+constexpr OUStringLiteral gsSoftPageBreak( u"SoftPageBreak" );
+constexpr OUStringLiteral gsTableService(u"com.sun.star.text.TextTable");
+constexpr OUStringLiteral gsText(u"Text");
+constexpr OUString gsTextContentService(u"com.sun.star.text.TextContent"_ustr);
+constexpr OUStringLiteral gsTextEmbeddedService(u"com.sun.star.text.TextEmbeddedObject");
+constexpr OUString gsTextField(u"TextField"_ustr);
+constexpr OUStringLiteral gsTextFieldService(u"com.sun.star.text.TextField");
+constexpr OUStringLiteral gsTextFrameService(u"com.sun.star.text.TextFrame");
+constexpr OUStringLiteral gsTextGraphicService(u"com.sun.star.text.TextGraphicObject");
+constexpr OUString gsTextPortionType(u"TextPortionType"_ustr);
+constexpr OUString gsUnvisitedCharStyleName(u"UnvisitedCharStyleName"_ustr);
+constexpr OUStringLiteral gsVertOrient(u"VertOrient");
+constexpr OUStringLiteral gsVertOrientPosition(u"VertOrientPosition");
+constexpr OUString gsVisitedCharStyleName(u"VisitedCharStyleName"_ustr);
+constexpr OUString gsWidth(u"Width"_ustr);
+constexpr OUString gsWidthType( u"WidthType"_ustr );
+constexpr OUStringLiteral gsTextFieldStart( u"TextFieldStart" );
+constexpr OUStringLiteral gsTextFieldSep(u"TextFieldSeparator");
+constexpr OUStringLiteral gsTextFieldEnd( u"TextFieldEnd" );
+constexpr OUStringLiteral gsTextFieldStartEnd( u"TextFieldStartEnd" );
+
+namespace
+{
+ class TextContentSet
+ {
+ public:
+ typedef std::list<Reference<XTextContent>> contents_t;
+ typedef std::back_insert_iterator<contents_t> inserter_t;
+ typedef contents_t::const_iterator const_iterator_t;
+
+ inserter_t getInserter()
+ { return std::back_insert_iterator<contents_t>(m_vTextContents); };
+ const_iterator_t getBegin() const
+ { return m_vTextContents.begin(); };
+ const_iterator_t getEnd() const
+ { return m_vTextContents.end(); };
+
+ private:
+ contents_t m_vTextContents;
+ };
+
+ struct FrameRefHash
+ {
+ size_t operator()(const Reference<XTextFrame>& rFrame) const
+ { return sal::static_int_cast<size_t>(reinterpret_cast<sal_uIntPtr>(rFrame.get())); }
+ };
+
+ bool lcl_TextContentsUnfiltered(const Reference<XTextContent>&)
+ { return true; };
+
+ bool lcl_ShapeFilter(const Reference<XTextContent>& xTxtContent)
+ {
+ Reference<XShape> xShape(xTxtContent, UNO_QUERY);
+ if(!xShape.is())
+ return false;
+ Reference<XServiceInfo> xServiceInfo(xTxtContent, UNO_QUERY);
+ return !xServiceInfo->supportsService("com.sun.star.text.TextFrame") &&
+ !xServiceInfo->supportsService("com.sun.star.text.TextGraphicObject") &&
+ !xServiceInfo->supportsService("com.sun.star.text.TextEmbeddedObject");
+ };
+
+ class BoundFrames
+ {
+ public:
+ typedef bool (*filter_t)(const Reference<XTextContent>&);
+ BoundFrames(
+ const Reference<XEnumerationAccess>& rEnumAccess,
+ const filter_t& rFilter)
+ : m_xEnumAccess(rEnumAccess)
+ {
+ Fill(rFilter);
+ };
+ BoundFrames()
+ {};
+ const TextContentSet& GetPageBoundContents() const
+ { return m_vPageBounds; };
+ const TextContentSet* GetFrameBoundContents(const Reference<XTextFrame>& rParentFrame) const
+ {
+ framebound_map_t::const_iterator it = m_vFrameBoundsOf.find(rParentFrame);
+ if(it == m_vFrameBoundsOf.end())
+ return nullptr;
+ return &(it->second);
+ };
+ Reference<XEnumeration> createEnumeration() const
+ {
+ if(!m_xEnumAccess.is())
+ return Reference<XEnumeration>();
+ return m_xEnumAccess->createEnumeration();
+ };
+
+ private:
+ typedef std::unordered_map<
+ Reference<XTextFrame>,
+ TextContentSet,
+ FrameRefHash> framebound_map_t;
+ TextContentSet m_vPageBounds;
+ framebound_map_t m_vFrameBoundsOf;
+ const Reference<XEnumerationAccess> m_xEnumAccess;
+ void Fill(const filter_t& rFilter);
+ };
+
+ class FieldParamExporter
+ {
+ public:
+ FieldParamExporter(SvXMLExport* const pExport, Reference<XNameContainer> const & xFieldParams)
+ : m_pExport(pExport)
+ , m_xFieldParams(xFieldParams)
+ { };
+ void Export();
+
+ private:
+ SvXMLExport* const m_pExport;
+ const Reference<XNameContainer> m_xFieldParams;
+
+ void ExportParameter(const OUString& sKey, const OUString& sValue);
+ };
+
+ struct HyperlinkData
+ {
+ OUString href, name, targetFrame, ustyleName, vstyleName;
+ bool serverMap = false;
+ css::uno::Reference<css::container::XNameReplace> events;
+
+ HyperlinkData() = default;
+ HyperlinkData(const css::uno::Reference<css::beans::XPropertySet>& rPropSet);
+
+ bool operator==(const HyperlinkData&);
+ bool operator!=(const HyperlinkData& rOther) { return !operator==(rOther); }
+
+ bool addHyperlinkAttributes(SvXMLExport& rExport);
+ void exportEvents(SvXMLExport& rExport);
+ };
+
+ HyperlinkData::HyperlinkData(const css::uno::Reference<css::beans::XPropertySet>& rPropSet)
+ {
+ const css::uno::Reference<css::beans::XPropertyState> xPropState(rPropSet, UNO_QUERY);
+ const auto xPropSetInfo(rPropSet->getPropertySetInfo());
+ if (xPropSetInfo->hasPropertyByName(gsHyperLinkURL)
+ && (!xPropState.is()
+ || PropertyState_DIRECT_VALUE == xPropState->getPropertyState(gsHyperLinkURL)))
+ {
+ rPropSet->getPropertyValue(gsHyperLinkURL) >>= href;
+ }
+
+ if (href.isEmpty())
+ return;
+
+ if (xPropSetInfo->hasPropertyByName(gsHyperLinkName)
+ && (!xPropState.is()
+ || PropertyState_DIRECT_VALUE == xPropState->getPropertyState(gsHyperLinkName)))
+ {
+ rPropSet->getPropertyValue(gsHyperLinkName) >>= name;
+ }
+
+ if (xPropSetInfo->hasPropertyByName(gsHyperLinkTarget)
+ && (!xPropState.is()
+ || PropertyState_DIRECT_VALUE == xPropState->getPropertyState(gsHyperLinkTarget)))
+ {
+ rPropSet->getPropertyValue(gsHyperLinkTarget) >>= targetFrame;
+ }
+
+ if (xPropSetInfo->hasPropertyByName(gsServerMap)
+ && (!xPropState.is()
+ || PropertyState_DIRECT_VALUE == xPropState->getPropertyState(gsServerMap)))
+ {
+ serverMap = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsServerMap));
+ }
+
+ if (xPropSetInfo->hasPropertyByName(gsUnvisitedCharStyleName)
+ && (!xPropState.is()
+ || PropertyState_DIRECT_VALUE
+ == xPropState->getPropertyState(gsUnvisitedCharStyleName)))
+ {
+ rPropSet->getPropertyValue(gsUnvisitedCharStyleName) >>= ustyleName;
+ }
+
+ if (xPropSetInfo->hasPropertyByName(gsVisitedCharStyleName)
+ && (!xPropState.is()
+ || PropertyState_DIRECT_VALUE
+ == xPropState->getPropertyState(gsVisitedCharStyleName)))
+ {
+ rPropSet->getPropertyValue(gsVisitedCharStyleName) >>= vstyleName;
+ }
+
+ static constexpr OUString sHyperLinkEvents(u"HyperLinkEvents"_ustr);
+ if (xPropSetInfo->hasPropertyByName(sHyperLinkEvents))
+ {
+ events.set(rPropSet->getPropertyValue(sHyperLinkEvents), uno::UNO_QUERY);
+ }
+ }
+
+ bool HyperlinkData::operator==(const HyperlinkData& rOther)
+ {
+ if (href != rOther.href || name != rOther.name || targetFrame != rOther.targetFrame
+ || ustyleName != rOther.ustyleName || vstyleName != rOther.vstyleName
+ || serverMap != rOther.serverMap)
+ return false;
+
+ if (events == rOther.events)
+ return true;
+ if (!events || !rOther.events)
+ return false;
+
+ const css::uno::Sequence<OUString> aNames = events->getElementNames();
+ if (aNames != rOther.events->getElementNames())
+ return false;
+ for (const auto& rName : aNames)
+ {
+ const css::uno::Any aAny = events->getByName(rName);
+ const css::uno::Any aOtherAny = rOther.events->getByName(rName);
+ if (aAny != aOtherAny)
+ return false;
+ }
+ return true;
+ }
+
+ bool HyperlinkData::addHyperlinkAttributes(SvXMLExport& rExport)
+ {
+ if (href.isEmpty())
+ {
+ // hyperlink without a URL does not make sense
+ OSL_ENSURE(false, "hyperlink without a URL --> no export to ODF");
+ return false;
+ }
+
+ rExport.AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE);
+ rExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, rExport.GetRelativeReference(href));
+
+ if (!name.isEmpty())
+ rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_NAME, name);
+
+ if (!targetFrame.isEmpty())
+ {
+ rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_TARGET_FRAME_NAME, targetFrame);
+ enum XMLTokenEnum eTok = targetFrame == "_blank" ? XML_NEW : XML_REPLACE;
+ rExport.AddAttribute(XML_NAMESPACE_XLINK, XML_SHOW, eTok);
+ }
+
+ if (serverMap)
+ rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_SERVER_MAP, XML_TRUE);
+
+ if (!ustyleName.isEmpty())
+ rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_STYLE_NAME,
+ rExport.EncodeStyleName(ustyleName));
+
+ if (!vstyleName.isEmpty())
+ rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_VISITED_STYLE_NAME,
+ rExport.EncodeStyleName(vstyleName));
+
+ return true;
+ }
+
+ void HyperlinkData::exportEvents(SvXMLExport& rExport)
+ {
+ // export events (if supported)
+ if (events)
+ rExport.GetEventExport().Export(events, false);
+ }
+}
+
+namespace xmloff
+{
+ class BoundFrameSets
+ {
+ public:
+ explicit BoundFrameSets(const Reference<XInterface>& rModel);
+ const BoundFrames* GetTexts() const
+ { return m_pTexts.get(); };
+ const BoundFrames* GetGraphics() const
+ { return m_pGraphics.get(); };
+ const BoundFrames* GetEmbeddeds() const
+ { return m_pEmbeddeds.get(); };
+ const BoundFrames* GetShapes() const
+ { return m_pShapes.get(); };
+ private:
+ std::unique_ptr<BoundFrames> m_pTexts;
+ std::unique_ptr<BoundFrames> m_pGraphics;
+ std::unique_ptr<BoundFrames> m_pEmbeddeds;
+ std::unique_ptr<BoundFrames> m_pShapes;
+ };
+}
+
+#ifdef DBG_UTIL
+static bool txtparae_bContainsIllegalCharacters = false;
+#endif
+
+// The following map shows which property values are required:
+
+// property auto style pass export
+
+// ParaStyleName if style exists always
+// ParaConditionalStyleName if style exists always
+// NumberingRules if style exists always
+// TextSection always always
+// ParaChapterNumberingLevel never always
+// NumberingIsNumber never always
+
+// The conclusion is that for auto styles the first three properties
+// should be queried using a multi property set if, and only if, an
+// auto style needs to be exported. TextSection should be queried by
+// an individual call to getPropertyvalue, because this seems to be
+// less expensive than querying the first three properties if they aren't
+// required.
+
+// For the export pass all properties can be queried using a multi property
+// set.
+
+static const char* aParagraphPropertyNamesAuto[] =
+{
+ "NumberingRules",
+ "ParaConditionalStyleName",
+ "ParaStyleName",
+ nullptr
+};
+
+namespace {
+
+enum eParagraphPropertyNamesEnumAuto
+{
+ NUMBERING_RULES_AUTO = 0,
+ PARA_CONDITIONAL_STYLE_NAME_AUTO = 1,
+ PARA_STYLE_NAME_AUTO = 2
+};
+
+}
+
+static const char* aParagraphPropertyNames[] =
+{
+ "NumberingIsNumber",
+ "NumberingStyleName",
+ "OutlineLevel",
+ "ParaConditionalStyleName",
+ "ParaStyleName",
+ "TextSection",
+ "OutlineContentVisible",
+ nullptr
+};
+
+namespace {
+
+enum eParagraphPropertyNamesEnum
+{
+ NUMBERING_IS_NUMBER = 0,
+ PARA_NUMBERING_STYLENAME = 1,
+ PARA_OUTLINE_LEVEL=2,
+ PARA_CONDITIONAL_STYLE_NAME = 3,
+ PARA_STYLE_NAME = 4,
+ TEXT_SECTION = 5,
+ PARA_OUTLINE_CONTENT_VISIBLE = 6
+};
+
+}
+
+void BoundFrames::Fill(const filter_t& rFilter)
+{
+ if(!m_xEnumAccess.is())
+ return;
+ const Reference< XEnumeration > xEnum = m_xEnumAccess->createEnumeration();
+ if(!xEnum.is())
+ return;
+ static constexpr OUStringLiteral our_sAnchorType(u"AnchorType");
+ static constexpr OUStringLiteral our_sAnchorFrame(u"AnchorFrame");
+ while(xEnum->hasMoreElements())
+ {
+ Reference<XPropertySet> xPropSet(xEnum->nextElement(), UNO_QUERY);
+ Reference<XTextContent> xTextContent(xPropSet, UNO_QUERY);
+ if(!xPropSet.is() || !xTextContent.is())
+ continue;
+ TextContentAnchorType eAnchor;
+ xPropSet->getPropertyValue(our_sAnchorType) >>= eAnchor;
+ if(TextContentAnchorType_AT_PAGE != eAnchor && TextContentAnchorType_AT_FRAME != eAnchor)
+ continue;
+ if(!rFilter(xTextContent))
+ continue;
+
+ TextContentSet::inserter_t pInserter = m_vPageBounds.getInserter();
+ if(TextContentAnchorType_AT_FRAME == eAnchor)
+ {
+ Reference<XTextFrame> xAnchorTxtFrame(
+ xPropSet->getPropertyValue(our_sAnchorFrame),
+ uno::UNO_QUERY);
+ pInserter = m_vFrameBoundsOf[xAnchorTxtFrame].getInserter();
+ }
+ *pInserter++ = xTextContent;
+ }
+}
+
+BoundFrameSets::BoundFrameSets(const Reference<XInterface>& rModel)
+ : m_pTexts(new BoundFrames())
+ , m_pGraphics(new BoundFrames())
+ , m_pEmbeddeds(new BoundFrames())
+ , m_pShapes(new BoundFrames())
+{
+ const Reference<XTextFramesSupplier> xTFS(rModel, UNO_QUERY);
+ const Reference<XTextGraphicObjectsSupplier> xGOS(rModel, UNO_QUERY);
+ const Reference<XTextEmbeddedObjectsSupplier> xEOS(rModel, UNO_QUERY);
+ const Reference<XDrawPageSupplier> xDPS(rModel, UNO_QUERY);
+ if(xTFS.is())
+ m_pTexts.reset(new BoundFrames(
+ Reference<XEnumerationAccess>(xTFS->getTextFrames(), UNO_QUERY),
+ &lcl_TextContentsUnfiltered));
+ if(xGOS.is())
+ m_pGraphics.reset(new BoundFrames(
+ Reference<XEnumerationAccess>(xGOS->getGraphicObjects(), UNO_QUERY),
+ &lcl_TextContentsUnfiltered));
+ if(xEOS.is())
+ m_pEmbeddeds.reset(new BoundFrames(
+ Reference<XEnumerationAccess>(xEOS->getEmbeddedObjects(), UNO_QUERY),
+ &lcl_TextContentsUnfiltered));
+ if(xDPS.is())
+ m_pShapes.reset(new BoundFrames(
+ Reference<XEnumerationAccess>(xDPS->getDrawPage(), UNO_QUERY),
+ &lcl_ShapeFilter));
+};
+
+void FieldParamExporter::Export()
+{
+ const Type aStringType = ::cppu::UnoType<OUString>::get();
+ const Type aBoolType = cppu::UnoType<sal_Bool>::get();
+ const Type aSeqType = cppu::UnoType<Sequence<OUString>>::get();
+ const Type aIntType = ::cppu::UnoType<sal_Int32>::get();
+ const Sequence<OUString> vParameters(m_xFieldParams->getElementNames());
+ for(const auto & rParameter : vParameters)
+ {
+ const Any aValue = m_xFieldParams->getByName(rParameter);
+ const Type& aValueType = aValue.getValueType();
+ if(aValueType == aStringType)
+ {
+ OUString sValue;
+ aValue >>= sValue;
+ ExportParameter(rParameter,sValue);
+
+ if ( rParameter == ODF_OLE_PARAM )
+ {
+ // Save the OLE object
+ Reference< embed::XStorage > xTargetStg = m_pExport->GetTargetStorage();
+ if (xTargetStg.is()) {
+ Reference< embed::XStorage > xDstStg = xTargetStg->openStorageElement(
+ "OLELinks", embed::ElementModes::WRITE );
+
+ if ( !xDstStg->hasByName( sValue ) ) {
+ Reference< XStorageBasedDocument > xStgDoc (
+ m_pExport->GetModel( ), UNO_QUERY );
+ Reference< embed::XStorage > xDocStg = xStgDoc->getDocumentStorage();
+ Reference< embed::XStorage > xOleStg = xDocStg->openStorageElement(
+ "OLELinks", embed::ElementModes::READ );
+
+ xOleStg->copyElementTo( sValue, xDstStg, sValue );
+ Reference< embed::XTransactedObject > xTransact( xDstStg, UNO_QUERY );
+ if ( xTransact.is( ) )
+ xTransact->commit( );
+ }
+ } else {
+ SAL_WARN("xmloff", "no target storage");
+ }
+ }
+ }
+ else if(aValueType == aBoolType)
+ {
+ bool bValue = false;
+ aValue >>= bValue;
+ ExportParameter(rParameter, OUString::boolean(bValue) );
+ }
+ else if(aValueType == aSeqType)
+ {
+ Sequence<OUString> vValue;
+ aValue >>= vValue;
+ for(const OUString & i : std::as_const(vValue))
+ {
+ ExportParameter(rParameter, i);
+ }
+ }
+ else if(aValueType == aIntType)
+ {
+ sal_Int32 nValue = 0;
+ aValue >>= nValue;
+ ExportParameter(rParameter, OUString::number(nValue));
+ }
+ }
+}
+
+void FieldParamExporter::ExportParameter(const OUString& sKey, const OUString& sValue)
+{
+ m_pExport->AddAttribute(XML_NAMESPACE_FIELD, XML_NAME, sKey);
+ m_pExport->AddAttribute(XML_NAMESPACE_FIELD, XML_VALUE, sValue);
+ m_pExport->StartElement(XML_NAMESPACE_FIELD, XML_PARAM, false);
+ m_pExport->EndElement(XML_NAMESPACE_FIELD, XML_PARAM, false);
+}
+
+void XMLTextParagraphExport::Add( XmlStyleFamily nFamily,
+ const Reference < XPropertySet > & rPropSet,
+ const std::span<const XMLPropertyState> aAddStates,
+ bool bDontSeek )
+{
+ rtl::Reference < SvXMLExportPropertyMapper > xPropMapper;
+ switch( nFamily )
+ {
+ case XmlStyleFamily::TEXT_PARAGRAPH:
+ xPropMapper = GetParaPropMapper();
+ break;
+ case XmlStyleFamily::TEXT_TEXT:
+ xPropMapper = GetTextPropMapper();
+ break;
+ case XmlStyleFamily::TEXT_FRAME:
+ xPropMapper = GetAutoFramePropMapper();
+ break;
+ case XmlStyleFamily::TEXT_SECTION:
+ xPropMapper = GetSectionPropMapper();
+ break;
+ case XmlStyleFamily::TEXT_RUBY:
+ xPropMapper = GetRubyPropMapper();
+ break;
+ default: break;
+ }
+ SAL_WARN_IF( !xPropMapper.is(), "xmloff", "There is the property mapper?" );
+
+ std::vector< XMLPropertyState > aPropStates =
+ xPropMapper->Filter(GetExport(), rPropSet);
+
+ aPropStates.insert( aPropStates.end(), aAddStates.begin(), aAddStates.end() );
+
+ if( aPropStates.empty() )
+ return;
+
+ Reference< XPropertySetInfo > xPropSetInfo(rPropSet->getPropertySetInfo());
+ OUString sParent, sCondParent;
+ switch( nFamily )
+ {
+ case XmlStyleFamily::TEXT_PARAGRAPH:
+ if( xPropSetInfo->hasPropertyByName( gsParaStyleName ) )
+ {
+ rPropSet->getPropertyValue( gsParaStyleName ) >>= sParent;
+ }
+ if( xPropSetInfo->hasPropertyByName( gsParaConditionalStyleName ) )
+ {
+ rPropSet->getPropertyValue( gsParaConditionalStyleName ) >>= sCondParent;
+ }
+ if( xPropSetInfo->hasPropertyByName( gsNumberingRules ) )
+ {
+ Reference < XIndexReplace > xNumRule(rPropSet->getPropertyValue( gsNumberingRules ), uno::UNO_QUERY);
+ if( xNumRule.is() && xNumRule->getCount() )
+ {
+ Reference < XNamed > xNamed( xNumRule, UNO_QUERY );
+ OUString sName;
+ if( xNamed.is() )
+ sName = xNamed->getName();
+ bool bAdd = sName.isEmpty();
+ if( !bAdd )
+ {
+ Reference < XPropertySet > xNumPropSet( xNumRule,
+ UNO_QUERY );
+ if( xNumPropSet.is() &&
+ xNumPropSet->getPropertySetInfo()
+ ->hasPropertyByName( "IsAutomatic" ) )
+ {
+ bAdd = *o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "IsAutomatic" ));
+ // Check on outline style (#i73361#)
+ if ( bAdd &&
+ xNumPropSet->getPropertySetInfo()
+ ->hasPropertyByName( "NumberingIsOutline" ) )
+ {
+ bAdd = !(*o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "NumberingIsOutline" )));
+ }
+ }
+ else
+ {
+ bAdd = true;
+ }
+ }
+ if( bAdd )
+ maListAutoPool.Add( xNumRule );
+ }
+ }
+ break;
+ case XmlStyleFamily::TEXT_TEXT:
+ {
+ // Get parent and remove hyperlinks (they aren't of interest)
+ rtl::Reference< XMLPropertySetMapper > xPM(xPropMapper->getPropertySetMapper());
+ sal_uInt16 nIgnoreProps = 0;
+ for( ::std::vector< XMLPropertyState >::iterator i(aPropStates.begin());
+ nIgnoreProps < 2 && i != aPropStates.end(); )
+ {
+ if( i->mnIndex == -1 )
+ {
+ ++i;
+ continue;
+ }
+
+ switch( xPM->GetEntryContextId(i->mnIndex) )
+ {
+ case CTF_CHAR_STYLE_NAME:
+ case CTF_HYPERLINK_URL:
+ i->mnIndex = -1;
+ nIgnoreProps++;
+ i = aPropStates.erase( i );
+ break;
+ default:
+ ++i;
+ break;
+ }
+ }
+ }
+ break;
+ case XmlStyleFamily::TEXT_FRAME:
+ if( xPropSetInfo->hasPropertyByName( gsFrameStyleName ) )
+ {
+ rPropSet->getPropertyValue( gsFrameStyleName ) >>= sParent;
+ }
+ break;
+ case XmlStyleFamily::TEXT_SECTION:
+ case XmlStyleFamily::TEXT_RUBY:
+ ; // section styles have no parents
+ break;
+ default: break;
+ }
+ if (aPropStates.size()) // could change after the previous check
+ {
+ GetAutoStylePool().Add( nFamily, sParent, std::vector(aPropStates), bDontSeek );
+ if( !sCondParent.isEmpty() && sParent != sCondParent )
+ GetAutoStylePool().Add( nFamily, sCondParent, std::move(aPropStates) );
+ }
+}
+
+static bool lcl_validPropState( const XMLPropertyState& rState )
+{
+ return rState.mnIndex != -1;
+}
+
+void XMLTextParagraphExport::Add( XmlStyleFamily nFamily,
+ MultiPropertySetHelper& rPropSetHelper,
+ const Reference < XPropertySet > & rPropSet)
+{
+ rtl::Reference < SvXMLExportPropertyMapper > xPropMapper;
+ switch( nFamily )
+ {
+ case XmlStyleFamily::TEXT_PARAGRAPH:
+ xPropMapper = GetParaPropMapper();
+ break;
+ default: break;
+ }
+ SAL_WARN_IF( !xPropMapper.is(), "xmloff", "There is the property mapper?" );
+
+ std::vector<XMLPropertyState> aPropStates(xPropMapper->Filter(GetExport(), rPropSet));
+
+ if( rPropSetHelper.hasProperty( NUMBERING_RULES_AUTO ) )
+ {
+ Reference < XIndexReplace > xNumRule(rPropSetHelper.getValue( NUMBERING_RULES_AUTO,
+ rPropSet, true ), uno::UNO_QUERY);
+ if( xNumRule.is() && xNumRule->getCount() )
+ {
+ Reference < XNamed > xNamed( xNumRule, UNO_QUERY );
+ OUString sName;
+ if( xNamed.is() )
+ sName = xNamed->getName();
+ bool bAdd = sName.isEmpty();
+ if( !bAdd )
+ {
+ Reference < XPropertySet > xNumPropSet( xNumRule,
+ UNO_QUERY );
+ if( xNumPropSet.is() &&
+ xNumPropSet->getPropertySetInfo()
+ ->hasPropertyByName( "IsAutomatic" ) )
+ {
+ bAdd = *o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "IsAutomatic" ));
+ // Check on outline style (#i73361#)
+ if ( bAdd &&
+ xNumPropSet->getPropertySetInfo()
+ ->hasPropertyByName( "NumberingIsOutline" ) )
+ {
+ bAdd = !(*o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "NumberingIsOutline" )));
+ }
+ }
+ else
+ {
+ bAdd = true;
+ }
+ }
+ if( bAdd )
+ maListAutoPool.Add( xNumRule );
+ }
+ }
+
+ if( aPropStates.empty() )
+ return;
+
+ OUString sParent, sCondParent;
+ switch( nFamily )
+ {
+ case XmlStyleFamily::TEXT_PARAGRAPH:
+ if( rPropSetHelper.hasProperty( PARA_STYLE_NAME_AUTO ) )
+ {
+ rPropSetHelper.getValue( PARA_STYLE_NAME_AUTO, rPropSet,
+ true ) >>= sParent;
+ }
+ if( rPropSetHelper.hasProperty( PARA_CONDITIONAL_STYLE_NAME_AUTO ) )
+ {
+ rPropSetHelper.getValue( PARA_CONDITIONAL_STYLE_NAME_AUTO,
+ rPropSet, true ) >>= sCondParent;
+ }
+
+ break;
+ default: break;
+ }
+
+ if( std::any_of( aPropStates.begin(), aPropStates.end(), lcl_validPropState ) )
+ {
+ GetAutoStylePool().Add( nFamily, sParent, std::vector(aPropStates) );
+ if( !sCondParent.isEmpty() && sParent != sCondParent )
+ GetAutoStylePool().Add( nFamily, sCondParent, std::move(aPropStates) );
+ }
+}
+
+OUString XMLTextParagraphExport::Find(
+ XmlStyleFamily nFamily,
+ const Reference < XPropertySet > & rPropSet,
+ const OUString& rParent,
+ const std::span<const XMLPropertyState> aAddStates) const
+{
+ OUString sName( rParent );
+ rtl::Reference < SvXMLExportPropertyMapper > xPropMapper;
+ switch( nFamily )
+ {
+ case XmlStyleFamily::TEXT_PARAGRAPH:
+ xPropMapper = GetParaPropMapper();
+ break;
+ case XmlStyleFamily::TEXT_FRAME:
+ xPropMapper = GetAutoFramePropMapper();
+ break;
+ case XmlStyleFamily::TEXT_SECTION:
+ xPropMapper = GetSectionPropMapper();
+ break;
+ case XmlStyleFamily::TEXT_RUBY:
+ xPropMapper = GetRubyPropMapper();
+ break;
+ default: break;
+ }
+ SAL_WARN_IF( !xPropMapper.is(), "xmloff", "There is the property mapper?" );
+ if( !xPropMapper.is() )
+ return sName;
+ std::vector<XMLPropertyState> aPropStates(xPropMapper->Filter(GetExport(), rPropSet));
+ aPropStates.insert( aPropStates.end(), aAddStates.begin(), aAddStates.end() );
+ if( std::any_of( aPropStates.begin(), aPropStates.end(), lcl_validPropState ) )
+ sName = GetAutoStylePool().Find( nFamily, sName, aPropStates );
+
+ return sName;
+}
+
+OUString XMLTextParagraphExport::FindTextStyle(
+ const Reference < XPropertySet > & rPropSet,
+ bool& rbHasCharStyle,
+ bool& rbHasAutoStyle,
+ const XMLPropertyState** ppAddStates ) const
+{
+ rtl::Reference < SvXMLExportPropertyMapper > xPropMapper(GetTextPropMapper());
+ std::vector<XMLPropertyState> aPropStates(xPropMapper->Filter(GetExport(), rPropSet));
+
+ // Get parent and remove hyperlinks (they aren't of interest)
+ OUString sName;
+ rbHasCharStyle = rbHasAutoStyle = false;
+ sal_uInt16 nIgnoreProps = 0;
+ rtl::Reference< XMLPropertySetMapper > xPM(xPropMapper->getPropertySetMapper());
+ ::std::vector< XMLPropertyState >::iterator aFirstDel = aPropStates.end();
+ ::std::vector< XMLPropertyState >::iterator aSecondDel = aPropStates.end();
+
+ for( ::std::vector< XMLPropertyState >::iterator
+ i = aPropStates.begin();
+ nIgnoreProps < 2 && i != aPropStates.end();
+ ++i )
+ {
+ if( i->mnIndex == -1 )
+ continue;
+
+ switch( xPM->GetEntryContextId(i->mnIndex) )
+ {
+ case CTF_CHAR_STYLE_NAME:
+ i->maValue >>= sName;
+ i->mnIndex = -1;
+ rbHasCharStyle = !sName.isEmpty();
+ if( nIgnoreProps )
+ aSecondDel = i;
+ else
+ aFirstDel = i;
+ nIgnoreProps++;
+ break;
+ case CTF_HYPERLINK_URL:
+ i->mnIndex = -1;
+ if( nIgnoreProps )
+ aSecondDel = i;
+ else
+ aFirstDel = i;
+ nIgnoreProps++;
+ break;
+ }
+ }
+ if( ppAddStates )
+ {
+ while( *ppAddStates )
+ {
+ aPropStates.push_back( **ppAddStates );
+ ppAddStates++;
+ }
+ }
+ if (aPropStates.size() - nIgnoreProps)
+ {
+ // erase the character style, otherwise the autostyle cannot be found!
+ // erase the hyperlink, otherwise the autostyle cannot be found!
+ if ( nIgnoreProps )
+ {
+ // If two elements of a vector have to be deleted,
+ // we should delete the second one first.
+ if( --nIgnoreProps )
+ aPropStates.erase( aSecondDel );
+ aPropStates.erase( aFirstDel );
+ }
+ sName = GetAutoStylePool().Find(
+ XmlStyleFamily::TEXT_TEXT,
+ OUString(), // AutoStyles should not have parents!
+ aPropStates );
+ rbHasAutoStyle = true;
+ }
+
+ return sName;
+}
+
+// adjustments to support lists independent from list style
+void XMLTextParagraphExport::exportListChange(
+ const XMLTextNumRuleInfo& rPrevInfo,
+ const XMLTextNumRuleInfo& rNextInfo )
+{
+ // end a list
+ if ( rPrevInfo.GetLevel() > 0 )
+ {
+ sal_uInt32 nListLevelsToBeClosed = 0; // unsigned larger type to safely multiply and compare
+ if ( !rNextInfo.BelongsToSameList( rPrevInfo ) ||
+ rNextInfo.GetLevel() <= 0 )
+ {
+ // close complete previous list
+ nListLevelsToBeClosed = rPrevInfo.GetLevel();
+ }
+ else if ( rPrevInfo.GetLevel() > rNextInfo.GetLevel() )
+ {
+ // close corresponding sub lists
+ nListLevelsToBeClosed = rPrevInfo.GetLevel() - rNextInfo.GetLevel();
+ }
+
+ if ( nListLevelsToBeClosed > 0 &&
+ maListElements.size() >= 2 * nListLevelsToBeClosed )
+ {
+ do {
+ for(size_t j = 0; j < 2; ++j)
+ {
+ OUString aElem(maListElements.back());
+ maListElements.pop_back();
+ GetExport().EndElement(aElem, true);
+ }
+
+ // remove closed list from list stack
+ mpTextListsHelper->PopListFromStack();
+
+ --nListLevelsToBeClosed;
+ } while ( nListLevelsToBeClosed > 0 );
+ }
+ }
+
+ // start a new list
+ if ( rNextInfo.GetLevel() > 0 )
+ {
+ bool bRootListToBeStarted = false;
+ sal_Int16 nListLevelsToBeOpened = 0;
+ if ( !rPrevInfo.BelongsToSameList( rNextInfo ) ||
+ rPrevInfo.GetLevel() <= 0 )
+ {
+ // new root list
+ bRootListToBeStarted = true;
+ nListLevelsToBeOpened = rNextInfo.GetLevel();
+ }
+ else if ( rNextInfo.GetLevel() > rPrevInfo.GetLevel() )
+ {
+ // open corresponding sub lists
+ nListLevelsToBeOpened = rNextInfo.GetLevel() - rPrevInfo.GetLevel();
+ }
+
+ if ( nListLevelsToBeOpened > 0 )
+ {
+ const OUString& sListStyleName( rNextInfo.GetNumRulesName() );
+ // Currently only the text documents support <ListId>.
+ // Thus, for other document types <sListId> is empty.
+ const OUString& sListId( rNextInfo.GetListId() );
+ bool bExportListStyle( true );
+ bool bRestartNumberingAtContinuedList( false );
+ sal_Int32 nRestartValueForContinuedList( -1 );
+ bool bContinueingPreviousSubList = !bRootListToBeStarted &&
+ rNextInfo.IsContinueingPreviousSubTree();
+ do {
+ GetExport().CheckAttrList();
+
+ if ( bRootListToBeStarted )
+ {
+ if ( !mpTextListsHelper->IsListProcessed( sListId ) )
+ {
+ if ( ExportListId() &&
+ !sListId.isEmpty() && !rNextInfo.IsListIdDefault() )
+ {
+ /* Property text:id at element <text:list> has to be
+ replaced by property xml:id (#i92221#)
+ */
+ GetExport().AddAttribute( XML_NAMESPACE_XML,
+ XML_ID,
+ sListId );
+ }
+ mpTextListsHelper->KeepListAsProcessed( sListId,
+ sListStyleName,
+ OUString() );
+ }
+ else
+ {
+ const OUString sNewListId(
+ mpTextListsHelper->GenerateNewListId() );
+ if ( ExportListId() &&
+ !sListId.isEmpty() && !rNextInfo.IsListIdDefault() )
+ {
+ /* Property text:id at element <text:list> has to be
+ replaced by property xml:id (#i92221#)
+ */
+ GetExport().AddAttribute( XML_NAMESPACE_XML,
+ XML_ID,
+ sNewListId );
+ }
+
+ const OUString sContinueListId =
+ mpTextListsHelper->GetLastContinuingListId( sListId );
+ // store that list with list id <sNewListId> is last list,
+ // which has continued list with list id <sListId>
+ mpTextListsHelper->StoreLastContinuingList( sListId,
+ sNewListId );
+ if ( sListStyleName ==
+ mpTextListsHelper->GetListStyleOfLastProcessedList() &&
+ // Inconsistent behavior regarding lists (#i92811#)
+ sContinueListId ==
+ mpTextListsHelper->GetLastProcessedListId() )
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT,
+ XML_CONTINUE_NUMBERING,
+ XML_TRUE );
+ }
+ else
+ {
+ if ( ExportListId() &&
+ !sListId.isEmpty() )
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT,
+ XML_CONTINUE_LIST,
+ sContinueListId );
+ }
+ }
+
+ if ( rNextInfo.IsRestart() &&
+ ( nListLevelsToBeOpened != 1 ||
+ !rNextInfo.HasStartValue() ) )
+ {
+ bRestartNumberingAtContinuedList = true;
+ nRestartValueForContinuedList =
+ rNextInfo.GetListLevelStartValue();
+ }
+
+ mpTextListsHelper->KeepListAsProcessed( sNewListId,
+ sListStyleName,
+ sContinueListId );
+ }
+
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
+ GetExport().EncodeStyleName( sListStyleName ) );
+ bExportListStyle = false;
+
+ bRootListToBeStarted = false;
+ }
+ else if ( bExportListStyle &&
+ !mpTextListsHelper->EqualsToTopListStyleOnStack( sListStyleName ) )
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
+ GetExport().EncodeStyleName( sListStyleName ) );
+ bExportListStyle = false;
+
+ }
+ else
+ {
+ // rhbz#746174: also export list restart for non root list
+ if (rNextInfo.IsRestart() && !rNextInfo.HasStartValue())
+ {
+ bRestartNumberingAtContinuedList = true;
+ nRestartValueForContinuedList =
+ rNextInfo.GetListLevelStartValue();
+ }
+ }
+
+ if ( bContinueingPreviousSubList )
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT,
+ XML_CONTINUE_NUMBERING, XML_TRUE );
+ bContinueingPreviousSubList = false;
+ }
+
+ enum XMLTokenEnum eLName = XML_LIST;
+
+ OUString aElem(GetExport().GetNamespaceMap().GetQNameByKey(
+ XML_NAMESPACE_TEXT,
+ GetXMLToken(eLName) ) );
+ GetExport().IgnorableWhitespace();
+ GetExport().StartElement(aElem, false);
+
+ maListElements.push_back(aElem);
+
+ mpTextListsHelper->PushListOnStack( sListId,
+ sListStyleName );
+
+ // <text:list-header> or <text:list-item>
+ GetExport().CheckAttrList();
+
+ /* Export start value at correct list item (#i97309#) */
+ if ( nListLevelsToBeOpened == 1 )
+ {
+ if ( rNextInfo.HasStartValue() )
+ {
+ OUString aTmp = OUString::number( static_cast<sal_Int32>(rNextInfo.GetStartValue()) );
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_START_VALUE,
+ aTmp );
+ }
+ else if (bRestartNumberingAtContinuedList)
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT,
+ XML_START_VALUE,
+ OUString::number(nRestartValueForContinuedList) );
+ bRestartNumberingAtContinuedList = false;
+ }
+ }
+
+ eLName = ( rNextInfo.IsNumbered() || nListLevelsToBeOpened > 1 )
+ ? XML_LIST_ITEM
+ : XML_LIST_HEADER;
+ aElem = GetExport().GetNamespaceMap().GetQNameByKey(
+ XML_NAMESPACE_TEXT,
+ GetXMLToken(eLName) );
+ GetExport().IgnorableWhitespace();
+ GetExport().StartElement(aElem, false);
+ maListElements.push_back(aElem);
+
+ // export of <text:number> element for last opened <text:list-item>, if requested
+ if ( GetExport().exportTextNumberElement() &&
+ eLName == XML_LIST_ITEM && nListLevelsToBeOpened == 1 && // last iteration --> last opened <text:list-item>
+ !rNextInfo.ListLabelString().isEmpty() )
+ {
+ const OUString aTextNumberElem =
+ GetExport().GetNamespaceMap().GetQNameByKey(
+ XML_NAMESPACE_TEXT,
+ GetXMLToken(XML_NUMBER) );
+ GetExport().IgnorableWhitespace();
+ GetExport().StartElement( aTextNumberElem, false );
+ GetExport().Characters( rNextInfo.ListLabelString() );
+ GetExport().EndElement( aTextNumberElem, true );
+ }
+ --nListLevelsToBeOpened;
+ } while ( nListLevelsToBeOpened > 0 );
+ }
+ }
+
+ bool bEndElement = false;
+
+ if ( rNextInfo.GetLevel() > 0 &&
+ rNextInfo.IsNumbered() &&
+ rPrevInfo.BelongsToSameList( rNextInfo ) &&
+ rPrevInfo.GetLevel() >= rNextInfo.GetLevel() )
+ {
+ assert(maListElements.size() >= 2 && "list elements missing");
+ bEndElement = maListElements.size() >= 2;
+ }
+
+ if (!bEndElement)
+ return;
+
+ // close previous list-item
+ GetExport().EndElement(maListElements.back(), true );
+ maListElements.pop_back();
+
+ // Only for sub lists (#i103745#)
+ if ( rNextInfo.IsRestart() && !rNextInfo.HasStartValue() &&
+ rNextInfo.GetLevel() != 1 )
+ {
+ // start new sub list respectively list on same list level
+ GetExport().EndElement(maListElements.back(), true );
+ GetExport().IgnorableWhitespace();
+ GetExport().StartElement(maListElements.back(), false);
+ }
+
+ // open new list-item
+ GetExport().CheckAttrList();
+ if( rNextInfo.HasStartValue() )
+ {
+ OUString aTmp = OUString::number( static_cast<sal_Int32>(rNextInfo.GetStartValue()) );
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_START_VALUE, aTmp );
+ }
+ // Handle restart without start value on list level 1 (#i103745#)
+ else if ( rNextInfo.IsRestart() && /*!rNextInfo.HasStartValue() &&*/
+ rNextInfo.GetLevel() == 1 )
+ {
+ OUString aTmp = OUString::number( static_cast<sal_Int32>(rNextInfo.GetListLevelStartValue()) );
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_START_VALUE, aTmp );
+ }
+ if ( ( GetExport().getExportFlags() & SvXMLExportFlags::OASIS ) &&
+ GetExport().getSaneDefaultVersion() >= SvtSaveOptions::ODFSVER_012)
+ {
+ const OUString& sListStyleName( rNextInfo.GetNumRulesName() );
+ if ( !mpTextListsHelper->EqualsToTopListStyleOnStack( sListStyleName ) )
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT,
+ XML_STYLE_OVERRIDE,
+ GetExport().EncodeStyleName( sListStyleName ) );
+ }
+ }
+ OUString aElem( GetExport().GetNamespaceMap().GetQNameByKey(
+ XML_NAMESPACE_TEXT,
+ GetXMLToken(XML_LIST_ITEM) ) );
+ GetExport().IgnorableWhitespace();
+ GetExport().StartElement(aElem, false );
+ maListElements.push_back(aElem);
+
+ // export of <text:number> element for <text:list-item>, if requested
+ if ( GetExport().exportTextNumberElement() &&
+ !rNextInfo.ListLabelString().isEmpty() )
+ {
+ const OUString aTextNumberElem =
+ GetExport().GetNamespaceMap().GetQNameByKey(
+ XML_NAMESPACE_TEXT,
+ GetXMLToken(XML_NUMBER) );
+ GetExport().IgnorableWhitespace();
+ GetExport().StartElement( aTextNumberElem, false );
+ GetExport().Characters( rNextInfo.ListLabelString() );
+ GetExport().EndElement( aTextNumberElem, true );
+ }
+
+}
+
+struct XMLTextParagraphExport::Impl
+{
+ typedef ::std::map<Reference<XFormField>, sal_Int32> FieldMarkMap_t;
+ FieldMarkMap_t m_FieldMarkMap;
+
+ explicit Impl() {}
+ sal_Int32 AddFieldMarkStart(Reference<XFormField> const& i_xFieldMark)
+ {
+ assert(m_FieldMarkMap.find(i_xFieldMark) == m_FieldMarkMap.end());
+ sal_Int32 const ret(m_FieldMarkMap.size());
+ m_FieldMarkMap.insert(::std::make_pair(i_xFieldMark, ret));
+ return ret;
+ }
+ sal_Int32 GetFieldMarkIndex(Reference<XFormField> const& i_xFieldMark)
+ {
+ FieldMarkMap_t::const_iterator const it(
+ m_FieldMarkMap.find(i_xFieldMark));
+ // rely on SwXFieldmark::CreateXFieldmark returning the same instance
+ // because the Reference in m_FieldMarkMap will keep it alive
+ assert(it != m_FieldMarkMap.end());
+ return it->second;
+ }
+};
+
+struct XMLTextParagraphExport::DocumentListNodes
+{
+ struct NodeData
+ {
+ sal_Int32 index; // see SwNode::GetIndex and SwNodeOffset
+ sal_uInt64 style_id; // actually a pointer to NumRule
+ OUString list_id;
+ };
+ std::vector<NodeData> docListNodes;
+ DocumentListNodes(const css::uno::Reference<css::frame::XModel>& xModel)
+ {
+ // Sequence of nodes, each of them represented by three-element sequence,
+ // corresponding to NodeData members
+ css::uno::Sequence<css::uno::Sequence<css::uno::Any>> nodes;
+ if (auto xPropSet = xModel.query<css::beans::XPropertySet>())
+ {
+ try
+ {
+ // See SwXTextDocument::getPropertyValue
+ xPropSet->getPropertyValue("ODFExport_ListNodes") >>= nodes;
+ }
+ catch (css::beans::UnknownPropertyException&)
+ {
+ // That's absolutely fine!
+ }
+ }
+
+ docListNodes.reserve(nodes.getLength());
+ for (const auto& node : nodes)
+ {
+ assert(node.getLength() == 3);
+ docListNodes.push_back({ node[0].get<sal_Int32>(), node[1].get<sal_uInt64>(),
+ node[2].get<OUString>() });
+ }
+
+ std::sort(docListNodes.begin(), docListNodes.end(),
+ [](const NodeData& lhs, const NodeData& rhs) { return lhs.index < rhs.index; });
+ }
+ bool ShouldSkipListId(const Reference<XTextContent>& xTextContent) const
+ {
+ if (docListNodes.empty())
+ return false;
+
+ if (auto xPropSet = xTextContent.query<css::beans::XPropertySet>())
+ {
+ sal_Int32 index = 0;
+ try
+ {
+ // See SwXParagraph::Impl::GetPropertyValues_Impl
+ xPropSet->getPropertyValue("ODFExport_NodeIndex") >>= index;
+ }
+ catch (css::beans::UnknownPropertyException&)
+ {
+ // That's absolutely fine!
+ return false;
+ }
+
+ auto it = std::lower_bound(docListNodes.begin(), docListNodes.end(), index,
+ [](const NodeData& lhs, sal_Int32 rhs)
+ { return lhs.index < rhs; });
+ if (it == docListNodes.end() || it->index != index)
+ return false;
+
+ // We need to write the id, when there will be continuation of the list either with
+ // a different list style, or after another list.
+
+ for (auto next = it + 1; next != docListNodes.end(); ++next)
+ {
+ if (it->list_id != next->list_id)
+ {
+ // List changed. We will have to refer to this id, only if there will
+ // appear a continuation of this list
+ return std::find_if(next + 1, docListNodes.end(),
+ [list_id = it->list_id](const NodeData& data)
+ { return data.list_id == list_id; })
+ == docListNodes.end();
+ }
+
+ if (it->style_id != next->style_id)
+ {
+ // Same list, new style -> this "next" will refer to the id, no skipping
+ return false;
+ }
+ if (it->index + 1 != next->index)
+ {
+ // we have a gap before the next node with the same list and style,
+ // with no other lists in between. There will be a continuation with a
+ // simple 'text:continue-numbering="true"'.
+ return true;
+ }
+ it = next; // walk through adjacent nodes of the same list
+ }
+ // all nodes were adjacent and of the same list and style -> no continuation, skip id
+ return true;
+ }
+
+ return false;
+ }
+};
+
+XMLTextParagraphExport::XMLTextParagraphExport(
+ SvXMLExport& rExp,
+ SvXMLAutoStylePoolP & rASP
+ ) :
+ XMLStyleExport( rExp, &rASP ),
+ m_xImpl(new Impl),
+ m_rAutoStylePool( rASP ),
+ m_pBoundFrameSets(new BoundFrameSets(GetExport().GetModel())),
+ maListAutoPool( GetExport() ),
+ m_bProgress( false ),
+ m_bBlock( false ),
+ m_bOpenRuby( false ),
+ mpTextListsHelper( nullptr ),
+ mbCollected(false),
+ m_aCharStyleNamesPropInfoCache( gsCharStyleNames )
+{
+ rtl::Reference < XMLPropertySetMapper > xPropMapper(new XMLTextPropertySetMapper( TextPropMap::PARA, true ));
+ m_xParaPropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
+ GetExport() );
+
+ OUString sFamily( GetXMLToken(XML_PARAGRAPH) );
+ OUString aPrefix(u'P');
+ m_rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_PARAGRAPH, sFamily,
+ m_xParaPropMapper, aPrefix );
+
+ xPropMapper = new XMLTextPropertySetMapper( TextPropMap::TEXT, true );
+ m_xTextPropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
+ GetExport() );
+ sFamily = GetXMLToken(XML_TEXT);
+ aPrefix = "T";
+ m_rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_TEXT, sFamily,
+ m_xTextPropMapper, aPrefix );
+
+ xPropMapper = new XMLTextPropertySetMapper( TextPropMap::AUTO_FRAME, true );
+ m_xAutoFramePropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
+ GetExport() );
+ sFamily = XML_STYLE_FAMILY_SD_GRAPHICS_NAME;
+ aPrefix = "fr";
+ m_rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_FRAME, sFamily,
+ m_xAutoFramePropMapper, aPrefix );
+
+ xPropMapper = new XMLTextPropertySetMapper( TextPropMap::SECTION, true );
+ m_xSectionPropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
+ GetExport() );
+ sFamily = GetXMLToken( XML_SECTION );
+ aPrefix = "Sect" ;
+ m_rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_SECTION, sFamily,
+ m_xSectionPropMapper, aPrefix );
+
+ xPropMapper = new XMLTextPropertySetMapper( TextPropMap::RUBY, true );
+ m_xRubyPropMapper = new SvXMLExportPropertyMapper( xPropMapper );
+ sFamily = GetXMLToken( XML_RUBY );
+ aPrefix = "Ru";
+ m_rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_RUBY, sFamily,
+ m_xRubyPropMapper, aPrefix );
+
+ xPropMapper = new XMLTextPropertySetMapper( TextPropMap::FRAME, true );
+ m_xFramePropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
+ GetExport() );
+
+ m_pSectionExport.reset( new XMLSectionExport( rExp, *this ) );
+ m_pIndexMarkExport.reset( new XMLIndexMarkExport( rExp ) );
+
+ if( ! IsBlockMode() &&
+ Reference<XRedlinesSupplier>( GetExport().GetModel(), UNO_QUERY ).is())
+ m_pRedlineExport.reset( new XMLRedlineExport( rExp ) );
+
+ // The text field helper needs a pre-constructed XMLPropertyState
+ // to export the combined characters field. We construct that
+ // here, because we need the text property mapper to do it.
+
+ // construct Any value, then find index
+ sal_Int32 nIndex = m_xTextPropMapper->getPropertySetMapper()->FindEntryIndex(
+ "", XML_NAMESPACE_STYLE,
+ GetXMLToken(XML_TEXT_COMBINE));
+ m_pFieldExport.reset( new XMLTextFieldExport( rExp, std::make_unique<XMLPropertyState>( nIndex, uno::Any(true) ) ) );
+ PushNewTextListsHelper();
+}
+
+XMLTextParagraphExport::~XMLTextParagraphExport()
+{
+ m_pRedlineExport.reset();
+ m_pIndexMarkExport.reset();
+ m_pSectionExport.reset();
+ m_pFieldExport.reset();
+#ifdef DBG_UTIL
+ txtparae_bContainsIllegalCharacters = false;
+#endif
+ PopTextListsHelper();
+ SAL_WARN_IF( !maTextListsHelperStack.empty(), "xmloff",
+ "misusage of text lists helper stack - it is not empty. Serious defect" );
+}
+
+SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateShapeExtPropMapper(
+ SvXMLExport& rExport )
+{
+ rtl::Reference < XMLPropertySetMapper > xPropMapper =
+ new XMLTextPropertySetMapper( TextPropMap::SHAPE, true );
+ return new XMLTextExportPropertySetMapper( xPropMapper, rExport );
+}
+
+SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateCharExtPropMapper(
+ SvXMLExport& rExport)
+{
+ XMLPropertySetMapper *pPropMapper =
+ new XMLTextPropertySetMapper( TextPropMap::TEXT, true );
+ return new XMLTextExportPropertySetMapper( pPropMapper, rExport );
+}
+
+SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateParaExtPropMapper(
+ SvXMLExport& rExport)
+{
+ XMLPropertySetMapper *pPropMapper =
+ new XMLTextPropertySetMapper( TextPropMap::SHAPE_PARA, true );
+ return new XMLTextExportPropertySetMapper( pPropMapper, rExport );
+}
+
+SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateParaDefaultExtPropMapper(
+ SvXMLExport& rExport)
+{
+ XMLPropertySetMapper *pPropMapper =
+ new XMLTextPropertySetMapper( TextPropMap::TEXT_ADDITIONAL_DEFAULTS, true );
+ return new XMLTextExportPropertySetMapper( pPropMapper, rExport );
+}
+
+void XMLTextParagraphExport::exportPageFrames( bool bIsProgress )
+{
+ const TextContentSet& rTexts = m_pBoundFrameSets->GetTexts()->GetPageBoundContents();
+ const TextContentSet& rGraphics = m_pBoundFrameSets->GetGraphics()->GetPageBoundContents();
+ const TextContentSet& rEmbeddeds = m_pBoundFrameSets->GetEmbeddeds()->GetPageBoundContents();
+ const TextContentSet& rShapes = m_pBoundFrameSets->GetShapes()->GetPageBoundContents();
+ for(TextContentSet::const_iterator_t it = rTexts.getBegin();
+ it != rTexts.getEnd();
+ ++it)
+ exportTextFrame(*it, false/*bAutoStyles*/, bIsProgress, true);
+ for(TextContentSet::const_iterator_t it = rGraphics.getBegin();
+ it != rGraphics.getEnd();
+ ++it)
+ exportTextGraphic(*it, false/*bAutoStyles*/);
+ for(TextContentSet::const_iterator_t it = rEmbeddeds.getBegin();
+ it != rEmbeddeds.getEnd();
+ ++it)
+ exportTextEmbedded(*it, false/*bAutoStyles*/);
+ for(TextContentSet::const_iterator_t it = rShapes.getBegin();
+ it != rShapes.getEnd();
+ ++it)
+ exportShape(*it, false/*bAutoStyles*/);
+}
+
+void XMLTextParagraphExport::exportFrameFrames(
+ bool bAutoStyles,
+ bool bIsProgress,
+ const Reference < XTextFrame >& rParentTxtFrame )
+{
+ const TextContentSet* const pTexts = m_pBoundFrameSets->GetTexts()->GetFrameBoundContents(rParentTxtFrame);
+ if(pTexts)
+ for(TextContentSet::const_iterator_t it = pTexts->getBegin();
+ it != pTexts->getEnd();
+ ++it)
+ exportTextFrame(*it, bAutoStyles, bIsProgress, true);
+ const TextContentSet* const pGraphics = m_pBoundFrameSets->GetGraphics()->GetFrameBoundContents(rParentTxtFrame);
+ if(pGraphics)
+ for(TextContentSet::const_iterator_t it = pGraphics->getBegin();
+ it != pGraphics->getEnd();
+ ++it)
+ exportTextGraphic(*it, bAutoStyles);
+ const TextContentSet* const pEmbeddeds = m_pBoundFrameSets->GetEmbeddeds()->GetFrameBoundContents(rParentTxtFrame);
+ if(pEmbeddeds)
+ for(TextContentSet::const_iterator_t it = pEmbeddeds->getBegin();
+ it != pEmbeddeds->getEnd();
+ ++it)
+ exportTextEmbedded(*it, bAutoStyles);
+ const TextContentSet* const pShapes = m_pBoundFrameSets->GetShapes()->GetFrameBoundContents(rParentTxtFrame);
+ if(pShapes)
+ for(TextContentSet::const_iterator_t it = pShapes->getBegin();
+ it != pShapes->getEnd();
+ ++it)
+ exportShape(*it, bAutoStyles);
+}
+
+// bookmarks, reference marks (and TOC marks) are the same except for the
+// element names. We use the same method for export and it an array with
+// the proper element names
+const enum XMLTokenEnum lcl_XmlReferenceElements[] = {
+ XML_REFERENCE_MARK, XML_REFERENCE_MARK_START, XML_REFERENCE_MARK_END };
+const enum XMLTokenEnum lcl_XmlBookmarkElements[] = {
+ XML_BOOKMARK, XML_BOOKMARK_START, XML_BOOKMARK_END };
+
+// This function replaces the text portion iteration during auto style
+// collection.
+void XMLTextParagraphExport::collectTextAutoStylesOptimized( bool bIsProgress )
+{
+ GetExport().GetShapeExport(); // make sure the graphics styles family is added
+
+ if (mbCollected)
+ return;
+
+ const bool bAutoStyles = true;
+ const bool bExportContent = false;
+
+ // Export AutoStyles:
+ Reference< XAutoStylesSupplier > xAutoStylesSupp( GetExport().GetModel(), UNO_QUERY );
+ if ( xAutoStylesSupp.is() )
+ {
+ Reference< XAutoStyles > xAutoStyleFamilies = xAutoStylesSupp->getAutoStyles();
+ const auto collectFamily = [this, &xAutoStyleFamilies](const OUString& sName,
+ XmlStyleFamily nFamily) {
+ Any aAny = xAutoStyleFamilies->getByName( sName );
+ Reference< XAutoStyleFamily > xAutoStyles = *o3tl::doAccess<Reference<XAutoStyleFamily>>(aAny);
+ Reference < XEnumeration > xAutoStylesEnum( xAutoStyles->createEnumeration() );
+
+ while ( xAutoStylesEnum->hasMoreElements() )
+ {
+ aAny = xAutoStylesEnum->nextElement();
+ Reference< XAutoStyle > xAutoStyle = *o3tl::doAccess<Reference<XAutoStyle>>(aAny);
+ Reference < XPropertySet > xPSet( xAutoStyle, uno::UNO_QUERY );
+ Add( nFamily, xPSet, {}, true );
+ }
+ };
+ collectFamily("CharacterStyles", XmlStyleFamily::TEXT_TEXT);
+ collectFamily("RubyStyles", XmlStyleFamily::TEXT_RUBY);
+ collectFamily("ParagraphStyles", XmlStyleFamily::TEXT_PARAGRAPH);
+ }
+
+ // Export Field AutoStyles:
+ Reference< XTextFieldsSupplier > xTextFieldsSupp( GetExport().GetModel(), UNO_QUERY );
+ if ( xTextFieldsSupp.is() )
+ {
+ Reference< XEnumerationAccess > xTextFields = xTextFieldsSupp->getTextFields();
+ Reference < XEnumeration > xTextFieldsEnum( xTextFields->createEnumeration() );
+
+ while ( xTextFieldsEnum->hasMoreElements() )
+ {
+ Any aAny = xTextFieldsEnum->nextElement();
+ Reference< XTextField > xTextField = *o3tl::doAccess<Reference<XTextField>>(aAny);
+ exportTextField( xTextField, bAutoStyles, bIsProgress,
+ !xAutoStylesSupp.is(), nullptr );
+ try
+ {
+ Reference < XPropertySet > xSet( xTextField, UNO_QUERY );
+ Reference < XText > xText;
+ Any a = xSet->getPropertyValue("TextRange");
+ a >>= xText;
+ if ( xText.is() )
+ {
+ exportText( xText, true, bIsProgress, bExportContent );
+ GetExport().GetTextParagraphExport()
+ ->collectTextAutoStyles( xText );
+ }
+ }
+ catch (Exception&)
+ {
+ }
+ }
+ }
+
+ // Export text frames:
+ Reference<XEnumeration> xTextFramesEnum = m_pBoundFrameSets->GetTexts()->createEnumeration();
+ if(xTextFramesEnum.is())
+ while(xTextFramesEnum->hasMoreElements())
+ {
+ Reference<XTextContent> xTxtCntnt(xTextFramesEnum->nextElement(), UNO_QUERY);
+ if(xTxtCntnt.is())
+ exportTextFrame(xTxtCntnt, bAutoStyles, bIsProgress, bExportContent);
+ }
+
+ // Export graphic objects:
+ Reference<XEnumeration> xGraphicsEnum = m_pBoundFrameSets->GetGraphics()->createEnumeration();
+ if(xGraphicsEnum.is())
+ while(xGraphicsEnum->hasMoreElements())
+ {
+ Reference<XTextContent> xTxtCntnt(xGraphicsEnum->nextElement(), UNO_QUERY);
+ if(xTxtCntnt.is())
+ exportTextGraphic(xTxtCntnt, true);
+ }
+
+ // Export embedded objects:
+ Reference<XEnumeration> xEmbeddedsEnum = m_pBoundFrameSets->GetEmbeddeds()->createEnumeration();
+ if(xEmbeddedsEnum.is())
+ while(xEmbeddedsEnum->hasMoreElements())
+ {
+ Reference<XTextContent> xTxtCntnt(xEmbeddedsEnum->nextElement(), UNO_QUERY);
+ if(xTxtCntnt.is())
+ exportTextEmbedded(xTxtCntnt, true);
+ }
+
+ // Export shapes:
+ Reference<XEnumeration> xShapesEnum = m_pBoundFrameSets->GetShapes()->createEnumeration();
+ if(xShapesEnum.is())
+ while(xShapesEnum->hasMoreElements())
+ {
+ Reference<XTextContent> xTxtCntnt(xShapesEnum->nextElement(), UNO_QUERY);
+ if(xTxtCntnt.is())
+ {
+ Reference<XServiceInfo> xServiceInfo(xTxtCntnt, UNO_QUERY);
+ if( xServiceInfo->supportsService(gsShapeService))
+ exportShape(xTxtCntnt, true);
+ }
+ }
+
+ sal_Int32 nCount;
+ // AutoStyles for sections
+ Reference< XTextSectionsSupplier > xSectionsSupp( GetExport().GetModel(), UNO_QUERY );
+ if ( xSectionsSupp.is() )
+ {
+ Reference< XIndexAccess > xSections( xSectionsSupp->getTextSections(), UNO_QUERY );
+ if ( xSections.is() )
+ {
+ nCount = xSections->getCount();
+ for( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ Any aAny = xSections->getByIndex( i );
+ Reference< XTextSection > xSection = *o3tl::doAccess<Reference<XTextSection>>(aAny);
+ Reference < XPropertySet > xPSet( xSection, uno::UNO_QUERY );
+ Add( XmlStyleFamily::TEXT_SECTION, xPSet );
+ }
+ }
+ }
+
+ // AutoStyles for tables (Note: suppress autostyle collection for paragraphs in exportTable)
+ Reference< XTextTablesSupplier > xTablesSupp( GetExport().GetModel(), UNO_QUERY );
+ if ( xTablesSupp.is() )
+ {
+ Reference< XIndexAccess > xTables( xTablesSupp->getTextTables(), UNO_QUERY );
+ if ( xTables.is() )
+ {
+ nCount = xTables->getCount();
+ for( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ Any aAny = xTables->getByIndex( i );
+ Reference< XTextTable > xTable = *o3tl::doAccess<Reference<XTextTable>>(aAny);
+ exportTable( xTable, true, true );
+ }
+ }
+ }
+
+ Reference< XNumberingRulesSupplier > xNumberingRulesSupp( GetExport().GetModel(), UNO_QUERY );
+ if ( xNumberingRulesSupp.is() )
+ {
+ Reference< XIndexAccess > xNumberingRules = xNumberingRulesSupp->getNumberingRules();
+ nCount = xNumberingRules->getCount();
+ // Custom outline assignment lost after re-importing sxw (#i73361#)
+ for( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ Reference< XIndexReplace > xNumRule( xNumberingRules->getByIndex( i ), UNO_QUERY );
+ if( xNumRule.is() && xNumRule->getCount() )
+ {
+ Reference < XNamed > xNamed( xNumRule, UNO_QUERY );
+ OUString sName;
+ if( xNamed.is() )
+ sName = xNamed->getName();
+ bool bAdd = sName.isEmpty();
+ if( !bAdd )
+ {
+ Reference < XPropertySet > xNumPropSet( xNumRule,
+ UNO_QUERY );
+ if( xNumPropSet.is() &&
+ xNumPropSet->getPropertySetInfo()
+ ->hasPropertyByName( "IsAutomatic" ) )
+ {
+ bAdd = *o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "IsAutomatic" ));
+ // Check on outline style (#i73361#)
+ if ( bAdd &&
+ xNumPropSet->getPropertySetInfo()
+ ->hasPropertyByName( "NumberingIsOutline" ) )
+ {
+ bAdd = !(*o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "NumberingIsOutline" )));
+ }
+ }
+ else
+ {
+ bAdd = true;
+ }
+ }
+ if( bAdd )
+ maListAutoPool.Add( xNumRule );
+ }
+ }
+ }
+ mbCollected = true;
+}
+
+void XMLTextParagraphExport::exportText(
+ const Reference < XText > & rText,
+ bool bAutoStyles,
+ bool bIsProgress,
+ bool bExportParagraph,
+ TextPNS eExtensionNS)
+{
+ if( bAutoStyles )
+ GetExport().GetShapeExport(); // make sure the graphics styles family
+ // is added
+ Reference < XEnumerationAccess > xEA( rText, UNO_QUERY );
+ if( ! xEA.is() )
+ return;
+
+ Reference < XEnumeration > xParaEnum(xEA->createEnumeration());
+ Reference < XPropertySet > xPropertySet( rText, UNO_QUERY );
+ Reference < XTextSection > xBaseSection;
+
+ // #97718# footnotes don't supply paragraph enumerations in some cases
+ // This is always a bug, but at least we don't want to crash.
+ SAL_WARN_IF( !xParaEnum.is(), "xmloff", "We need a paragraph enumeration" );
+ if( ! xParaEnum.is() )
+ return;
+
+ if (xPropertySet.is())
+ {
+ Reference < XPropertySetInfo > xInfo ( xPropertySet->getPropertySetInfo() );
+
+ if( xInfo.is() )
+ {
+ if (xInfo->hasPropertyByName( gsTextSection ))
+ {
+ xPropertySet->getPropertyValue(gsTextSection) >>= xBaseSection ;
+ }
+ }
+ }
+
+ // #96530# Export redlines at start & end of XText before & after
+ // exporting the text content enumeration
+ if( !bAutoStyles && (m_pRedlineExport != nullptr) )
+ m_pRedlineExport->ExportStartOrEndRedline( xPropertySet, true );
+ exportTextContentEnumeration( xParaEnum, bAutoStyles, xBaseSection,
+ bIsProgress, bExportParagraph, nullptr, eExtensionNS );
+ if( !bAutoStyles && (m_pRedlineExport != nullptr) )
+ m_pRedlineExport->ExportStartOrEndRedline( xPropertySet, false );
+}
+
+void XMLTextParagraphExport::exportText(
+ const Reference < XText > & rText,
+ const Reference < XTextSection > & rBaseSection,
+ bool bAutoStyles,
+ bool bIsProgress,
+ bool bExportParagraph)
+{
+ if( bAutoStyles )
+ GetExport().GetShapeExport(); // make sure the graphics styles family
+ // is added
+ Reference < XEnumerationAccess > xEA( rText, UNO_QUERY );
+ Reference < XEnumeration > xParaEnum(xEA->createEnumeration());
+
+ // #98165# don't continue without a paragraph enumeration
+ if( ! xParaEnum.is() )
+ return;
+
+ // #96530# Export redlines at start & end of XText before & after
+ // exporting the text content enumeration
+ Reference<XPropertySet> xPropertySet;
+ if( !bAutoStyles && (m_pRedlineExport != nullptr) )
+ {
+ xPropertySet.set(rText, uno::UNO_QUERY );
+ m_pRedlineExport->ExportStartOrEndRedline( xPropertySet, true );
+ }
+ exportTextContentEnumeration( xParaEnum, bAutoStyles, rBaseSection,
+ bIsProgress, bExportParagraph );
+ if( !bAutoStyles && (m_pRedlineExport != nullptr) )
+ m_pRedlineExport->ExportStartOrEndRedline( xPropertySet, false );
+}
+
+bool XMLTextParagraphExport::ExportListId() const
+{
+ return (GetExport().getExportFlags() & SvXMLExportFlags::OASIS)
+ && GetExport().getSaneDefaultVersion() >= SvtSaveOptions::ODFSVER_012;
+}
+
+bool XMLTextParagraphExport::ShouldSkipListId(const Reference<XTextContent>& xTextContent)
+{
+ if (!mpDocumentListNodes)
+ {
+ if (ExportListId())
+ mpDocumentListNodes.reset(new DocumentListNodes(GetExport().GetModel()));
+ else
+ mpDocumentListNodes.reset(new DocumentListNodes({}));
+ }
+
+ return mpDocumentListNodes->ShouldSkipListId(xTextContent);
+}
+
+void XMLTextParagraphExport::exportTextContentEnumeration(
+ const Reference < XEnumeration > & rContEnum,
+ bool bAutoStyles,
+ const Reference < XTextSection > & rBaseSection,
+ bool bIsProgress,
+ bool bExportParagraph,
+ const Reference < XPropertySet > *pRangePropSet,
+ TextPNS eExtensionNS )
+{
+ SAL_WARN_IF( !rContEnum.is(), "xmloff", "No enumeration to export!" );
+ bool bHasMoreElements = rContEnum->hasMoreElements();
+ if( !bHasMoreElements )
+ return;
+
+ XMLTextNumRuleInfo aPrevNumInfo;
+ XMLTextNumRuleInfo aNextNumInfo;
+
+ bool bHasContent = false;
+ Reference<XTextSection> xCurrentTextSection(rBaseSection);
+
+ MultiPropertySetHelper aPropSetHelper(
+ bAutoStyles ? aParagraphPropertyNamesAuto :
+ aParagraphPropertyNames );
+
+ bool bHoldElement = false;
+ Reference < XTextContent > xTxtCntnt;
+ while( bHoldElement || bHasMoreElements )
+ {
+ if (bHoldElement)
+ {
+ bHoldElement = false;
+ }
+ else
+ {
+ xTxtCntnt.set(rContEnum->nextElement(), uno::UNO_QUERY);
+
+ aPropSetHelper.resetValues();
+
+ }
+
+ Reference<XServiceInfo> xServiceInfo( xTxtCntnt, UNO_QUERY );
+ if( xServiceInfo->supportsService( gsParagraphService ) )
+ {
+ if( bAutoStyles )
+ {
+ exportListAndSectionChange( xCurrentTextSection, xTxtCntnt,
+ aPrevNumInfo, aNextNumInfo,
+ bAutoStyles );
+ }
+ else
+ {
+ /* Pass list auto style pool to <XMLTextNumRuleInfo> instance
+ Pass info about request to export <text:number> element
+ to <XMLTextNumRuleInfo> instance (#i69627#)
+ */
+ aNextNumInfo.Set( xTxtCntnt,
+ GetExport().writeOutlineStyleAsNormalListStyle(),
+ GetListAutoStylePool(),
+ GetExport().exportTextNumberElement(),
+ ShouldSkipListId(xTxtCntnt) );
+
+ exportListAndSectionChange( xCurrentTextSection, aPropSetHelper,
+ TEXT_SECTION, xTxtCntnt,
+ aPrevNumInfo, aNextNumInfo,
+ bAutoStyles );
+ }
+
+ // if we found a mute section: skip all section content
+ if (m_pSectionExport->IsMuteSection(xCurrentTextSection))
+ {
+ // Make sure headings are exported anyway.
+ if( !bAutoStyles )
+ m_pSectionExport->ExportMasterDocHeadingDummies();
+
+ while (rContEnum->hasMoreElements() &&
+ XMLSectionExport::IsInSection( xCurrentTextSection,
+ xTxtCntnt, true ))
+ {
+ xTxtCntnt.set(rContEnum->nextElement(), uno::UNO_QUERY);
+ aPropSetHelper.resetValues();
+ aNextNumInfo.Reset();
+ }
+ // the first non-mute element still needs to be processed
+ bHoldElement =
+ ! XMLSectionExport::IsInSection( xCurrentTextSection,
+ xTxtCntnt, false );
+ }
+ else
+ exportParagraph( xTxtCntnt, bAutoStyles, bIsProgress,
+ bExportParagraph, aPropSetHelper, eExtensionNS );
+ bHasContent = true;
+ }
+ else if( xServiceInfo->supportsService( gsTableService ) )
+ {
+ if( !bAutoStyles )
+ {
+ aNextNumInfo.Reset();
+ }
+
+ exportListAndSectionChange( xCurrentTextSection, xTxtCntnt,
+ aPrevNumInfo, aNextNumInfo,
+ bAutoStyles );
+
+ if (! m_pSectionExport->IsMuteSection(xCurrentTextSection))
+ {
+ // export start + end redlines (for wholly redlined tables)
+ if ((! bAutoStyles) && (nullptr != m_pRedlineExport))
+ m_pRedlineExport->ExportStartOrEndRedline(xTxtCntnt, true);
+
+ exportTable( xTxtCntnt, bAutoStyles, bIsProgress );
+
+ if ((! bAutoStyles) && (nullptr != m_pRedlineExport))
+ m_pRedlineExport->ExportStartOrEndRedline(xTxtCntnt, false);
+ }
+ else if( !bAutoStyles )
+ {
+ // Make sure headings are exported anyway.
+ m_pSectionExport->ExportMasterDocHeadingDummies();
+ }
+
+ bHasContent = true;
+ }
+ else if( xServiceInfo->supportsService( gsTextFrameService ) )
+ {
+ exportTextFrame( xTxtCntnt, bAutoStyles, bIsProgress, true, pRangePropSet );
+ }
+ else if( xServiceInfo->supportsService( gsTextGraphicService ) )
+ {
+ exportTextGraphic( xTxtCntnt, bAutoStyles, pRangePropSet );
+ }
+ else if( xServiceInfo->supportsService( gsTextEmbeddedService ) )
+ {
+ exportTextEmbedded( xTxtCntnt, bAutoStyles, pRangePropSet );
+ }
+ else if( xServiceInfo->supportsService( gsShapeService ) )
+ {
+ exportShape( xTxtCntnt, bAutoStyles, pRangePropSet );
+ }
+ else
+ {
+ SAL_WARN_IF( xTxtCntnt.is(), "xmloff", "unknown text content" );
+ }
+
+ if( !bAutoStyles )
+ {
+ aPrevNumInfo = aNextNumInfo;
+ }
+
+ bHasMoreElements = rContEnum->hasMoreElements();
+ }
+
+ if( bHasContent && !bAutoStyles )
+ {
+ aNextNumInfo.Reset();
+
+ // close open lists and sections; no new styles
+ exportListAndSectionChange( xCurrentTextSection, rBaseSection,
+ aPrevNumInfo, aNextNumInfo,
+ bAutoStyles );
+ }
+}
+
+void XMLTextParagraphExport::exportParagraph(
+ const Reference < XTextContent > & rTextContent,
+ bool bAutoStyles, bool bIsProgress, bool bExportParagraph,
+ MultiPropertySetHelper& rPropSetHelper, TextPNS eExtensionNS)
+{
+ sal_Int16 nOutlineLevel = -1;
+
+ if( bIsProgress )
+ {
+ ProgressBarHelper *pProgress = GetExport().GetProgressBarHelper();
+ pProgress->SetValue( pProgress->GetValue()+1 );
+ }
+
+ // get property set or multi property set and initialize helper
+ Reference<XMultiPropertySet> xMultiPropSet( rTextContent, UNO_QUERY );
+ Reference<XPropertySet> xPropSet( rTextContent, UNO_QUERY );
+
+ // check for supported properties
+ if( !rPropSetHelper.checkedProperties() )
+ rPropSetHelper.hasProperties( xPropSet->getPropertySetInfo() );
+
+// if( xMultiPropSet.is() )
+// rPropSetHelper.getValues( xMultiPropSet );
+// else
+// rPropSetHelper.getValues( xPropSet );
+
+ if( bExportParagraph )
+ {
+ if( bAutoStyles )
+ {
+ Add( XmlStyleFamily::TEXT_PARAGRAPH, rPropSetHelper, xPropSet );
+ }
+ else
+ {
+ // xml:id for RDF metadata
+ GetExport().AddAttributeXmlId(rTextContent);
+ GetExport().AddAttributesRDFa(rTextContent);
+
+ OUString sStyle;
+ if( rPropSetHelper.hasProperty( PARA_STYLE_NAME ) )
+ {
+ if( xMultiPropSet.is() )
+ rPropSetHelper.getValue( PARA_STYLE_NAME,
+ xMultiPropSet ) >>= sStyle;
+ else
+ rPropSetHelper.getValue( PARA_STYLE_NAME,
+ xPropSet ) >>= sStyle;
+ }
+
+ if( rTextContent.is() )
+ {
+ const OUString& rIdentifier = GetExport().getInterfaceToIdentifierMapper().getIdentifier( rTextContent );
+ if( !rIdentifier.isEmpty() )
+ {
+ // FIXME: this is just temporary until EditEngine
+ // paragraphs implement XMetadatable.
+ // then that must be used and not the mapper, because
+ // when both can be used we get two xml:id!
+ uno::Reference<rdf::XMetadatable> const xMeta(rTextContent,
+ uno::UNO_QUERY);
+ OSL_ENSURE(!xMeta.is(), "paragraph that implements "
+ "XMetadatable used in interfaceToIdentifierMapper?");
+ GetExport().AddAttributeIdLegacy(XML_NAMESPACE_TEXT,
+ rIdentifier);
+ }
+ }
+
+ OUString sAutoStyle = Find( XmlStyleFamily::TEXT_PARAGRAPH, xPropSet, sStyle );
+ if ( sAutoStyle.isEmpty() )
+ sAutoStyle = sStyle;
+ if( !sAutoStyle.isEmpty() )
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
+ GetExport().EncodeStyleName( sAutoStyle ) );
+
+ if( rPropSetHelper.hasProperty( PARA_CONDITIONAL_STYLE_NAME ) )
+ {
+ OUString sCondStyle;
+ if( xMultiPropSet.is() )
+ rPropSetHelper.getValue( PARA_CONDITIONAL_STYLE_NAME,
+ xMultiPropSet ) >>= sCondStyle;
+ else
+ rPropSetHelper.getValue( PARA_CONDITIONAL_STYLE_NAME,
+ xPropSet ) >>= sCondStyle;
+ if( sCondStyle != sStyle )
+ {
+ sCondStyle = Find( XmlStyleFamily::TEXT_PARAGRAPH, xPropSet,
+ sCondStyle );
+ if( !sCondStyle.isEmpty() )
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT,
+ XML_COND_STYLE_NAME,
+ GetExport().EncodeStyleName( sCondStyle ) );
+ }
+ }
+
+ if( rPropSetHelper.hasProperty( PARA_OUTLINE_LEVEL ) )
+ {
+ if( xMultiPropSet.is() )
+ rPropSetHelper.getValue( PARA_OUTLINE_LEVEL,
+ xMultiPropSet ) >>= nOutlineLevel;
+ else
+ rPropSetHelper.getValue( PARA_OUTLINE_LEVEL,
+ xPropSet ) >>= nOutlineLevel;
+
+ if( 0 < nOutlineLevel )
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT,
+ XML_OUTLINE_LEVEL,
+ OUString::number( sal_Int32( nOutlineLevel) ) );
+
+ if ( rPropSetHelper.hasProperty( PARA_OUTLINE_CONTENT_VISIBLE ) )
+ {
+ uno::Sequence<beans::PropertyValue> propList;
+ bool bIsOutlineContentVisible = true;
+ if( xMultiPropSet.is() )
+ rPropSetHelper.getValue(
+ PARA_OUTLINE_CONTENT_VISIBLE, xMultiPropSet ) >>= propList;
+ else
+ rPropSetHelper.getValue(
+ PARA_OUTLINE_CONTENT_VISIBLE, xPropSet ) >>= propList;
+ for (const auto& rProp : std::as_const(propList))
+ {
+ OUString propName = rProp.Name;
+ if (propName == "OutlineContentVisibleAttr")
+ {
+ rProp.Value >>= bIsOutlineContentVisible;
+ break;
+ }
+ }
+ if (!bIsOutlineContentVisible)
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_LO_EXT,
+ XML_OUTLINE_CONTENT_VISIBLE,
+ XML_FALSE);
+ }
+ }
+
+ if( rPropSetHelper.hasProperty( NUMBERING_IS_NUMBER ) )
+ {
+ bool bIsNumber = false;
+ if( xMultiPropSet.is() )
+ rPropSetHelper.getValue(
+ NUMBERING_IS_NUMBER, xMultiPropSet ) >>= bIsNumber;
+ else
+ rPropSetHelper.getValue(
+ NUMBERING_IS_NUMBER, xPropSet ) >>= bIsNumber;
+
+ OUString sListStyleName;
+ if( xMultiPropSet.is() )
+ rPropSetHelper.getValue(
+ PARA_NUMBERING_STYLENAME, xMultiPropSet ) >>= sListStyleName;
+ else
+ rPropSetHelper.getValue(
+ PARA_NUMBERING_STYLENAME, xPropSet ) >>= sListStyleName;
+
+ bool bAssignedtoOutlineStyle = false;
+ {
+ Reference< XChapterNumberingSupplier > xCNSupplier( GetExport().GetModel(), UNO_QUERY );
+
+ if (xCNSupplier.is())
+ {
+ Reference< XIndexReplace > xNumRule ( xCNSupplier->getChapterNumberingRules() );
+ SAL_WARN_IF( !xNumRule.is(), "xmloff", "no chapter numbering rules" );
+
+ if (xNumRule.is())
+ {
+ Reference< XPropertySet > xNumRulePropSet( xNumRule, UNO_QUERY );
+ OUString sOutlineName;
+ xNumRulePropSet->getPropertyValue(
+ "Name" ) >>= sOutlineName;
+ bAssignedtoOutlineStyle = ( sListStyleName == sOutlineName );
+ }
+ }
+ }
+
+ if( ! bIsNumber && bAssignedtoOutlineStyle )
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT,
+ XML_IS_LIST_HEADER,
+ XML_TRUE );
+ }
+
+ {
+ bool bIsRestartNumbering = false;
+
+ Reference< XPropertySetInfo >
+ xPropSetInfo(xMultiPropSet.is() ?
+ xMultiPropSet->getPropertySetInfo():
+ xPropSet->getPropertySetInfo());
+
+ if (xPropSetInfo->
+ hasPropertyByName("ParaIsNumberingRestart"))
+ {
+ xPropSet->getPropertyValue("ParaIsNumberingRestart")
+ >>= bIsRestartNumbering;
+ }
+
+ if (bIsRestartNumbering)
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT,
+ XML_RESTART_NUMBERING,
+ XML_TRUE);
+
+ if (xPropSetInfo->
+ hasPropertyByName("NumberingStartValue"))
+ {
+ sal_Int32 nStartValue = 0;
+
+ xPropSet->getPropertyValue("NumberingStartValue")
+ >>= nStartValue;
+
+ GetExport().
+ AddAttribute(XML_NAMESPACE_TEXT,
+ XML_START_VALUE,
+ OUString::number(nStartValue));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
+ {
+ try
+ {
+ // ParaMarkerAutoStyleSpan is a hidden property, just to pass the autostyle here
+ // See SwXParagraph::Impl::GetPropertyValues_Impl
+ css::uno::Any aVal = xPropSet->getPropertyValue("ParaMarkerAutoStyleSpan");
+ if (auto xFakeSpan = aVal.query<css::beans::XPropertySet>())
+ {
+ if (bAutoStyles)
+ {
+ Add(XmlStyleFamily::TEXT_TEXT, xFakeSpan);
+ }
+ else
+ {
+ bool bIsUICharStyle, bHasAutoStyle;
+ OUString sStyle = FindTextStyle(xFakeSpan, bIsUICharStyle, bHasAutoStyle);
+ if (!sStyle.isEmpty())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_MARKER_STYLE_NAME,
+ sStyle);
+ }
+ }
+ }
+ }
+ catch (const css::beans::UnknownPropertyException&)
+ {
+ // No problem
+ }
+ }
+ }
+
+ Reference < XEnumerationAccess > xEA( rTextContent, UNO_QUERY );
+ Reference < XEnumeration > xTextEnum = xEA->createEnumeration();
+ const bool bHasPortions = xTextEnum.is();
+
+ Reference < XEnumeration> xContentEnum;
+ Reference < XContentEnumerationAccess > xCEA( rTextContent, UNO_QUERY );
+ if( xCEA.is() )
+ xContentEnum.set(xCEA->createContentEnumeration( gsTextContentService ));
+ const bool bHasContentEnum = xContentEnum.is() &&
+ xContentEnum->hasMoreElements();
+
+ Reference < XTextSection > xSection;
+ if( bHasContentEnum )
+ {
+ // For the auto styles, the multi property set helper is only used
+ // if hard attributes are existing. Therefore, it seems to be a better
+ // strategy to have the TextSection property separate, because otherwise
+ // we always retrieve the style names even if they are not required.
+ if( bAutoStyles )
+ {
+ if( xPropSet->getPropertySetInfo()->hasPropertyByName( gsTextSection ) )
+ {
+ xSection.set(xPropSet->getPropertyValue( gsTextSection ), uno::UNO_QUERY);
+ }
+ }
+ else
+ {
+ if( rPropSetHelper.hasProperty( TEXT_SECTION ) )
+ {
+ xSection.set(rPropSetHelper.getValue( TEXT_SECTION ), uno::UNO_QUERY);
+ }
+ }
+ }
+
+ bool bPrevCharIsSpace(true); // true because whitespace at start is ignored
+
+ if( bAutoStyles )
+ {
+ if( bHasContentEnum )
+ exportTextContentEnumeration(
+ xContentEnum, bAutoStyles, xSection,
+ bIsProgress );
+ if ( bHasPortions )
+ {
+ exportTextRangeEnumeration(xTextEnum, bAutoStyles, bIsProgress, bPrevCharIsSpace);
+ }
+ }
+ else
+ {
+ enum XMLTokenEnum eElem =
+ 0 < nOutlineLevel ? XML_H : XML_P;
+ SvXMLElementExport aElem( GetExport(), eExtensionNS == TextPNS::EXTENSION ? XML_NAMESPACE_LO_EXT : XML_NAMESPACE_TEXT, eElem,
+ true, false );
+ if( bHasContentEnum )
+ {
+ exportTextContentEnumeration(
+ xContentEnum, bAutoStyles, xSection,
+ bIsProgress );
+ }
+ exportTextRangeEnumeration(xTextEnum, bAutoStyles, bIsProgress, bPrevCharIsSpace);
+ }
+}
+
+void XMLTextParagraphExport::exportTextRangeEnumeration(
+ const Reference < XEnumeration > & rTextEnum,
+ bool bAutoStyles, bool bIsProgress,
+ bool & rPrevCharIsSpace)
+{
+ static const char sFieldMarkName[] = "__FieldMark_";
+
+ /* This is used for exporting to strict OpenDocument 1.2, in which case traditional
+ * bookmarks are used instead of fieldmarks. */
+ FieldmarkType openFieldMark = NONE;
+
+ std::optional<SvXMLElementExport> oTextA;
+ HyperlinkData aHyperlinkData;
+
+ while( rTextEnum->hasMoreElements() )
+ {
+ Reference<XPropertySet> xPropSet(rTextEnum->nextElement(), UNO_QUERY);
+ Reference < XTextRange > xTxtRange(xPropSet, uno::UNO_QUERY);
+ Reference<XPropertySetInfo> xPropInfo(xPropSet->getPropertySetInfo());
+
+ if (!bAutoStyles)
+ {
+ if (HyperlinkData aNewHyperlinkData(xPropSet); aNewHyperlinkData != aHyperlinkData)
+ {
+ aHyperlinkData = aNewHyperlinkData;
+ oTextA.reset();
+ if (aHyperlinkData.addHyperlinkAttributes(GetExport()))
+ {
+ oTextA.emplace(GetExport(), true, XML_NAMESPACE_TEXT, XML_A, false, false);
+ aHyperlinkData.exportEvents(GetExport());
+ }
+ }
+ }
+
+ if (xPropInfo->hasPropertyByName(gsTextPortionType))
+ {
+ OUString sType;
+ xPropSet->getPropertyValue(gsTextPortionType) >>= sType;
+
+ if( sType == gsText)
+ {
+ exportTextRange( xTxtRange, bAutoStyles,
+ rPrevCharIsSpace, openFieldMark);
+ }
+ else if( sType == gsTextField)
+ {
+ exportTextField(xTxtRange, bAutoStyles, bIsProgress, &rPrevCharIsSpace);
+ }
+ else if ( sType == "Annotation" )
+ {
+ exportTextField(xTxtRange, bAutoStyles, bIsProgress, &rPrevCharIsSpace);
+ }
+ else if ( sType == "AnnotationEnd" )
+ {
+ if (!bAutoStyles)
+ {
+ Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
+ const OUString& rName = xBookmark->getName();
+ if (!rName.isEmpty())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_OFFICE, XML_NAME, rName);
+ }
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_OFFICE, XML_ANNOTATION_END, false, false );
+ }
+ }
+ else if( sType == gsFrame )
+ {
+ Reference < XEnumeration> xContentEnum;
+ Reference < XContentEnumerationAccess > xCEA( xTxtRange,
+ UNO_QUERY );
+ if( xCEA.is() )
+ xContentEnum.set(xCEA->createContentEnumeration(
+ gsTextContentService ));
+ // frames are never in sections
+ Reference<XTextSection> xSection;
+ if( xContentEnum.is() )
+ exportTextContentEnumeration( xContentEnum,
+ bAutoStyles,
+ xSection, bIsProgress, true,
+ &xPropSet );
+
+ }
+ else if (sType == gsFootnote)
+ {
+ exportTextFootnote(xPropSet,
+ xTxtRange->getString(),
+ bAutoStyles, bIsProgress );
+ }
+ else if (sType == gsBookmark)
+ {
+ exportTextMark(xPropSet,
+ gsBookmark,
+ lcl_XmlBookmarkElements,
+ bAutoStyles);
+ }
+ else if (sType == gsReferenceMark)
+ {
+ exportTextMark(xPropSet,
+ gsReferenceMark,
+ lcl_XmlReferenceElements,
+ bAutoStyles);
+ }
+ else if (sType == gsDocumentIndexMark)
+ {
+ m_pIndexMarkExport->ExportIndexMark(xPropSet, bAutoStyles);
+ }
+ else if (sType == gsRedline)
+ {
+ if (nullptr != m_pRedlineExport)
+ m_pRedlineExport->ExportChange(xPropSet, bAutoStyles);
+ }
+ else if (sType == gsRuby)
+ {
+ exportRuby(xPropSet, bAutoStyles);
+ }
+ else if (sType == "InContentMetadata")
+ {
+ exportMeta(xPropSet, bAutoStyles, bIsProgress, rPrevCharIsSpace);
+ }
+ else if (sType == "ContentControl")
+ {
+ ExportContentControl(xPropSet, bAutoStyles, bIsProgress, rPrevCharIsSpace);
+ }
+ else if (sType == gsTextFieldStart)
+ {
+ Reference< css::text::XFormField > xFormField(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
+
+ /* As of now, textmarks are a proposed extension to the OpenDocument standard. */
+ if (!bAutoStyles)
+ {
+ if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
+ {
+ Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
+ if (xBookmark.is())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xBookmark->getName());
+ }
+
+ if (xFormField.is())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_FIELD, XML_TYPE, xFormField->getFieldType());
+ }
+
+ GetExport().StartElement(XML_NAMESPACE_FIELD, XML_FIELDMARK_START, false);
+ if (xFormField.is())
+ {
+ FieldParamExporter(&GetExport(), xFormField->getParameters()).Export();
+ }
+ GetExport().EndElement(XML_NAMESPACE_FIELD, XML_FIELDMARK_START, false);
+ }
+ /* The OpenDocument standard does not include support for TextMarks for now, so use bookmarks instead. */
+ else
+ {
+ if (xFormField.is())
+ {
+ OUString sName;
+ Reference< css::container::XNameAccess > xParameters = xFormField->getParameters();
+ if (xParameters.is() && xParameters->hasByName("Name"))
+ {
+ const Any aValue = xParameters->getByName("Name");
+ aValue >>= sName;
+ }
+ if (sName.isEmpty())
+ { // name attribute is mandatory, so have to pull a
+ // rabbit out of the hat here
+ sName = sFieldMarkName + OUString::number(
+ m_xImpl->AddFieldMarkStart(xFormField));
+ }
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME,
+ sName);
+ SvXMLElementExport aElem( GetExport(), !bAutoStyles,
+ XML_NAMESPACE_TEXT, XML_BOOKMARK_START,
+ false, false );
+ const OUString sFieldType = xFormField->getFieldType();
+ if (sFieldType == ODF_FORMTEXT)
+ {
+ openFieldMark = TEXT;
+ }
+ else if (sFieldType == ODF_FORMCHECKBOX)
+ {
+ openFieldMark = CHECK;
+ }
+ else
+ {
+ openFieldMark = NONE;
+ }
+ }
+ }
+ }
+ }
+ else if (sType == gsTextFieldSep)
+ {
+ if (!bAutoStyles)
+ {
+ if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
+ {
+ SvXMLElementExport aElem( GetExport(), !bAutoStyles,
+ XML_NAMESPACE_FIELD, XML_FIELDMARK_SEPARATOR,
+ false, false );
+ }
+ }
+ }
+ else if (sType == gsTextFieldEnd)
+ {
+ if (!bAutoStyles)
+ {
+ Reference< css::text::XFormField > xFormField(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
+
+ if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
+ {
+ SvXMLElementExport aElem( GetExport(), !bAutoStyles,
+ XML_NAMESPACE_FIELD, XML_FIELDMARK_END,
+ false, false );
+ }
+ else
+ {
+ if (xFormField.is())
+ {
+ OUString sName;
+ Reference< css::container::XNameAccess > xParameters = xFormField->getParameters();
+ if (xParameters.is() && xParameters->hasByName("Name"))
+ {
+ const Any aValue = xParameters->getByName("Name");
+ aValue >>= sName;
+ }
+ if (sName.isEmpty())
+ { // name attribute is mandatory, so have to pull a
+ // rabbit out of the hat here
+ sName = sFieldMarkName + OUString::number(
+ m_xImpl->GetFieldMarkIndex(xFormField));
+ }
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME,
+ sName);
+ SvXMLElementExport aElem( GetExport(), !bAutoStyles,
+ XML_NAMESPACE_TEXT, XML_BOOKMARK_END,
+ false, false );
+ }
+ }
+ }
+ }
+ else if (sType == gsTextFieldStartEnd)
+ {
+ if (!bAutoStyles)
+ {
+ if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
+ {
+ Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
+ if (xBookmark.is())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xBookmark->getName());
+ }
+ Reference< css::text::XFormField > xFormField(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
+ if (xFormField.is())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_FIELD, XML_TYPE, xFormField->getFieldType());
+ }
+ GetExport().StartElement(XML_NAMESPACE_FIELD, XML_FIELDMARK, false);
+ if (xFormField.is())
+ {
+ FieldParamExporter(&GetExport(), xFormField->getParameters()).Export();
+ }
+ GetExport().EndElement(XML_NAMESPACE_FIELD, XML_FIELDMARK, false);
+ }
+ else
+ {
+ Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
+ if (xBookmark.is())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xBookmark->getName());
+ SvXMLElementExport aElem( GetExport(), !bAutoStyles,
+ XML_NAMESPACE_TEXT, XML_BOOKMARK,
+ false, false );
+ }
+ }
+ }
+ }
+ else if (sType == gsSoftPageBreak)
+ {
+ if (!bAutoStyles)
+ exportSoftPageBreak();
+ }
+ else if (sType == "LineBreak")
+ {
+ if (!bAutoStyles)
+ exportTextLineBreak(xPropSet);
+ }
+ else {
+ OSL_FAIL("unknown text portion type");
+ }
+ }
+ else
+ {
+ Reference<XServiceInfo> xServiceInfo( xTxtRange, UNO_QUERY );
+ if( xServiceInfo->supportsService( gsTextFieldService ) )
+ {
+ exportTextField(xTxtRange, bAutoStyles, bIsProgress, &rPrevCharIsSpace);
+ }
+ else
+ {
+ // no TextPortionType property -> non-Writer app -> text
+ exportTextRange(xTxtRange, bAutoStyles, rPrevCharIsSpace, openFieldMark);
+ }
+ }
+ }
+
+// now that there are nested enumerations for meta(-field), this may be valid!
+// SAL_WARN_IF( bOpenRuby, "xmloff", "Red Alert: Ruby still open!" );
+}
+
+void XMLTextParagraphExport::exportTable(
+ const Reference < XTextContent > &,
+ bool /*bAutoStyles*/, bool /*bIsProgress*/ )
+{
+}
+
+void XMLTextParagraphExport::exportTextField(
+ const Reference < XTextRange > & rTextRange,
+ bool bAutoStyles, bool bIsProgress, bool *const pPrevCharIsSpace)
+{
+ Reference < XPropertySet > xPropSet( rTextRange, UNO_QUERY );
+ // non-Writer apps need not support Property TextField, so test first
+ if (!xPropSet->getPropertySetInfo()->hasPropertyByName( gsTextField ))
+ return;
+
+ Reference < XTextField > xTxtFld(xPropSet->getPropertyValue( gsTextField ), uno::UNO_QUERY);
+ SAL_WARN_IF( !xTxtFld.is(), "xmloff", "text field missing" );
+ if( xTxtFld.is() )
+ {
+ exportTextField(xTxtFld, bAutoStyles, bIsProgress, true, pPrevCharIsSpace);
+ }
+ else
+ {
+ // write only characters
+ GetExport().Characters(rTextRange->getString());
+ }
+}
+
+void XMLTextParagraphExport::exportTextField(
+ const Reference < XTextField > & xTextField,
+ const bool bAutoStyles, const bool bIsProgress,
+ const bool bRecursive, bool *const pPrevCharIsSpace)
+{
+ if ( bAutoStyles )
+ {
+ m_pFieldExport->ExportFieldAutoStyle( xTextField, bIsProgress,
+ bRecursive );
+ }
+ else
+ {
+ assert(pPrevCharIsSpace);
+ m_pFieldExport->ExportField(xTextField, bIsProgress, *pPrevCharIsSpace);
+ }
+}
+
+void XMLTextParagraphExport::exportSoftPageBreak()
+{
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
+ XML_SOFT_PAGE_BREAK, false,
+ false );
+}
+
+void XMLTextParagraphExport::exportTextLineBreak(
+ const uno::Reference<beans::XPropertySet>& xPropSet)
+{
+ static const XMLTokenEnum aLineBreakClears[] = {
+ XML_NONE,
+ XML_LEFT,
+ XML_RIGHT,
+ XML_ALL,
+ };
+
+ uno::Reference<text::XTextContent> xLineBreak;
+ xPropSet->getPropertyValue("LineBreak") >>= xLineBreak;
+ if (!xLineBreak.is())
+ {
+ return;
+ }
+
+ uno::Reference<beans::XPropertySet> xLineBreakProps(xLineBreak, uno::UNO_QUERY);
+ if (!xLineBreakProps.is())
+ {
+ return;
+ }
+
+ sal_Int16 eClear{};
+ xLineBreakProps->getPropertyValue("Clear") >>= eClear;
+ if (eClear >= 0 && o3tl::make_unsigned(eClear) < SAL_N_ELEMENTS(aLineBreakClears))
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_CLEAR,
+ GetXMLToken(aLineBreakClears[eClear]));
+ }
+ SvXMLElementExport aElem(GetExport(), XML_NAMESPACE_TEXT, XML_LINE_BREAK,
+ /*bIgnWSOutside=*/false, /*bIgnWSInside=*/false);
+}
+
+void XMLTextParagraphExport::exportTextMark(
+ const Reference<XPropertySet> & rPropSet,
+ const OUString& rProperty,
+ const ::xmloff::token::XMLTokenEnum pElements[],
+ bool bAutoStyles)
+{
+ // mib said: "Hau wech!"
+
+ // (Originally, I'd export a span element in case the (book|reference)mark
+ // was formatted. This actually makes a difference in case some pervert
+ // sets a point reference mark in the document and, say, formats it bold.
+ // This basically meaningless formatting will now been thrown away
+ // (aka cleaned up), since mib said: ... dvo
+
+ if (bAutoStyles)
+ return;
+
+ // name element
+ Reference<XNamed> xName(rPropSet->getPropertyValue(rProperty), UNO_QUERY);
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME,
+ xName->getName());
+
+ // start, end, or point-reference?
+ sal_Int8 nElement;
+ if( *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsCollapsed)) )
+ {
+ nElement = 0;
+ }
+ else
+ {
+ nElement = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsStart)) ? 1 : 2;
+ }
+
+ // bookmark, bookmark-start: xml:id and RDFa for RDF metadata
+ if( nElement < 2 ) {
+ GetExport().AddAttributeXmlId(xName);
+ const uno::Reference<text::XTextContent> xTextContent(
+ xName, uno::UNO_QUERY_THROW);
+ GetExport().AddAttributesRDFa(xTextContent);
+ }
+
+ // bookmark-start: add attributes hidden and condition
+ if (nElement == 1)
+ {
+ Reference<XPropertySet> bkmkProps(rPropSet->getPropertyValue(rProperty), UNO_QUERY);
+ Reference<XPropertySetInfo> bkmkPropInfo = bkmkProps->getPropertySetInfo();
+ OUString sHidden("BookmarkHidden");
+ if (bkmkPropInfo->hasPropertyByName(sHidden))
+ {
+ bool bHidden = false;
+ bkmkProps->getPropertyValue(sHidden) >>= bHidden;
+ if (bHidden)
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, "hidden", "true");
+ OUString sCondition("BookmarkCondition");
+ if (bkmkPropInfo->hasPropertyByName(sCondition))
+ {
+ OUString sBookmarkCondition;
+ bkmkProps->getPropertyValue(sCondition) >>= sBookmarkCondition;
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, "condition", sBookmarkCondition);
+ }
+ }
+ }
+ }
+
+ // export element
+ assert(pElements != nullptr);
+ assert(0 <= nElement && nElement <= 2);
+ SvXMLElementExport aElem(GetExport(),
+ XML_NAMESPACE_TEXT, pElements[nElement],
+ false, false);
+ // else: no styles. (see above)
+}
+
+static bool lcl_txtpara_isBoundAsChar(
+ const Reference < XPropertySet > & rPropSet,
+ const Reference < XPropertySetInfo > & rPropSetInfo )
+{
+ bool bIsBoundAsChar = false;
+ OUString sAnchorType( "AnchorType" );
+ if( rPropSetInfo->hasPropertyByName( sAnchorType ) )
+ {
+ TextContentAnchorType eAnchor;
+ rPropSet->getPropertyValue( sAnchorType ) >>= eAnchor;
+ bIsBoundAsChar = TextContentAnchorType_AS_CHARACTER == eAnchor;
+ }
+
+ return bIsBoundAsChar;
+}
+
+XMLShapeExportFlags XMLTextParagraphExport::addTextFrameAttributes(
+ const Reference < XPropertySet >& rPropSet,
+ bool bShape,
+ basegfx::B2DPoint* pCenter,
+ OUString* pMinHeightValue,
+ OUString* pMinWidthValue)
+{
+ XMLShapeExportFlags nShapeFeatures = SEF_DEFAULT;
+
+ // draw:name (#97662#: not for shapes, since those names will be
+ // treated in the shape export)
+ if( !bShape )
+ {
+ Reference < XNamed > xNamed( rPropSet, UNO_QUERY );
+ if( xNamed.is() )
+ {
+ OUString sName( xNamed->getName() );
+ if( !sName.isEmpty() )
+ GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_NAME,
+ xNamed->getName() );
+ }
+ }
+
+ OUStringBuffer sValue;
+
+ // text:anchor-type
+ TextContentAnchorType eAnchor = TextContentAnchorType_AT_PARAGRAPH;
+ rPropSet->getPropertyValue( gsAnchorType ) >>= eAnchor;
+ {
+ XMLAnchorTypePropHdl aAnchorTypeHdl;
+ OUString sTmp;
+ aAnchorTypeHdl.exportXML( sTmp, uno::Any(eAnchor),
+ GetExport().GetMM100UnitConverter() );
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_ANCHOR_TYPE, sTmp );
+ }
+
+ // text:anchor-page-number
+ if( TextContentAnchorType_AT_PAGE == eAnchor )
+ {
+ sal_Int16 nPage = 0;
+ rPropSet->getPropertyValue( gsAnchorPageNo ) >>= nPage;
+ SAL_WARN_IF(nPage <= 0, "xmloff",
+ "ERROR: writing invalid anchor-page-number 0");
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_ANCHOR_PAGE_NUMBER,
+ OUString::number( nPage ) );
+ }
+ else
+ {
+ nShapeFeatures |= XMLShapeExportFlags::NO_WS;
+ }
+
+ // OD 2004-06-01 #i27691# - correction: no export of svg:x, if object
+ // is anchored as-character.
+ if ( !bShape &&
+ eAnchor != TextContentAnchorType_AS_CHARACTER )
+ {
+ // svg:x
+ sal_Int16 nHoriOrient = HoriOrientation::NONE;
+ rPropSet->getPropertyValue( gsHoriOrient ) >>= nHoriOrient;
+ if( HoriOrientation::NONE == nHoriOrient )
+ {
+ sal_Int32 nPos = 0;
+ rPropSet->getPropertyValue( gsHoriOrientPosition ) >>= nPos;
+ GetExport().GetMM100UnitConverter().convertMeasureToXML(
+ sValue, nPos );
+ GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_X,
+ sValue.makeStringAndClear() );
+ if(nullptr != pCenter)
+ {
+ // add left edge to Center
+ pCenter->setX(pCenter->getX() + nPos);
+ }
+ }
+ }
+ else if( TextContentAnchorType_AS_CHARACTER == eAnchor )
+ nShapeFeatures = (nShapeFeatures & ~XMLShapeExportFlags::X);
+
+ if( !bShape || TextContentAnchorType_AS_CHARACTER == eAnchor )
+ {
+ // svg:y
+ sal_Int16 nVertOrient = VertOrientation::NONE;
+ rPropSet->getPropertyValue( gsVertOrient ) >>= nVertOrient;
+ if( VertOrientation::NONE == nVertOrient )
+ {
+ sal_Int32 nPos = 0;
+ rPropSet->getPropertyValue( gsVertOrientPosition ) >>= nPos;
+ GetExport().GetMM100UnitConverter().convertMeasureToXML(
+ sValue, nPos );
+ GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_Y,
+ sValue.makeStringAndClear() );
+ if(nullptr != pCenter)
+ {
+ // add top edge to Center
+ pCenter->setY(pCenter->getY() + nPos);
+ }
+ }
+ if( bShape )
+ nShapeFeatures = (nShapeFeatures & ~XMLShapeExportFlags::Y);
+ }
+
+ Reference< XPropertySetInfo > xPropSetInfo(rPropSet->getPropertySetInfo());
+
+ bool bSyncWidth = false;
+ if (xPropSetInfo->hasPropertyByName(gsIsSyncWidthToHeight))
+ {
+ bSyncWidth = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsSyncWidthToHeight));
+ }
+ sal_Int16 nRelWidth = 0;
+ if (!bSyncWidth && xPropSetInfo->hasPropertyByName(gsRelativeWidth))
+ {
+ rPropSet->getPropertyValue(gsRelativeWidth) >>= nRelWidth;
+ }
+ bool bSyncHeight = false;
+ if (xPropSetInfo->hasPropertyByName(gsIsSyncHeightToWidth))
+ {
+ bSyncHeight = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsSyncHeightToWidth));
+ }
+ sal_Int16 nRelHeight = 0;
+ if (!bSyncHeight && xPropSetInfo->hasPropertyByName(gsRelativeHeight))
+ {
+ rPropSet->getPropertyValue(gsRelativeHeight) >>= nRelHeight;
+ }
+ awt::Size aLayoutSize;
+ if ((nRelWidth > 0 || nRelHeight > 0) && xPropSetInfo->hasPropertyByName("LayoutSize"))
+ {
+ rPropSet->getPropertyValue("LayoutSize") >>= aLayoutSize;
+ }
+
+ bool bUseLayoutSize = true;
+ if (bSyncWidth && bSyncHeight)
+ {
+ // This is broken, width depends on height and height depends on width. Don't use the
+ // invalid layout size we got.
+ bUseLayoutSize = false;
+ }
+ if (aLayoutSize.Width <= 0 || aLayoutSize.Height <= 0)
+ {
+ // This is broken, Writer frames have a minimal size, see MINFLY.
+ bUseLayoutSize = false;
+ }
+
+ // svg:width
+ sal_Int16 nWidthType = SizeType::FIX;
+ if( xPropSetInfo->hasPropertyByName( gsWidthType ) )
+ {
+ rPropSet->getPropertyValue( gsWidthType ) >>= nWidthType;
+ }
+ if( xPropSetInfo->hasPropertyByName( gsWidth ) )
+ {
+ sal_Int32 nWidth = 0;
+ // VAR size will be written as zero min-size
+ if( SizeType::VARIABLE != nWidthType )
+ {
+ rPropSet->getPropertyValue( gsWidth ) >>= nWidth;
+ }
+ GetExport().GetMM100UnitConverter().convertMeasureToXML(sValue, nWidth);
+ if( SizeType::FIX != nWidthType )
+ {
+ assert(pMinWidthValue);
+ if (pMinWidthValue)
+ {
+ *pMinWidthValue = sValue.makeStringAndClear();
+ }
+ }
+ else
+ {
+ if ((nRelWidth > 0 || bSyncWidth) && bUseLayoutSize)
+ {
+ // Relative width: write the layout size for the fallback width.
+ sValue.setLength(0);
+ GetExport().GetMM100UnitConverter().convertMeasureToXML(sValue, aLayoutSize.Width);
+ }
+
+ GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_WIDTH,
+ sValue.makeStringAndClear() );
+ if(nullptr != pCenter)
+ {
+ // add half width to Center
+ pCenter->setX(pCenter->getX() + (0.5 * nWidth));
+ }
+ }
+ }
+ if( xPropSetInfo->hasPropertyByName( gsIsSyncWidthToHeight ) )
+ {
+ if( bSyncWidth )
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_WIDTH,
+ XML_SCALE );
+ }
+ if( !bSyncWidth && xPropSetInfo->hasPropertyByName( gsRelativeWidth ) )
+ {
+ SAL_WARN_IF( nRelWidth < 0 || nRelWidth > 254, "xmloff",
+ "Got illegal relative width from API" );
+ if( nRelWidth > 0 )
+ {
+ ::sax::Converter::convertPercent( sValue, nRelWidth );
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_WIDTH,
+ sValue.makeStringAndClear() );
+ }
+ }
+
+ // svg:height, fo:min-height or style:rel-height
+ sal_Int16 nSizeType = SizeType::FIX;
+ if( xPropSetInfo->hasPropertyByName( gsSizeType ) )
+ {
+ rPropSet->getPropertyValue( gsSizeType ) >>= nSizeType;
+ }
+ if( xPropSetInfo->hasPropertyByName( gsHeight ) )
+ {
+ sal_Int32 nHeight = 0;
+ if( SizeType::VARIABLE != nSizeType )
+ {
+ rPropSet->getPropertyValue( gsHeight ) >>= nHeight;
+ }
+ GetExport().GetMM100UnitConverter().convertMeasureToXML( sValue,
+ nHeight );
+ if( SizeType::FIX != nSizeType && 0==nRelHeight && !bSyncHeight &&
+ pMinHeightValue )
+ {
+ *pMinHeightValue = sValue.makeStringAndClear();
+ }
+ else
+ {
+ if ((nRelHeight > 0 || bSyncHeight) && bUseLayoutSize)
+ {
+ // Relative height: write the layout size for the fallback height.
+ sValue.setLength(0);
+ GetExport().GetMM100UnitConverter().convertMeasureToXML(sValue, aLayoutSize.Height);
+ }
+
+ GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_HEIGHT,
+ sValue.makeStringAndClear() );
+ if(nullptr != pCenter)
+ {
+ // add half height to Center
+ pCenter->setY(pCenter->getY() + (0.5 * nHeight));
+ }
+ }
+ }
+ if( bSyncHeight )
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_HEIGHT,
+ SizeType::MIN == nSizeType ? XML_SCALE_MIN : XML_SCALE );
+
+ }
+ else if( nRelHeight > 0 )
+ {
+ ::sax::Converter::convertPercent( sValue, nRelHeight );
+ if( SizeType::MIN == nSizeType )
+ {
+ assert(pMinHeightValue);
+ if (pMinHeightValue)
+ {
+ *pMinHeightValue = sValue.makeStringAndClear();
+ }
+ }
+ else
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_HEIGHT,
+ sValue.makeStringAndClear() );
+ }
+
+ OUString sZOrder( "ZOrder" );
+ if( xPropSetInfo->hasPropertyByName( sZOrder ) )
+ {
+ sal_Int32 nZIndex = 0;
+ rPropSet->getPropertyValue( sZOrder ) >>= nZIndex;
+ if( -1 != nZIndex )
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_ZINDEX,
+ OUString::number( nZIndex ) );
+ }
+ }
+
+ if (xPropSetInfo->hasPropertyByName("IsSplitAllowed")
+ && rPropSet->getPropertyValue("IsSplitAllowed").get<bool>())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_MAY_BREAK_BETWEEN_PAGES, XML_TRUE);
+ }
+
+ return nShapeFeatures;
+}
+
+void XMLTextParagraphExport::exportAnyTextFrame(
+ const Reference < XTextContent > & rTxtCntnt,
+ FrameType eType,
+ bool bAutoStyles,
+ bool bIsProgress,
+ bool bExportContent,
+ const Reference < XPropertySet > *pRangePropSet)
+{
+ Reference < XPropertySet > xPropSet( rTxtCntnt, UNO_QUERY );
+
+ if( bAutoStyles )
+ {
+ if( FrameType::Embedded == eType )
+ _collectTextEmbeddedAutoStyles( xPropSet );
+ // No text frame style for shapes (#i28745#)
+ else if ( FrameType::Shape != eType )
+ Add( XmlStyleFamily::TEXT_FRAME, xPropSet );
+
+ if( pRangePropSet && lcl_txtpara_isBoundAsChar( xPropSet,
+ xPropSet->getPropertySetInfo() ) )
+ Add( XmlStyleFamily::TEXT_TEXT, *pRangePropSet );
+
+ switch( eType )
+ {
+ case FrameType::Text:
+ {
+ // frame bound frames
+ if ( bExportContent )
+ {
+ Reference < XTextFrame > xTxtFrame( rTxtCntnt, UNO_QUERY );
+ bool bAlreadySeen = !maFrameRecurseGuard.insert(xTxtFrame).second;
+ if (bAlreadySeen)
+ {
+ SAL_WARN("xmloff", "loop in frame export, ditching");
+ }
+ else
+ {
+ comphelper::ScopeGuard const g([this, xTxtFrame]() {
+ maFrameRecurseGuard.erase(xTxtFrame);
+ });
+ Reference < XText > xTxt(xTxtFrame->getText());
+ exportFrameFrames( true, bIsProgress, xTxtFrame );
+ exportText( xTxt, bAutoStyles, bIsProgress, true );
+ }
+ }
+ }
+ break;
+ case FrameType::Shape:
+ {
+ Reference < XShape > xShape( rTxtCntnt, UNO_QUERY );
+ bool bAlreadySeen = !maShapeRecurseGuard.insert(xShape).second;
+ if (bAlreadySeen)
+ {
+ SAL_WARN("xmloff", "loop in shape export, ditching");
+ }
+ else
+ {
+ comphelper::ScopeGuard const g([this, xShape]() {
+ maShapeRecurseGuard.erase(xShape);
+ });
+ GetExport().GetShapeExport()->collectShapeAutoStyles( xShape );
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ Reference< XPropertySetInfo > xPropSetInfo(xPropSet->getPropertySetInfo());
+ {
+ bool bAddCharStyles = pRangePropSet &&
+ lcl_txtpara_isBoundAsChar( xPropSet, xPropSetInfo );
+
+ bool bIsUICharStyle;
+ bool bHasAutoStyle = false;
+
+ OUString sStyle;
+
+ if( bAddCharStyles )
+ sStyle = FindTextStyle( *pRangePropSet, bIsUICharStyle, bHasAutoStyle );
+ else
+ bIsUICharStyle = false;
+
+ bool bDoSomething = bIsUICharStyle
+ && m_aCharStyleNamesPropInfoCache.hasProperty( *pRangePropSet );
+ XMLTextCharStyleNamesElementExport aCharStylesExport(
+ GetExport(), bDoSomething, bHasAutoStyle,
+ bDoSomething ? *pRangePropSet : Reference<XPropertySet>(),
+ gsCharStyleNames );
+
+ if( !sStyle.isEmpty() )
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
+ GetExport().EncodeStyleName( sStyle ) );
+ {
+ SvXMLElementExport aElem( GetExport(), !sStyle.isEmpty(),
+ XML_NAMESPACE_TEXT, XML_SPAN, false, false );
+ {
+ SvXMLElementExport aElement( GetExport(),
+ FrameType::Shape != eType &&
+ HyperlinkData(xPropSet).addHyperlinkAttributes(GetExport()),
+ XML_NAMESPACE_DRAW, XML_A, false, false );
+ switch( eType )
+ {
+ case FrameType::Text:
+ _exportTextFrame( xPropSet, xPropSetInfo, bIsProgress );
+ break;
+ case FrameType::Graphic:
+ _exportTextGraphic( xPropSet, xPropSetInfo );
+ break;
+ case FrameType::Embedded:
+ _exportTextEmbedded( xPropSet, xPropSetInfo );
+ break;
+ case FrameType::Shape:
+ {
+ Reference < XShape > xShape( rTxtCntnt, UNO_QUERY );
+ XMLShapeExportFlags nFeatures =
+ addTextFrameAttributes( xPropSet, true );
+ GetExport().GetShapeExport()
+ ->exportShape( xShape, nFeatures );
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+void XMLTextParagraphExport::_exportTextFrame(
+ const Reference < XPropertySet > & rPropSet,
+ const Reference < XPropertySetInfo > & rPropSetInfo,
+ bool bIsProgress )
+{
+ Reference < XTextFrame > xTxtFrame( rPropSet, UNO_QUERY );
+ Reference < XText > xTxt(xTxtFrame->getText());
+
+ OUString sStyle;
+ if( rPropSetInfo->hasPropertyByName( gsFrameStyleName ) )
+ {
+ rPropSet->getPropertyValue( gsFrameStyleName ) >>= sStyle;
+ }
+
+ OUString aMinHeightValue;
+ OUString sMinWidthValue;
+ OUString sAutoStyle = Find( XmlStyleFamily::TEXT_FRAME, rPropSet, sStyle );
+ if ( sAutoStyle.isEmpty() )
+ sAutoStyle = sStyle;
+ if( !sAutoStyle.isEmpty() )
+ GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE_NAME,
+ GetExport().EncodeStyleName( sAutoStyle ) );
+ addTextFrameAttributes(rPropSet, false, nullptr, &aMinHeightValue, &sMinWidthValue);
+
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW,
+ XML_FRAME, false, true );
+
+ if( !aMinHeightValue.isEmpty() )
+ GetExport().AddAttribute( XML_NAMESPACE_FO, XML_MIN_HEIGHT,
+ aMinHeightValue );
+
+ if (!sMinWidthValue.isEmpty())
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_FO, XML_MIN_WIDTH,
+ sMinWidthValue );
+ }
+
+ // draw:chain-next-name
+ if( rPropSetInfo->hasPropertyByName( gsChainNextName ) )
+ {
+ OUString sNext;
+ if( (rPropSet->getPropertyValue( gsChainNextName ) >>= sNext) && !sNext.isEmpty() )
+ GetExport().AddAttribute( XML_NAMESPACE_DRAW,
+ XML_CHAIN_NEXT_NAME,
+ sNext );
+ }
+
+ {
+ SvXMLElementExport aElement( GetExport(), XML_NAMESPACE_DRAW,
+ XML_TEXT_BOX, true, true );
+
+ // frames bound to frame
+ exportFrameFrames( false, bIsProgress, xTxtFrame );
+
+ exportText( xTxt, false, bIsProgress, true );
+ }
+
+ // script:events
+ Reference<XEventsSupplier> xEventsSupp( xTxtFrame, UNO_QUERY );
+ GetExport().GetEventExport().Export(xEventsSupp);
+
+ // image map
+ GetExport().GetImageMapExport().Export( rPropSet );
+
+ // svg:title and svg:desc (#i73249#)
+ exportTitleAndDescription( rPropSet, rPropSetInfo );
+}
+
+void XMLTextParagraphExport::exportContour(
+ const Reference < XPropertySet > & rPropSet,
+ const Reference < XPropertySetInfo > & rPropSetInfo )
+{
+ if( !rPropSetInfo->hasPropertyByName( gsContourPolyPolygon ) )
+ {
+ return;
+ }
+
+ PointSequenceSequence aSourcePolyPolygon;
+ rPropSet->getPropertyValue( gsContourPolyPolygon ) >>= aSourcePolyPolygon;
+ const basegfx::B2DPolyPolygon aPolyPolygon(
+ basegfx::utils::UnoPointSequenceSequenceToB2DPolyPolygon(
+ aSourcePolyPolygon));
+ const sal_uInt32 nPolygonCount(aPolyPolygon.count());
+
+ if(!nPolygonCount)
+ {
+ return;
+ }
+
+ const basegfx::B2DRange aPolyPolygonRange(aPolyPolygon.getB2DRange());
+ bool bPixel(false);
+
+ if( rPropSetInfo->hasPropertyByName( gsIsPixelContour ) )
+ {
+ bPixel = *o3tl::doAccess<bool>(rPropSet->getPropertyValue( gsIsPixelContour ));
+ }
+
+ // svg: width
+ OUStringBuffer aStringBuffer( 10 );
+
+ if(bPixel)
+ {
+ ::sax::Converter::convertMeasurePx(aStringBuffer, basegfx::fround(aPolyPolygonRange.getWidth()));
+ }
+ else
+ {
+ GetExport().GetMM100UnitConverter().convertMeasureToXML(aStringBuffer, basegfx::fround(aPolyPolygonRange.getWidth()));
+ }
+
+ GetExport().AddAttribute(XML_NAMESPACE_SVG, XML_WIDTH, aStringBuffer.makeStringAndClear());
+
+ // svg: height
+ if(bPixel)
+ {
+ ::sax::Converter::convertMeasurePx(aStringBuffer, basegfx::fround(aPolyPolygonRange.getHeight()));
+ }
+ else
+ {
+ GetExport().GetMM100UnitConverter().convertMeasureToXML(aStringBuffer, basegfx::fround(aPolyPolygonRange.getHeight()));
+ }
+
+ GetExport().AddAttribute(XML_NAMESPACE_SVG, XML_HEIGHT, aStringBuffer.makeStringAndClear());
+
+ // svg:viewbox
+ SdXMLImExViewBox aViewBox(0.0, 0.0, aPolyPolygonRange.getWidth(), aPolyPolygonRange.getHeight());
+ GetExport().AddAttribute(XML_NAMESPACE_SVG, XML_VIEWBOX, aViewBox.GetExportString());
+ enum XMLTokenEnum eElem = XML_TOKEN_INVALID;
+
+ if(1 == nPolygonCount )
+ {
+ // simple polygon shape, can be written as svg:points sequence
+ const OUString aPointString(
+ basegfx::utils::exportToSvgPoints(
+ aPolyPolygon.getB2DPolygon(0)));
+
+ // write point array
+ GetExport().AddAttribute(XML_NAMESPACE_DRAW, XML_POINTS, aPointString);
+ eElem = XML_CONTOUR_POLYGON;
+ }
+ else
+ {
+ // polypolygon, needs to be written as a svg:path sequence
+ const OUString aPolygonString(
+ basegfx::utils::exportToSvgD(
+ aPolyPolygon,
+ true, // bUseRelativeCoordinates
+ false, // bDetectQuadraticBeziers: not used in old, but maybe activated now
+ true)); // bHandleRelativeNextPointCompatible
+
+ // write point array
+ GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_D, aPolygonString);
+ eElem = XML_CONTOUR_PATH;
+ }
+
+ if( rPropSetInfo->hasPropertyByName( gsIsAutomaticContour ) )
+ {
+ bool bTmp = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(
+ gsIsAutomaticContour ));
+ GetExport().AddAttribute( XML_NAMESPACE_DRAW,
+ XML_RECREATE_ON_EDIT, bTmp ? XML_TRUE : XML_FALSE );
+ }
+
+ // write object now
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW, eElem,
+ true, true );
+}
+
+void XMLTextParagraphExport::_exportTextGraphic(
+ const Reference < XPropertySet > & rPropSet,
+ const Reference < XPropertySetInfo > & rPropSetInfo )
+{
+ OUString sStyle;
+ if( rPropSetInfo->hasPropertyByName( gsFrameStyleName ) )
+ {
+ rPropSet->getPropertyValue( gsFrameStyleName ) >>= sStyle;
+ }
+
+ OUString sAutoStyle = Find( XmlStyleFamily::TEXT_FRAME, rPropSet, sStyle );
+ if ( sAutoStyle.isEmpty() )
+ sAutoStyle = sStyle;
+ if( !sAutoStyle.isEmpty() )
+ GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE_NAME,
+ GetExport().EncodeStyleName( sAutoStyle ) );
+
+ // check if we need to use svg:transform
+ sal_Int16 nRotation(0);
+ rPropSet->getPropertyValue( gsGraphicRotation ) >>= nRotation;
+ const bool bUseRotation(0 != nRotation);
+ basegfx::B2DPoint aCenter(0.0, 0.0);
+
+ // add TextFrame attributes like svg:x/y/width/height, also get back
+ // object's center point if rotation is used and has to be exported
+ addTextFrameAttributes(rPropSet, false, bUseRotation ? &aCenter : nullptr);
+
+ // svg:transform
+ if(bUseRotation)
+ {
+ // RotateFlyFrameFix: im/export full 'draw:transform' using existing tooling.
+ // Currently only rotation is used, but combinations with 'draw:transform'
+ // may be necessary in the future, so that svg:x/svg:y/svg:width/svg:height
+ // may be extended/replaced with 'draw:transform' (see draw objects)
+ SdXMLImExTransform2D aSdXMLImExTransform2D;
+
+ // Convert from 10th degree integer to deg.
+ // CAUTION: internal rotation is classically mathematically 'wrong' defined by ignoring that
+ // we have a right-handed coordinate system, so need to correct this by mirroring
+ // the rotation to get the correct transformation. See also case XML_TOK_TEXT_FRAME_TRANSFORM
+ // in XMLTextFrameContext_Impl::XMLTextFrameContext_Impl and #i78696#
+ // CAUTION-II: due to tdf#115782 it is better for current ODF to indeed write it with the wrong
+ // orientation as in all other cases - ARGH! We will need to correct this in future ODF ASAP!
+ const double fRotate(basegfx::deg2rad<10>(nRotation));
+
+ // transform to rotation center which is the object's center
+ aSdXMLImExTransform2D.AddTranslate(-aCenter);
+
+ // add rotation itself
+ // tdf#115529 but correct value modulo 2PI to have it positive and in the range of [0.0 .. 2PI[
+ aSdXMLImExTransform2D.AddRotate(basegfx::normalizeToRange(fRotate, 2 * M_PI));
+
+ // back-transform after rotation
+ aSdXMLImExTransform2D.AddTranslate(aCenter);
+
+ // Note: using GetTwipUnitConverter instead of GetMM100UnitConverter may be needed,
+ // but is not generally available (as it should be, a 'current' UnitConverter should
+ // be available at GetExport() - and maybe was once). May have to be addressed as soon
+ // as translate transformations are used here.
+ GetExport().AddAttribute(
+ XML_NAMESPACE_DRAW,
+ XML_TRANSFORM,
+ aSdXMLImExTransform2D.GetExportString(GetExport().GetMM100UnitConverter()));
+ }
+
+ // original content
+ SvXMLElementExport aElem(GetExport(), XML_NAMESPACE_DRAW, XML_FRAME, false, true);
+
+ {
+ // xlink:href
+ uno::Reference<graphic::XGraphic> xGraphic;
+ rPropSet->getPropertyValue("Graphic") >>= xGraphic;
+
+ OUString sInternalURL;
+ OUString sOutMimeType;
+
+ if (xGraphic.is())
+ {
+ sInternalURL = GetExport().AddEmbeddedXGraphic(xGraphic, sOutMimeType);
+ }
+
+ // If there still is no url, then graphic is empty
+ if (!sInternalURL.isEmpty())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, sInternalURL);
+ GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE);
+ GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED);
+ GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD);
+ }
+
+ // draw:filter-name
+ OUString sGrfFilter;
+ rPropSet->getPropertyValue( gsGraphicFilter ) >>= sGrfFilter;
+ if( !sGrfFilter.isEmpty() )
+ GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_FILTER_NAME,
+ sGrfFilter );
+
+ if (GetExport().getSaneDefaultVersion() > SvtSaveOptions::ODFSVER_012)
+ {
+ if (sOutMimeType.isEmpty())
+ {
+ GetExport().GetGraphicMimeTypeFromStream(xGraphic, sOutMimeType);
+ }
+ if (!sOutMimeType.isEmpty())
+ { // ODF 1.3 OFFICE-3943
+ GetExport().AddAttribute(
+ SvtSaveOptions::ODFSVER_013 <= GetExport().getSaneDefaultVersion()
+ ? XML_NAMESPACE_DRAW
+ : XML_NAMESPACE_LO_EXT,
+ "mime-type", sOutMimeType);
+ }
+ }
+
+
+ // optional office:binary-data
+ if (xGraphic.is())
+ {
+ SvXMLElementExport aElement(GetExport(), XML_NAMESPACE_DRAW, XML_IMAGE, false, true );
+ GetExport().AddEmbeddedXGraphicAsBase64(xGraphic);
+ }
+ }
+
+ const bool bAddReplacementImages = officecfg::Office::Common::Save::Graphic::AddReplacementImages::get();
+ if (bAddReplacementImages)
+ {
+ // replacement graphic for backwards compatibility, but
+ // only for SVG and metafiles currently
+ uno::Reference<graphic::XGraphic> xReplacementGraphic;
+ rPropSet->getPropertyValue("ReplacementGraphic") >>= xReplacementGraphic;
+
+ OUString sInternalURL;
+ OUString sOutMimeType;
+
+ //Resolves: fdo#62461 put preferred image first above, followed by
+ //fallback here
+ if (xReplacementGraphic.is())
+ {
+ sInternalURL = GetExport().AddEmbeddedXGraphic(xReplacementGraphic, sOutMimeType);
+ }
+
+ // If there is no url, then graphic is empty
+ if (!sInternalURL.isEmpty())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, sInternalURL);
+ GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE);
+ GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED);
+ GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD);
+ }
+
+ if (GetExport().getSaneDefaultVersion() > SvtSaveOptions::ODFSVER_012)
+ {
+ if (sOutMimeType.isEmpty())
+ {
+ GetExport().GetGraphicMimeTypeFromStream(xReplacementGraphic, sOutMimeType);
+ }
+ if (!sOutMimeType.isEmpty())
+ { // ODF 1.3 OFFICE-3943
+ GetExport().AddAttribute(
+ SvtSaveOptions::ODFSVER_013 <= GetExport().getSaneDefaultVersion()
+ ? XML_NAMESPACE_DRAW
+ : XML_NAMESPACE_LO_EXT,
+ "mime-type", sOutMimeType);
+ }
+ }
+
+
+ // optional office:binary-data
+ if (xReplacementGraphic.is())
+ {
+ SvXMLElementExport aElement(GetExport(), XML_NAMESPACE_DRAW, XML_IMAGE, true, true);
+ GetExport().AddEmbeddedXGraphicAsBase64(xReplacementGraphic);
+ }
+ }
+
+ // script:events
+ Reference<XEventsSupplier> xEventsSupp( rPropSet, UNO_QUERY );
+ GetExport().GetEventExport().Export(xEventsSupp);
+
+ // image map
+ GetExport().GetImageMapExport().Export( rPropSet );
+
+ // svg:title and svg:desc (#i73249#)
+ exportTitleAndDescription( rPropSet, rPropSetInfo );
+
+ // draw:contour
+ exportContour( rPropSet, rPropSetInfo );
+}
+
+void XMLTextParagraphExport::_collectTextEmbeddedAutoStyles(const Reference < XPropertySet > & )
+{
+ SAL_WARN( "xmloff", "no API implementation available" );
+}
+
+void XMLTextParagraphExport::_exportTextEmbedded(
+ const Reference < XPropertySet > &,
+ const Reference < XPropertySetInfo > & )
+{
+ SAL_WARN( "xmloff", "no API implementation available" );
+}
+
+void XMLTextParagraphExport::exportEvents( const Reference < XPropertySet > & rPropSet )
+{
+ // script:events
+ Reference<XEventsSupplier> xEventsSupp( rPropSet, UNO_QUERY );
+ GetExport().GetEventExport().Export(xEventsSupp);
+
+ // image map
+ if (rPropSet->getPropertySetInfo()->hasPropertyByName("ImageMap"))
+ GetExport().GetImageMapExport().Export( rPropSet );
+}
+
+// Implement Title/Description Elements UI (#i73249#)
+void XMLTextParagraphExport::exportTitleAndDescription(
+ const Reference < XPropertySet > & rPropSet,
+ const Reference < XPropertySetInfo > & rPropSetInfo )
+{
+ // svg:title
+ if( rPropSetInfo->hasPropertyByName( gsTitle ) )
+ {
+ OUString sObjTitle;
+ rPropSet->getPropertyValue( gsTitle ) >>= sObjTitle;
+ if( !sObjTitle.isEmpty() )
+ {
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_SVG,
+ XML_TITLE, true, false );
+ GetExport().Characters( sObjTitle );
+ }
+ }
+
+ // svg:description
+ if( rPropSetInfo->hasPropertyByName( gsDescription ) )
+ {
+ OUString sObjDesc;
+ rPropSet->getPropertyValue( gsDescription ) >>= sObjDesc;
+ if( !sObjDesc.isEmpty() )
+ {
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_SVG,
+ XML_DESC, true, false );
+ GetExport().Characters( sObjDesc );
+ }
+ }
+}
+
+void XMLTextParagraphExport::exportTextRangeSpan(
+ const css::uno::Reference< css::text::XTextRange > & rTextRange,
+ Reference< XPropertySet > const & xPropSet,
+ Reference < XPropertySetInfo > & xPropSetInfo,
+ const bool bIsUICharStyle,
+ const bool bHasAutoStyle,
+ const OUString& sStyle,
+ bool& rPrevCharIsSpace,
+ FieldmarkType& openFieldMark )
+{
+ XMLTextCharStyleNamesElementExport aCharStylesExport(
+ GetExport(),
+ bIsUICharStyle && m_aCharStyleNamesPropInfoCache.hasProperty( xPropSet, xPropSetInfo ),
+ bHasAutoStyle,
+ xPropSet,
+ gsCharStyleNames );
+
+ if ( !sStyle.isEmpty() )
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME, GetExport().EncodeStyleName( sStyle ) );
+ }
+ {
+ SvXMLElementExport aElement( GetExport(), !sStyle.isEmpty(), XML_NAMESPACE_TEXT, XML_SPAN, false, false );
+ const OUString aText( rTextRange->getString() );
+ SvXMLElementExport aElem2( GetExport(), TEXT == openFieldMark,
+ XML_NAMESPACE_TEXT, XML_TEXT_INPUT,
+ false, false );
+ exportCharacterData(aText, rPrevCharIsSpace);
+ openFieldMark = NONE;
+ }
+}
+
+void XMLTextParagraphExport::exportTextRange(
+ const Reference< XTextRange > & rTextRange,
+ bool bAutoStyles,
+ bool& rPrevCharIsSpace,
+ FieldmarkType& openFieldMark )
+{
+ Reference< XPropertySet > xPropSet( rTextRange, UNO_QUERY );
+ if ( bAutoStyles )
+ {
+ Add( XmlStyleFamily::TEXT_TEXT, xPropSet );
+ }
+ else
+ {
+ bool bIsUICharStyle = false;
+ bool bHasAutoStyle = false;
+ const OUString sStyle(
+ FindTextStyle( xPropSet, bIsUICharStyle, bHasAutoStyle ) );
+
+ Reference < XPropertySetInfo > xPropSetInfo;
+ exportTextRangeSpan( rTextRange, xPropSet, xPropSetInfo, bIsUICharStyle, bHasAutoStyle, sStyle, rPrevCharIsSpace, openFieldMark );
+ }
+}
+
+void XMLTextParagraphExport::exportCharacterData(const OUString& rText,
+ bool& rPrevCharIsSpace )
+{
+ sal_Int32 nExpStartPos = 0;
+ sal_Int32 nEndPos = rText.getLength();
+ sal_Int32 nSpaceChars = 0;
+ for( sal_Int32 nPos = 0; nPos < nEndPos; nPos++ )
+ {
+ sal_Unicode cChar = rText[nPos];
+ bool bExpCharAsText = true;
+ bool bExpCharAsElement = false;
+ bool bCurrCharIsSpace = false;
+ switch( cChar )
+ {
+ case 0x0009: // Tab
+ case 0x000A: // LF
+ // These characters are exported as text.
+ bExpCharAsElement = true;
+ bExpCharAsText = false;
+ break;
+ case 0x000D:
+ break; // legal character
+ case 0x0020: // Blank
+ if( rPrevCharIsSpace )
+ {
+ // If the previous character is a space character,
+ // too, export a special space element.
+ bExpCharAsText = false;
+ }
+ bCurrCharIsSpace = true;
+ break;
+ default:
+ if( cChar < 0x0020 )
+ {
+#ifdef DBG_UTIL
+ OSL_ENSURE( txtparae_bContainsIllegalCharacters ||
+ cChar >= 0x0020,
+ "illegal character in text content" );
+ txtparae_bContainsIllegalCharacters = true;
+#endif
+ bExpCharAsText = false;
+ }
+ break;
+ }
+
+ // If the current character is not exported as text
+ // the text that has not been exported by now has to be exported now.
+ if( nPos > nExpStartPos && !bExpCharAsText )
+ {
+ SAL_WARN_IF( 0 != nSpaceChars, "xmloff", "pending spaces" );
+ OUString sExp( rText.copy( nExpStartPos, nPos - nExpStartPos ) );
+ GetExport().Characters( sExp );
+ nExpStartPos = nPos;
+ }
+
+ // If there are spaces left that have not been exported and the
+ // current character is not a space , the pending spaces have to be
+ // exported now.
+ if( nSpaceChars > 0 && !bCurrCharIsSpace )
+ {
+ SAL_WARN_IF( nExpStartPos != nPos, "xmloff", " pending characters" );
+
+ if( nSpaceChars > 1 )
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_C,
+ OUString::number(nSpaceChars) );
+ }
+
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
+ XML_S, false, false );
+
+ nSpaceChars = 0;
+ }
+
+ // If the current character has to be exported as a special
+ // element, the element will be exported now.
+ if( bExpCharAsElement )
+ {
+ switch( cChar )
+ {
+ case 0x0009: // Tab
+ {
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
+ XML_TAB, false,
+ false );
+ }
+ break;
+ case 0x000A: // LF
+ {
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
+ XML_LINE_BREAK, false,
+ false );
+ }
+ break;
+ }
+ }
+
+ // If the current character is a space, and the previous one
+ // is a space, too, the number of pending spaces is incremented
+ // only.
+ if( bCurrCharIsSpace && rPrevCharIsSpace )
+ nSpaceChars++;
+ rPrevCharIsSpace = bCurrCharIsSpace;
+
+ // If the current character is not exported as text, the start
+ // position for text is the position behind the current position.
+ if( !bExpCharAsText )
+ {
+ SAL_WARN_IF( nExpStartPos != nPos, "xmloff", "wrong export start pos" );
+ nExpStartPos = nPos+1;
+ }
+ }
+
+ if( nExpStartPos < nEndPos )
+ {
+ SAL_WARN_IF( 0 != nSpaceChars, "xmloff", " pending spaces " );
+ OUString sExp( rText.copy( nExpStartPos, nEndPos - nExpStartPos ) );
+ GetExport().Characters( sExp );
+ }
+
+ // If there are some spaces left, they have to be exported now.
+ if( nSpaceChars > 0 )
+ {
+ if( nSpaceChars > 1 )
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_C,
+ OUString::number(nSpaceChars) );
+ }
+
+ SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT, XML_S,
+ false, false );
+ }
+}
+
+void XMLTextParagraphExport::exportTextDeclarations()
+{
+ m_pFieldExport->ExportFieldDeclarations();
+
+ // get XPropertySet from the document and ask for AutoMarkFileURL.
+ // If it exists, export the auto-mark-file element.
+ Reference<XPropertySet> xPropertySet( GetExport().GetModel(), UNO_QUERY );
+ if (!xPropertySet.is())
+ return;
+
+ OUString sUrl;
+ OUString sIndexAutoMarkFileURL(
+ "IndexAutoMarkFileURL");
+ if (!xPropertySet->getPropertySetInfo()->hasPropertyByName(
+ sIndexAutoMarkFileURL))
+ return;
+
+ xPropertySet->getPropertyValue(sIndexAutoMarkFileURL) >>= sUrl;
+ if (!sUrl.isEmpty())
+ {
+ GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_HREF,
+ GetExport().GetRelativeReference(sUrl) );
+ SvXMLElementExport aAutoMarkElement(
+ GetExport(), XML_NAMESPACE_TEXT,
+ XML_ALPHABETICAL_INDEX_AUTO_MARK_FILE,
+ true, true );
+ }
+}
+
+void XMLTextParagraphExport::exportTextDeclarations(
+ const Reference<XText> & rText )
+{
+ m_pFieldExport->ExportFieldDeclarations(rText);
+}
+
+void XMLTextParagraphExport::exportUsedDeclarations()
+{
+ m_pFieldExport->SetExportOnlyUsedFieldDeclarations( false/*bOnlyUsed*/ );
+}
+
+void XMLTextParagraphExport::exportTrackedChanges(bool bAutoStyles)
+{
+ if (nullptr != m_pRedlineExport)
+ m_pRedlineExport->ExportChangesList( bAutoStyles );
+}
+
+void XMLTextParagraphExport::exportTrackedChanges(
+ const Reference<XText> & rText,
+ bool bAutoStyle)
+{
+ if (nullptr != m_pRedlineExport)
+ m_pRedlineExport->ExportChangesList(rText, bAutoStyle);
+}
+
+void XMLTextParagraphExport::recordTrackedChangesForXText(
+ const Reference<XText> & rText )
+{
+ if (nullptr != m_pRedlineExport)
+ m_pRedlineExport->SetCurrentXText(rText);
+}
+
+void XMLTextParagraphExport::recordTrackedChangesNoXText()
+{
+ if (nullptr != m_pRedlineExport)
+ m_pRedlineExport->SetCurrentXText();
+}
+
+void XMLTextParagraphExport::exportTableAutoStyles() {}
+
+void XMLTextParagraphExport::exportTextAutoStyles()
+{
+ // tdf#135942: do not collect styles during their export: this may modify iterated containers
+ mbCollected = true;
+ exportTableAutoStyles();
+
+ GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_PARAGRAPH );
+
+ GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_TEXT );
+
+ GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_FRAME );
+
+ GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_SECTION );
+
+ GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_RUBY );
+
+ maListAutoPool.exportXML();
+}
+
+void XMLTextParagraphExport::exportRuby(
+ const Reference<XPropertySet> & rPropSet,
+ bool bAutoStyles )
+{
+ // early out: a collapsed ruby makes no sense
+ if (*o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsCollapsed)))
+ return;
+
+ // start value ?
+ bool bStart = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsStart));
+
+ if (bAutoStyles)
+ {
+ // ruby auto styles
+ if (bStart)
+ Add( XmlStyleFamily::TEXT_RUBY, rPropSet );
+ }
+ else
+ {
+ if (bStart)
+ {
+ // ruby start
+
+ // we can only start a ruby if none is open
+ assert(!m_bOpenRuby && "Can't open a ruby inside of ruby!");
+ if( m_bOpenRuby )
+ return;
+
+ // save ruby text + ruby char style
+ rPropSet->getPropertyValue(gsRubyText) >>= m_sOpenRubyText;
+ rPropSet->getPropertyValue(gsRubyCharStyleName) >>= m_sOpenRubyCharStyle;
+
+ // ruby style
+ GetExport().CheckAttrList();
+ OUString sStyleName(Find(XmlStyleFamily::TEXT_RUBY, rPropSet, ""));
+ SAL_WARN_IF(sStyleName.isEmpty(), "xmloff", "Can't find ruby style!");
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT,
+ XML_STYLE_NAME, sStyleName);
+
+ // export <text:ruby> and <text:ruby-base> start elements
+ GetExport().StartElement( XML_NAMESPACE_TEXT, XML_RUBY, false);
+ GetExport().ClearAttrList();
+ GetExport().StartElement( XML_NAMESPACE_TEXT, XML_RUBY_BASE,
+ false );
+ m_bOpenRuby = true;
+ }
+ else
+ {
+ // ruby end
+
+ // check for an open ruby
+ assert(m_bOpenRuby && "Can't close a ruby if none is open!");
+ if( !m_bOpenRuby )
+ return;
+
+ // close <text:ruby-base>
+ GetExport().EndElement(XML_NAMESPACE_TEXT, XML_RUBY_BASE,
+ false);
+
+ // write the ruby text (with char style)
+ {
+ if (!m_sOpenRubyCharStyle.isEmpty())
+ GetExport().AddAttribute(
+ XML_NAMESPACE_TEXT, XML_STYLE_NAME,
+ GetExport().EncodeStyleName( m_sOpenRubyCharStyle) );
+
+ SvXMLElementExport aRubyElement(
+ GetExport(), XML_NAMESPACE_TEXT, XML_RUBY_TEXT,
+ false, false);
+
+ GetExport().Characters(m_sOpenRubyText);
+ }
+
+ // and finally, close the ruby
+ GetExport().EndElement(XML_NAMESPACE_TEXT, XML_RUBY, false);
+ m_bOpenRuby = false;
+ }
+ }
+}
+
+void XMLTextParagraphExport::exportMeta(
+ const Reference<XPropertySet> & i_xPortion,
+ bool i_bAutoStyles, bool i_isProgress, bool & rPrevCharIsSpace)
+{
+ bool doExport(!i_bAutoStyles); // do not export element if autostyles
+ // check version >= 1.2
+ switch (GetExport().getSaneDefaultVersion()) {
+ case SvtSaveOptions::ODFSVER_011: // fall through
+ case SvtSaveOptions::ODFSVER_010: doExport = false; break;
+ default: break;
+ }
+
+ const Reference< XTextContent > xTextContent(
+ i_xPortion->getPropertyValue("InContentMetadata"), UNO_QUERY_THROW);
+ const Reference< XEnumerationAccess > xEA( xTextContent, UNO_QUERY_THROW );
+ const Reference< XEnumeration > xTextEnum( xEA->createEnumeration() );
+
+ if (doExport)
+ {
+ const Reference<rdf::XMetadatable> xMeta(xTextContent, UNO_QUERY_THROW);
+
+ // text:meta with neither xml:id nor RDFa is invalid
+ xMeta->ensureMetadataReference();
+
+ // xml:id and RDFa for RDF metadata
+ GetExport().AddAttributeXmlId(xMeta);
+ GetExport().AddAttributesRDFa(xTextContent);
+ }
+
+ SvXMLElementExport aElem( GetExport(), doExport,
+ XML_NAMESPACE_TEXT, XML_META, false, false );
+
+ // recurse to export content
+ exportTextRangeEnumeration(xTextEnum, i_bAutoStyles, i_isProgress, rPrevCharIsSpace);
+}
+
+void XMLTextParagraphExport::ExportContentControl(
+ const uno::Reference<beans::XPropertySet>& xPortion, bool bAutoStyles, bool isProgress,
+ bool& rPrevCharIsSpace)
+{
+ // Do not export the element in the autostyle case.
+ bool bExport = !bAutoStyles;
+ if (!(GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED))
+ {
+ bExport = false;
+ }
+
+ uno::Reference<text::XTextContent> xTextContent(xPortion->getPropertyValue("ContentControl"),
+ uno::UNO_QUERY_THROW);
+ uno::Reference<container::XEnumerationAccess> xEA(xTextContent, uno::UNO_QUERY_THROW);
+ uno::Reference<container::XEnumeration> xTextEnum = xEA->createEnumeration();
+
+ uno::Reference<beans::XPropertySet> xPropertySet(xTextContent, uno::UNO_QUERY_THROW);
+ if (bExport)
+ {
+ bool bShowingPlaceHolder = false;
+ xPropertySet->getPropertyValue("ShowingPlaceHolder") >>= bShowingPlaceHolder;
+ if (bShowingPlaceHolder)
+ {
+ OUStringBuffer aBuffer;
+ sax::Converter::convertBool(aBuffer, bShowingPlaceHolder);
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_SHOWING_PLACE_HOLDER,
+ aBuffer.makeStringAndClear());
+ }
+
+ bool bCheckbox = false;
+ xPropertySet->getPropertyValue("Checkbox") >>= bCheckbox;
+ if (bCheckbox)
+ {
+ OUStringBuffer aBuffer;
+ sax::Converter::convertBool(aBuffer, bCheckbox);
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_CHECKBOX, aBuffer.makeStringAndClear());
+ }
+
+ bool bChecked = false;
+ xPropertySet->getPropertyValue("Checked") >>= bChecked;
+ if (bChecked)
+ {
+ OUStringBuffer aBuffer;
+ sax::Converter::convertBool(aBuffer, bChecked);
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_CHECKED, aBuffer.makeStringAndClear());
+ }
+
+ OUString aCheckedState;
+ xPropertySet->getPropertyValue("CheckedState") >>= aCheckedState;
+ if (!aCheckedState.isEmpty())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_CHECKED_STATE, aCheckedState);
+ }
+
+ OUString aUncheckedState;
+ xPropertySet->getPropertyValue("UncheckedState") >>= aUncheckedState;
+ if (!aUncheckedState.isEmpty())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_UNCHECKED_STATE, aUncheckedState);
+ }
+
+ bool bPicture = false;
+ xPropertySet->getPropertyValue("Picture") >>= bPicture;
+ if (bPicture)
+ {
+ OUStringBuffer aBuffer;
+ sax::Converter::convertBool(aBuffer, bPicture);
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_PICTURE,
+ aBuffer.makeStringAndClear());
+ }
+
+ bool bDate = false;
+ xPropertySet->getPropertyValue("Date") >>= bDate;
+ if (bDate)
+ {
+ OUStringBuffer aBuffer;
+ sax::Converter::convertBool(aBuffer, bDate);
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_DATE, aBuffer.makeStringAndClear());
+ }
+
+ OUString aDateFormat;
+ xPropertySet->getPropertyValue("DateFormat") >>= aDateFormat;
+ if (!aDateFormat.isEmpty())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_DATE_FORMAT, aDateFormat);
+ }
+
+ OUString aDateLanguage;
+ xPropertySet->getPropertyValue("DateLanguage") >>= aDateLanguage;
+ if (!aDateLanguage.isEmpty())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_DATE_RFC_LANGUAGE_TAG, aDateLanguage);
+ }
+ OUString aCurrentDate;
+ xPropertySet->getPropertyValue("CurrentDate") >>= aCurrentDate;
+ if (!aCurrentDate.isEmpty())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_CURRENT_DATE, aCurrentDate);
+ }
+
+ bool bPlainText = false;
+ xPropertySet->getPropertyValue("PlainText") >>= bPlainText;
+ if (bPlainText)
+ {
+ OUStringBuffer aBuffer;
+ sax::Converter::convertBool(aBuffer, bPlainText);
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_PLAIN_TEXT, aBuffer.makeStringAndClear());
+ }
+
+ bool bComboBox = false;
+ xPropertySet->getPropertyValue("ComboBox") >>= bComboBox;
+ if (bComboBox)
+ {
+ OUStringBuffer aBuffer;
+ sax::Converter::convertBool(aBuffer, bComboBox);
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_COMBOBOX, aBuffer.makeStringAndClear());
+ }
+
+ bool bDropDown = false;
+ xPropertySet->getPropertyValue("DropDown") >>= bDropDown;
+ if (bDropDown)
+ {
+ OUStringBuffer aBuffer;
+ sax::Converter::convertBool(aBuffer, bDropDown);
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_DROPDOWN, aBuffer.makeStringAndClear());
+ }
+
+ OUString aAlias;
+ xPropertySet->getPropertyValue("Alias") >>= aAlias;
+ if (!aAlias.isEmpty())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_ALIAS, aAlias);
+ }
+
+ OUString aTag;
+ xPropertySet->getPropertyValue("Tag") >>= aTag;
+ if (!aTag.isEmpty())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_TAG, aTag);
+ }
+
+ sal_Int32 nId = 0;
+ xPropertySet->getPropertyValue("Id") >>= nId;
+ if (nId)
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_ID, OUString::number(nId));
+ }
+
+ sal_uInt32 nTabIndex = 0;
+ if ((xPropertySet->getPropertyValue("TabIndex") >>= nTabIndex) && nTabIndex)
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_TAB_INDEX,
+ OUString::number(nTabIndex));
+ }
+
+ OUString aLock;
+ xPropertySet->getPropertyValue("Lock") >>= aLock;
+ if (!aLock.isEmpty())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_LOCK, aLock);
+ }
+ }
+
+ SvXMLElementExport aElem(GetExport(), bExport, XML_NAMESPACE_LO_EXT, XML_CONTENT_CONTROL, false,
+ false);
+
+ if (bExport)
+ {
+ // Export list items of dropdowns.
+ uno::Sequence<beans::PropertyValues> aListItems;
+ xPropertySet->getPropertyValue("ListItems") >>= aListItems;
+ for (const auto& rListItem : aListItems)
+ {
+ comphelper::SequenceAsHashMap aMap(rListItem);
+ auto it = aMap.find("DisplayText");
+ OUString aValue;
+ if (it != aMap.end() && (it->second >>= aValue) && !aValue.isEmpty())
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_DISPLAY_TEXT, aValue);
+ }
+
+ it = aMap.find("Value");
+ if (it != aMap.end() && (it->second >>= aValue))
+ {
+ GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, XML_VALUE, aValue);
+ }
+
+ SvXMLElementExport aItem(GetExport(), bExport, XML_NAMESPACE_LO_EXT, XML_LIST_ITEM, false,
+ false);
+ }
+ }
+
+ // Recurse to export content.
+ exportTextRangeEnumeration(xTextEnum, bAutoStyles, isProgress, rPrevCharIsSpace);
+}
+
+void XMLTextParagraphExport::PreventExportOfControlsInMuteSections(
+ const Reference<XIndexAccess> & rShapes,
+ const rtl::Reference<xmloff::OFormLayerXMLExport>& xFormExport )
+{
+ // check parameters ad pre-conditions
+ if( ( ! rShapes.is() ) || ( ! xFormExport.is() ) )
+ {
+ // if we don't have shapes or a form export, there's nothing to do
+ return;
+ }
+ SAL_WARN_IF( m_pSectionExport == nullptr, "xmloff", "We need the section export." );
+
+ Reference<XEnumeration> xShapesEnum = m_pBoundFrameSets->GetShapes()->createEnumeration();
+ if(!xShapesEnum.is())
+ return;
+ while( xShapesEnum->hasMoreElements() )
+ {
+ // now we need to check
+ // 1) if this is a control shape, and
+ // 2) if it's in a mute section
+ // if both answers are 'yes', notify the form layer export
+
+ // we join accessing the shape and testing for control
+ Reference<XControlShape> xControlShape(xShapesEnum->nextElement(), UNO_QUERY);
+ if( xControlShape.is() )
+ {
+ // Reference<XPropertySet> xPropSet( xControlShape, UNO_QUERY );
+ // Reference<XTextContent> xTextContent;
+ // xPropSet->getPropertyValue("TextRange") >>= xTextContent;
+
+ Reference<XTextContent> xTextContent( xControlShape, UNO_QUERY );
+ if( xTextContent.is() )
+ {
+ if( m_pSectionExport->IsMuteSection( xTextContent, false ) )
+ {
+ // Ah, we've found a shape that
+ // 1) is a control shape
+ // 2) is anchored in a mute section
+ // so: don't export it!
+ xFormExport->excludeFromExport(
+ xControlShape->getControl() );
+ }
+ // else: not in mute section -> should be exported -> nothing
+ // to do
+ }
+ // else: no anchor -> ignore
+ }
+ // else: no control shape -> nothing to do
+ }
+}
+
+void XMLTextParagraphExport::PushNewTextListsHelper()
+{
+ maTextListsHelperStack.emplace_back( new XMLTextListsHelper() );
+ mpTextListsHelper = maTextListsHelperStack.back().get();
+}
+
+void XMLTextParagraphExport::PopTextListsHelper()
+{
+ mpTextListsHelper = nullptr;
+ maTextListsHelperStack.pop_back();
+ if ( !maTextListsHelperStack.empty() )
+ {
+ mpTextListsHelper = maTextListsHelperStack.back().get();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/txtparai.cxx b/xmloff/source/text/txtparai.cxx
new file mode 100644
index 0000000000..c777fa0c29
--- /dev/null
+++ b/xmloff/source/text/txtparai.cxx
@@ -0,0 +1,2147 @@
+/* -*- 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 <xmloff/unointerfacetouniqueidentifiermapper.hxx>
+
+#include <memory>
+#include <string_view>
+#include <vector>
+
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/text/XTextFrame.hpp>
+#include <com/sun/star/text/XTextCursor.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/text/ControlCharacter.hpp>
+#include <com/sun/star/text/XTextRangeCompare.hpp>
+#include <com/sun/star/container/XIndexReplace.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+#include <com/sun/star/rdf/XMetadatable.hpp>
+
+#include <sax/tools/converter.hxx>
+
+#include <xmloff/prstylei.hxx>
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/txtimp.hxx>
+#include "txtparai.hxx"
+#include <txtfldi.hxx>
+#include "XMLFootnoteImportContext.hxx"
+#include "XMLTextMarkImportContext.hxx"
+#include "XMLTextFrameContext.hxx"
+#include <xmloff/XMLCharContext.hxx>
+#include "XMLTextFrameHyperlinkContext.hxx"
+#include <xmloff/XMLEventsImportContext.hxx>
+#include "XMLChangeImportContext.hxx"
+#include <txtlists.hxx>
+
+#include "txtparaimphint.hxx"
+#include "xmllinebreakcontext.hxx"
+#include "xmlcontentcontrolcontext.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::drawing;
+using namespace ::com::sun::star::beans;
+using namespace ::xmloff::token;
+using ::com::sun::star::container::XEnumerationAccess;
+using ::com::sun::star::container::XEnumeration;
+
+class XMLHints_Impl
+{
+private:
+
+ std::vector<std::unique_ptr<XMLHint_Impl>> m_Hints;
+ std::unordered_map<OUString, XMLIndexMarkHint_Impl*> m_IndexHintsById;
+ uno::Reference<uno::XInterface> m_xCrossRefHeadingBookmark;
+
+public:
+ void push_back(std::unique_ptr<XMLHint_Impl> pHint)
+ {
+ m_Hints.push_back(std::move(pHint));
+ }
+
+ void push_back(std::unique_ptr<XMLIndexMarkHint_Impl> pHint)
+ {
+ m_IndexHintsById.emplace(pHint->GetID(), pHint.get());
+ m_Hints.push_back(std::move(pHint));
+ }
+
+ std::vector<std::unique_ptr<XMLHint_Impl>> const& GetHints() const
+ {
+ return m_Hints;
+ }
+
+ XMLIndexMarkHint_Impl* GetIndexHintById(const OUString& sID)
+ {
+ auto it = m_IndexHintsById.find(sID);
+ return it == m_IndexHintsById.end() ? nullptr : it->second;
+ }
+
+ uno::Reference<uno::XInterface> & GetCrossRefHeadingBookmark()
+ {
+ return m_xCrossRefHeadingBookmark;
+ }
+};
+
+
+XMLCharContext::XMLCharContext(
+ SvXMLImport& rImport,
+ const Reference< xml::sax::XFastAttributeList > & xAttrList,
+ sal_Unicode c,
+ bool bCount ) :
+ SvXMLImportContext( rImport )
+ ,m_nControl(0)
+ ,m_nCount(1)
+ ,m_c(c)
+{
+ if( !bCount )
+ return;
+
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
+ {
+ if( aIter.getToken() == XML_ELEMENT(TEXT, XML_C) )
+ {
+ sal_Int32 nTmp = aIter.toInt32();
+ if( nTmp > 0 )
+ {
+ if( nTmp > SAL_MAX_UINT16 )
+ m_nCount = SAL_MAX_UINT16;
+ else
+ m_nCount = static_cast<sal_uInt16>(nTmp);
+ }
+ }
+ else
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+}
+
+XMLCharContext::XMLCharContext(
+ SvXMLImport& rImp,
+ sal_Int16 nControl ) :
+ SvXMLImportContext( rImp )
+ ,m_nControl(nControl)
+ ,m_nCount(0)
+ ,m_c(0)
+{
+}
+
+XMLCharContext::~XMLCharContext()
+{
+}
+void XMLCharContext::endFastElement(sal_Int32 )
+{
+ if ( !m_nCount )
+ InsertControlCharacter( m_nControl );
+ else
+ {
+ if( 1U == m_nCount )
+ {
+ OUString sBuff( &m_c, 1 );
+ InsertString(sBuff);
+ }
+ else
+ {
+ OUStringBuffer sBuff(static_cast<int>(m_nCount));
+ while( m_nCount-- )
+ sBuff.append( &m_c, 1 );
+
+ InsertString(sBuff.makeStringAndClear() );
+ }
+ }
+}
+void XMLCharContext::InsertControlCharacter(sal_Int16 _nControl)
+{
+ GetImport().GetTextImport()->InsertControlCharacter( _nControl );
+}
+void XMLCharContext::InsertString(const OUString& _sString)
+{
+ GetImport().GetTextImport()->InsertString( _sString );
+}
+
+namespace {
+
+/** import start of reference (<text:reference-start>) */
+class XMLStartReferenceContext_Impl : public SvXMLImportContext
+{
+public:
+
+ // Do everything in constructor. Well ...
+ XMLStartReferenceContext_Impl (
+ SvXMLImport& rImport,
+ XMLHints_Impl& rHints,
+ const Reference<xml::sax::XFastAttributeList> & xAttrList);
+
+ static bool FindName(
+ const Reference<xml::sax::XFastAttributeList> & xAttrList,
+ OUString& rName);
+};
+
+}
+
+XMLStartReferenceContext_Impl::XMLStartReferenceContext_Impl(
+ SvXMLImport& rImport,
+ XMLHints_Impl& rHints,
+ const Reference<xml::sax::XFastAttributeList> & xAttrList) :
+ SvXMLImportContext(rImport)
+{
+ OUString sName;
+
+ if (FindName(xAttrList, sName))
+ {
+ std::unique_ptr<XMLHint_Impl> pHint(new XMLReferenceHint_Impl(
+ sName, rImport.GetTextImport()->GetCursor()->getStart()));
+
+ // degenerates to point reference, if no end is found!
+ pHint->SetEnd(rImport.GetTextImport()->GetCursor()->getStart() );
+
+ rHints.push_back(std::move(pHint));
+ }
+}
+
+bool XMLStartReferenceContext_Impl::FindName(
+ const Reference<xml::sax::XFastAttributeList> & xAttrList,
+ OUString& rName)
+{
+ bool bNameOK( false );
+
+ // find name attribute first
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ if ( aIter.getToken() == XML_ELEMENT(TEXT, XML_NAME) )
+ {
+ rName = aIter.toString();
+ bNameOK = true;
+ break;
+ }
+ }
+
+ return bNameOK;
+}
+
+namespace {
+
+/** import end of reference (<text:reference-end>) */
+class XMLEndReferenceContext_Impl : public SvXMLImportContext
+{
+public:
+
+ // Do everything in constructor. Well ...
+ XMLEndReferenceContext_Impl(
+ SvXMLImport& rImport,
+ const XMLHints_Impl& rHints,
+ const Reference<xml::sax::XFastAttributeList> & xAttrList);
+};
+
+}
+
+XMLEndReferenceContext_Impl::XMLEndReferenceContext_Impl(
+ SvXMLImport& rImport,
+ const XMLHints_Impl& rHints,
+ const Reference<xml::sax::XFastAttributeList> & xAttrList) :
+ SvXMLImportContext(rImport)
+{
+ OUString sName;
+
+ // borrow from XMLStartReferenceContext_Impl
+ if (!XMLStartReferenceContext_Impl::FindName(xAttrList, sName))
+ return;
+
+ // search for reference start
+ for (const auto& rHintPtr : rHints.GetHints())
+ {
+ XMLHint_Impl *const pHint = rHintPtr.get();
+ if ( pHint->IsReference() &&
+ sName == static_cast<XMLReferenceHint_Impl *>(pHint)->GetRefName() )
+ {
+ // set end and stop searching
+ pHint->SetEnd(GetImport().GetTextImport()->
+ GetCursor()->getStart() );
+ break;
+ }
+ }
+ // else: no start (in this paragraph) -> ignore
+}
+
+namespace {
+
+class XMLImpHyperlinkContext_Impl : public SvXMLImportContext
+{
+ XMLHints_Impl& m_rHints;
+ XMLHyperlinkHint_Impl *mpHint;
+
+ bool& mrbIgnoreLeadingSpace;
+
+public:
+
+
+ XMLImpHyperlinkContext_Impl(
+ SvXMLImport& rImport,
+ sal_Int32 nElement,
+ const Reference< xml::sax::XFastAttributeList > & xAttrList,
+ XMLHints_Impl& rHints,
+ bool& rIgnLeadSpace );
+
+ virtual ~XMLImpHyperlinkContext_Impl() override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+
+ virtual void SAL_CALL characters( const OUString& rChars ) override;
+};
+
+}
+
+XMLImpHyperlinkContext_Impl::XMLImpHyperlinkContext_Impl(
+ SvXMLImport& rImport,
+ sal_Int32 /*nElement*/,
+ const Reference< xml::sax::XFastAttributeList > & xAttrList,
+ XMLHints_Impl& rHints,
+ bool& rIgnLeadSpace )
+ : SvXMLImportContext( rImport )
+ , m_rHints( rHints )
+ , mpHint( new XMLHyperlinkHint_Impl( GetImport().GetTextImport()->GetCursorAsRange()->getStart() ) )
+ , mrbIgnoreLeadingSpace( rIgnLeadSpace )
+{
+ OUString sShow;
+
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ OUString sValue = aIter.toString();
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(XLINK, XML_HREF):
+ mpHint->SetHRef( GetImport().GetAbsoluteReference( sValue ) );
+ break;
+ case XML_ELEMENT(OFFICE, XML_NAME):
+ mpHint->SetName( sValue );
+ break;
+ case XML_ELEMENT(OFFICE, XML_TARGET_FRAME_NAME):
+ mpHint->SetTargetFrameName( sValue );
+ break;
+ case XML_ELEMENT(XLINK, XML_SHOW):
+ sShow = sValue;
+ break;
+ case XML_ELEMENT(TEXT, XML_STYLE_NAME):
+ mpHint->SetStyleName( sValue );
+ break;
+ case XML_ELEMENT(TEXT, XML_VISITED_STYLE_NAME):
+ mpHint->SetVisitedStyleName( sValue );
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+
+ if( !sShow.isEmpty() && mpHint->GetTargetFrameName().isEmpty() )
+ {
+ if( IsXMLToken( sShow, XML_NEW ) )
+ mpHint->SetTargetFrameName(
+ "_blank" );
+ else if( IsXMLToken( sShow, XML_REPLACE ) )
+ mpHint->SetTargetFrameName(
+ "_self" );
+ }
+
+ if ( mpHint->GetHRef().isEmpty() )
+ {
+ // hyperlink without a URL is not imported.
+ delete mpHint;
+ mpHint = nullptr;
+ }
+ else
+ {
+ m_rHints.push_back(std::unique_ptr<XMLHyperlinkHint_Impl>(mpHint));
+ }
+}
+
+XMLImpHyperlinkContext_Impl::~XMLImpHyperlinkContext_Impl()
+{
+ if (mpHint)
+ mpHint->SetEnd( GetImport().GetTextImport()
+ ->GetCursorAsRange()->getStart() );
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLImpHyperlinkContext_Impl::createFastChildContext(
+ sal_Int32 nElement,
+ const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
+{
+ if ( nElement == XML_ELEMENT(OFFICE, XML_EVENT_LISTENERS) )
+ {
+ XMLEventsImportContext* pCtxt = new XMLEventsImportContext(GetImport());
+ if (mpHint)
+ mpHint->SetEventsContext(pCtxt);
+ return pCtxt;
+ }
+ else
+ {
+ return XMLImpSpanContext_Impl::CreateSpanContext(
+ GetImport(), nElement, xAttrList,
+ m_rHints, mrbIgnoreLeadingSpace );
+ }
+}
+
+void XMLImpHyperlinkContext_Impl::characters( const OUString& rChars )
+{
+ GetImport().GetTextImport()->InsertString( rChars, mrbIgnoreLeadingSpace );
+}
+
+namespace {
+
+class XMLImpRubyBaseContext_Impl : public SvXMLImportContext
+{
+ XMLHints_Impl& m_rHints;
+
+ bool& rIgnoreLeadingSpace;
+
+public:
+
+
+ XMLImpRubyBaseContext_Impl(
+ SvXMLImport& rImport,
+ sal_Int32 nElement,
+ const Reference< xml::sax::XFastAttributeList > & xAttrList,
+ XMLHints_Impl& rHints,
+ bool& rIgnLeadSpace );
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+
+ virtual void SAL_CALL characters( const OUString& rChars ) override;
+};
+
+}
+
+XMLImpRubyBaseContext_Impl::XMLImpRubyBaseContext_Impl(
+ SvXMLImport& rImport,
+ sal_Int32 /*nElement*/,
+ const Reference< xml::sax::XFastAttributeList > &,
+ XMLHints_Impl& rHints,
+ bool& rIgnLeadSpace )
+ : SvXMLImportContext( rImport )
+ , m_rHints( rHints )
+ , rIgnoreLeadingSpace( rIgnLeadSpace )
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLImpRubyBaseContext_Impl::createFastChildContext(
+ sal_Int32 nElement,
+ const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
+{
+ return XMLImpSpanContext_Impl::CreateSpanContext( GetImport(), nElement, xAttrList,
+ m_rHints, rIgnoreLeadingSpace );
+}
+
+void XMLImpRubyBaseContext_Impl::characters( const OUString& rChars )
+{
+ GetImport().GetTextImport()->InsertString( rChars, rIgnoreLeadingSpace );
+}
+
+namespace {
+
+class XMLImpRubyContext_Impl : public SvXMLImportContext
+{
+ XMLHints_Impl& m_rHints;
+
+ bool& rIgnoreLeadingSpace;
+
+ Reference < XTextRange > m_xStart;
+ OUString m_sStyleName;
+ OUString m_sTextStyleName;
+ OUString m_sText;
+
+public:
+
+
+ XMLImpRubyContext_Impl(
+ SvXMLImport& rImport,
+ sal_Int32 nElement,
+ const Reference< xml::sax::XFastAttributeList > & xAttrList,
+ XMLHints_Impl& rHints,
+ bool& rIgnLeadSpace );
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+
+ void SetTextStyleName( const OUString& s ) { m_sTextStyleName = s; }
+ void AppendText( std::u16string_view s ) { m_sText += s; }
+};
+
+class XMLImpRubyTextContext_Impl : public SvXMLImportContext
+{
+ XMLImpRubyContext_Impl & m_rRubyContext;
+
+public:
+
+
+ XMLImpRubyTextContext_Impl(
+ SvXMLImport& rImport,
+ sal_Int32 nElement,
+ const Reference< xml::sax::XFastAttributeList > & xAttrList,
+ XMLImpRubyContext_Impl & rParent );
+
+ virtual void SAL_CALL characters( const OUString& rChars ) override;
+};
+
+}
+
+XMLImpRubyTextContext_Impl::XMLImpRubyTextContext_Impl(
+ SvXMLImport& rImport,
+ sal_Int32 /*nElement*/,
+ const Reference< xml::sax::XFastAttributeList > & xAttrList,
+ XMLImpRubyContext_Impl & rParent )
+ : SvXMLImportContext( rImport )
+ , m_rRubyContext( rParent )
+{
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ if( aIter.getToken() == XML_ELEMENT(TEXT, XML_STYLE_NAME) )
+ {
+ m_rRubyContext.SetTextStyleName( aIter.toString() );
+ break;
+ }
+ }
+}
+
+void XMLImpRubyTextContext_Impl::characters( const OUString& rChars )
+{
+ m_rRubyContext.AppendText( rChars );
+}
+
+
+XMLImpRubyContext_Impl::XMLImpRubyContext_Impl(
+ SvXMLImport& rImport,
+ sal_Int32 /*nElement*/,
+ const Reference< xml::sax::XFastAttributeList > & xAttrList,
+ XMLHints_Impl& rHints,
+ bool& rIgnLeadSpace )
+ : SvXMLImportContext( rImport )
+ , m_rHints( rHints )
+ , rIgnoreLeadingSpace( rIgnLeadSpace )
+ , m_xStart( GetImport().GetTextImport()->GetCursorAsRange()->getStart() )
+{
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ if( aIter.getToken() == XML_ELEMENT(TEXT, XML_STYLE_NAME) )
+ {
+ m_sStyleName = aIter.toString();
+ break;
+ }
+ }
+}
+
+void XMLImpRubyContext_Impl::endFastElement(sal_Int32 )
+{
+ const rtl::Reference < XMLTextImportHelper > xTextImport(
+ GetImport().GetTextImport());
+ const Reference < XTextCursor > xAttrCursor(
+ xTextImport->GetText()->createTextCursorByRange( m_xStart ));
+ if (!xAttrCursor.is())
+ {
+ SAL_WARN("xmloff.text", "cannot insert ruby");
+ return;
+ }
+ xAttrCursor->gotoRange(xTextImport->GetCursorAsRange()->getStart(),
+ true);
+ xTextImport->SetRuby( GetImport(), xAttrCursor,
+ m_sStyleName, m_sTextStyleName, m_sText );
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLImpRubyContext_Impl::createFastChildContext(
+ sal_Int32 nElement,
+ const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
+{
+ if( nElement == XML_ELEMENT(TEXT, XML_RUBY_BASE) )
+ return new XMLImpRubyBaseContext_Impl( GetImport(), nElement,
+ xAttrList,
+ m_rHints,
+ rIgnoreLeadingSpace );
+ else if( nElement == XML_ELEMENT(TEXT, XML_RUBY_TEXT) )
+ return new XMLImpRubyTextContext_Impl( GetImport(), nElement,
+ xAttrList,
+ *this );
+ else
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+
+ return nullptr;
+}
+
+namespace {
+
+/** for text:meta and text:meta-field
+ */
+class XMLMetaImportContextBase : public SvXMLImportContext
+{
+ XMLHints_Impl& m_rHints;
+
+ bool& m_rIgnoreLeadingSpace;
+
+ /// start position
+ Reference<XTextRange> m_xStart;
+
+protected:
+ OUString m_XmlId;
+
+public:
+
+ XMLMetaImportContextBase(
+ SvXMLImport& i_rImport,
+ const sal_Int32 nElement,
+ XMLHints_Impl& i_rHints,
+ bool & i_rIgnoreLeadingSpace );
+
+ virtual void SAL_CALL startFastElement(
+ sal_Int32 nElement,
+ const Reference<xml::sax::XFastAttributeList> & i_xAttrList) override;
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+
+ virtual void SAL_CALL characters( const OUString& i_rChars ) override;
+
+ virtual void ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter);
+
+ virtual void InsertMeta(const Reference<XTextRange> & i_xInsertionRange)
+ = 0;
+};
+
+}
+
+XMLMetaImportContextBase::XMLMetaImportContextBase(
+ SvXMLImport& i_rImport,
+ const sal_Int32 /*i_nElement*/,
+ XMLHints_Impl& i_rHints,
+ bool & i_rIgnoreLeadingSpace )
+ : SvXMLImportContext( i_rImport )
+ , m_rHints( i_rHints )
+ , m_rIgnoreLeadingSpace( i_rIgnoreLeadingSpace )
+ , m_xStart( GetImport().GetTextImport()->GetCursorAsRange()->getStart() )
+{
+}
+
+void XMLMetaImportContextBase::startFastElement(
+ sal_Int32 /*nElement*/,
+ const Reference<xml::sax::XFastAttributeList> & xAttrList)
+{
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
+ ProcessAttribute(aIter);
+}
+
+void XMLMetaImportContextBase::endFastElement(sal_Int32 )
+{
+ SAL_WARN_IF(!m_xStart.is(), "xmloff.text", "no mxStart?");
+ if (!m_xStart.is()) return;
+
+ const Reference<XTextRange> xEndRange(
+ GetImport().GetTextImport()->GetCursorAsRange()->getStart() );
+
+ // create range for insertion
+ const Reference<XTextCursor> xInsertionCursor(
+ GetImport().GetTextImport()->GetText()->createTextCursorByRange(
+ xEndRange) );
+ xInsertionCursor->gotoRange(m_xStart, true);
+
+ InsertMeta(xInsertionCursor);
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLMetaImportContextBase::createFastChildContext(
+ sal_Int32 nElement,
+ const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
+{
+ return XMLImpSpanContext_Impl::CreateSpanContext( GetImport(), nElement,
+ xAttrList, m_rHints, m_rIgnoreLeadingSpace );
+}
+
+void XMLMetaImportContextBase::characters( const OUString& i_rChars )
+{
+ GetImport().GetTextImport()->InsertString(i_rChars, m_rIgnoreLeadingSpace);
+}
+
+void XMLMetaImportContextBase::ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)
+{
+ if ( aIter.getToken() == XML_ELEMENT(XML, XML_ID) )
+ m_XmlId = aIter.toString();
+ else
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+}
+
+namespace {
+
+/** text:meta */
+class XMLMetaImportContext : public XMLMetaImportContextBase
+{
+ // RDFa
+ bool m_bHaveAbout;
+ OUString m_sAbout;
+ OUString m_sProperty;
+ OUString m_sContent;
+ OUString m_sDatatype;
+
+public:
+
+ XMLMetaImportContext(
+ SvXMLImport& i_rImport,
+ sal_Int32 nElement,
+ XMLHints_Impl& i_rHints,
+ bool & i_rIgnoreLeadingSpace );
+
+ virtual void ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter) override;
+
+ virtual void InsertMeta(const Reference<XTextRange> & i_xInsertionRange) override;
+};
+
+}
+
+XMLMetaImportContext::XMLMetaImportContext(
+ SvXMLImport& i_rImport,
+ sal_Int32 nElement,
+ XMLHints_Impl& i_rHints,
+ bool & i_rIgnoreLeadingSpace )
+ : XMLMetaImportContextBase( i_rImport, nElement,
+ i_rHints, i_rIgnoreLeadingSpace )
+ , m_bHaveAbout(false)
+{
+}
+
+void XMLMetaImportContext::ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)
+{
+ switch (aIter.getToken())
+ {
+ // RDFa
+ case XML_ELEMENT(XHTML, XML_ABOUT):
+ m_sAbout = aIter.toString();
+ m_bHaveAbout = true;
+ break;
+ case XML_ELEMENT(XHTML, XML_PROPERTY):
+ m_sProperty = aIter.toString();
+ break;
+ case XML_ELEMENT(XHTML, XML_CONTENT):
+ m_sContent = aIter.toString();
+ break;
+ case XML_ELEMENT(XHTML, XML_DATATYPE):
+ m_sDatatype = aIter.toString();
+ break;
+ default:
+ XMLMetaImportContextBase::ProcessAttribute(aIter);
+ }
+}
+
+void XMLMetaImportContext::InsertMeta(
+ const Reference<XTextRange> & i_xInsertionRange)
+{
+ SAL_WARN_IF(m_bHaveAbout == m_sProperty.isEmpty(), "xmloff.text", "XMLMetaImportContext::InsertMeta: invalid RDFa?");
+ if (!m_XmlId.isEmpty() || (m_bHaveAbout && !m_sProperty.isEmpty()))
+ {
+ // insert mark
+ const uno::Reference<rdf::XMetadatable> xMeta(
+ XMLTextMarkImportContext::CreateAndInsertMark(
+ GetImport(),
+ "com.sun.star.text.InContentMetadata",
+ OUString(),
+ i_xInsertionRange, m_XmlId),
+ uno::UNO_QUERY);
+ SAL_WARN_IF(!xMeta.is(), "xmloff.text", "cannot insert Meta?");
+
+ if (xMeta.is() && m_bHaveAbout)
+ {
+ GetImport().AddRDFa(xMeta,
+ m_sAbout, m_sProperty, m_sContent, m_sDatatype);
+ }
+ }
+ else
+ {
+ SAL_INFO("xmloff.text", "invalid <text:meta>: no xml:id, no valid RDFa");
+ }
+}
+
+namespace {
+
+/** text:meta-field */
+class XMLMetaFieldImportContext : public XMLMetaImportContextBase
+{
+ OUString m_DataStyleName;
+
+public:
+
+ XMLMetaFieldImportContext(
+ SvXMLImport& i_rImport,
+ sal_Int32 nElement,
+ XMLHints_Impl& i_rHints,
+ bool & i_rIgnoreLeadingSpace );
+
+ virtual void ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter) override;
+
+ virtual void InsertMeta(const Reference<XTextRange> & i_xInsertionRange) override;
+};
+
+}
+
+XMLMetaFieldImportContext::XMLMetaFieldImportContext(
+ SvXMLImport& i_rImport,
+ sal_Int32 nElement,
+ XMLHints_Impl& i_rHints,
+ bool & i_rIgnoreLeadingSpace )
+ : XMLMetaImportContextBase( i_rImport, nElement,
+ i_rHints, i_rIgnoreLeadingSpace )
+{
+}
+
+void XMLMetaFieldImportContext::ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)
+{
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(STYLE, XML_DATA_STYLE_NAME):
+ m_DataStyleName = aIter.toString();
+ break;
+ default:
+ XMLMetaImportContextBase::ProcessAttribute(aIter);
+ }
+}
+
+void XMLMetaFieldImportContext::InsertMeta(
+ const Reference<XTextRange> & i_xInsertionRange)
+{
+ if (!m_XmlId.isEmpty()) // valid?
+ {
+ // insert mark
+ const Reference<XPropertySet> xPropertySet(
+ XMLTextMarkImportContext::CreateAndInsertMark(
+ GetImport(),
+ "com.sun.star.text.textfield.MetadataField",
+ OUString(),
+ i_xInsertionRange, m_XmlId),
+ UNO_QUERY);
+ SAL_WARN_IF(!xPropertySet.is(), "xmloff.text", "cannot insert MetaField?");
+ if (!xPropertySet.is()) return;
+
+ if (!m_DataStyleName.isEmpty())
+ {
+ bool isDefaultLanguage(true);
+
+ const sal_Int32 nKey( GetImport().GetTextImport()->GetDataStyleKey(
+ m_DataStyleName, & isDefaultLanguage) );
+
+ if (-1 != nKey)
+ {
+ OUString sPropertyIsFixedLanguage("IsFixedLanguage");
+ xPropertySet->setPropertyValue("NumberFormat", Any(nKey));
+ if ( xPropertySet->getPropertySetInfo()->
+ hasPropertyByName( sPropertyIsFixedLanguage ) )
+ {
+ xPropertySet->setPropertyValue( sPropertyIsFixedLanguage,
+ Any(!isDefaultLanguage) );
+ }
+ }
+ }
+ }
+ else
+ {
+ SAL_INFO("xmloff.text", "invalid <text:meta-field>: no xml:id");
+ }
+}
+
+namespace {
+
+/**
+ * Process index marks.
+ *
+ * All *-mark-end index marks should instantiate *this* class (because
+ * it doesn't process attributes other than ID), while the *-mark and
+ * *-mark-start classes should instantiate the appropriate subclasses.
+ */
+class XMLIndexMarkImportContext_Impl : public SvXMLImportContext
+{
+ XMLHints_Impl& m_rHints;
+ OUString sID;
+
+public:
+
+ XMLIndexMarkImportContext_Impl(
+ SvXMLImport& rImport,
+ XMLHints_Impl& rHints);
+
+ void SAL_CALL startFastElement(sal_Int32 nElement, const Reference<xml::sax::XFastAttributeList> & xAttrList) override;
+
+protected:
+
+ /// process all attributes
+ void ProcessAttributes(sal_Int32 nElement, const Reference<xml::sax::XFastAttributeList> & xAttrList,
+ Reference<beans::XPropertySet>& rPropSet);
+
+ /**
+ * All marks can be created immediately. Since we don't care about
+ * the element content, ProcessAttribute should set the properties
+ * immediately.
+ *
+ * This method tolerates an empty PropertySet; subclasses however
+ * are not expected to.
+ */
+ virtual void ProcessAttribute(sal_Int32 nElement,
+ const sax_fastparser::FastAttributeList::FastAttributeIter & aIter,
+ Reference<beans::XPropertySet>& rPropSet);
+
+ static void GetServiceName(OUString& sServiceName,
+ sal_Int32 nElement);
+
+ bool CreateMark(Reference<beans::XPropertySet>& rPropSet,
+ const OUString& rServiceName);
+};
+
+}
+
+XMLIndexMarkImportContext_Impl::XMLIndexMarkImportContext_Impl(
+ SvXMLImport& rImport,
+ XMLHints_Impl& rHints)
+ : SvXMLImportContext(rImport)
+ , m_rHints(rHints)
+{
+}
+
+void XMLIndexMarkImportContext_Impl::startFastElement(
+ sal_Int32 nElement,
+ const Reference<xml::sax::XFastAttributeList> & xAttrList)
+{
+ // get Cursor position (needed for all cases)
+ Reference<XTextRange> xPos(
+ GetImport().GetTextImport()->GetCursor()->getStart());
+ Reference<beans::XPropertySet> xMark;
+
+ switch (nElement)
+ {
+ case XML_ELEMENT(TEXT, XML_TOC_MARK):
+ case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK):
+ case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK):
+ {
+ // single mark: create mark and insert
+ OUString sService;
+ GetServiceName(sService, nElement);
+ if (CreateMark(xMark, sService))
+ {
+ ProcessAttributes(nElement, xAttrList, xMark);
+ m_rHints.push_back(
+ std::make_unique<XMLIndexMarkHint_Impl>(xMark, xPos));
+ }
+ // else: can't create mark -> ignore
+ break;
+ }
+
+ case XML_ELEMENT(TEXT, XML_TOC_MARK_START):
+ case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_START):
+ case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_START):
+ {
+ // start: create mark and insert (if ID is found)
+ OUString sService;
+ GetServiceName(sService, nElement);
+ if (CreateMark(xMark, sService))
+ {
+ ProcessAttributes(nElement, xAttrList, xMark);
+ if (!sID.isEmpty())
+ {
+ // process only if we find an ID
+ m_rHints.push_back(
+ std::make_unique<XMLIndexMarkHint_Impl>(xMark, xPos, sID));
+ }
+ // else: no ID -> we'll never find the end -> ignore
+ }
+ // else: can't create mark -> ignore
+ break;
+ }
+
+ case XML_ELEMENT(TEXT, XML_TOC_MARK_END):
+ case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_END):
+ case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_END):
+ {
+ // end: search for ID and set end of mark
+
+ // call process attributes with empty XPropertySet:
+ ProcessAttributes(nElement, xAttrList, xMark);
+ if (!sID.isEmpty())
+ {
+ // if we have an ID, find the hint and set the end position
+ XMLIndexMarkHint_Impl *const pHint = m_rHints.GetIndexHintById(sID);
+ if (pHint)
+ // set end and stop searching
+ pHint->SetEnd(xPos);
+ }
+ // else: no ID -> ignore
+ break;
+ }
+
+ default:
+ SAL_WARN("xmloff.text", "unknown index mark type!");
+ break;
+ }
+}
+
+void XMLIndexMarkImportContext_Impl::ProcessAttributes(
+ sal_Int32 nElement,
+ const Reference<xml::sax::XFastAttributeList> & xAttrList,
+ Reference<beans::XPropertySet>& rPropSet)
+{
+ // process attributes
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
+ {
+ ProcessAttribute(nElement, aIter, rPropSet);
+ }
+}
+
+void XMLIndexMarkImportContext_Impl::ProcessAttribute(
+ sal_Int32 nElement,
+ const sax_fastparser::FastAttributeList::FastAttributeIter & aIter,
+ Reference<beans::XPropertySet>& rPropSet)
+{
+ // we only know ID + string-value attribute;
+ // (former: marks, latter: -start + -end-marks)
+ // the remainder is handled in sub-classes
+ switch (nElement)
+ {
+ case XML_ELEMENT(TEXT, XML_TOC_MARK):
+ case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK):
+ case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK):
+ if ( aIter.getToken() == XML_ELEMENT(TEXT, XML_STRING_VALUE) )
+ {
+ rPropSet->setPropertyValue("AlternativeText", uno::Any(aIter.toString()));
+ }
+ // else: ignore!
+ break;
+
+ case XML_ELEMENT(TEXT, XML_TOC_MARK_START):
+ case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_START):
+ case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_START):
+ case XML_ELEMENT(TEXT, XML_TOC_MARK_END):
+ case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_END):
+ case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_END):
+ if ( aIter.getToken() == XML_ELEMENT(TEXT, XML_ID) )
+ {
+ sID = aIter.toString();
+ }
+ // else: ignore
+ break;
+
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ break;
+ }
+}
+
+
+void XMLIndexMarkImportContext_Impl::GetServiceName(
+ OUString& sServiceName,
+ sal_Int32 nElement)
+{
+ switch (nElement)
+ {
+ case XML_ELEMENT(TEXT, XML_TOC_MARK):
+ case XML_ELEMENT(TEXT, XML_TOC_MARK_START):
+ case XML_ELEMENT(TEXT, XML_TOC_MARK_END):
+ {
+ sServiceName = "com.sun.star.text.ContentIndexMark";
+ break;
+ }
+
+ case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK):
+ case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_START):
+ case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_END):
+ {
+ sServiceName = "com.sun.star.text.UserIndexMark";
+ break;
+ }
+
+ case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK):
+ case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_START):
+ case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_END):
+ {
+ sServiceName = "com.sun.star.text.DocumentIndexMark";
+ break;
+ }
+
+ default:
+ {
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ sServiceName.clear();
+ break;
+ }
+ }
+}
+
+bool XMLIndexMarkImportContext_Impl::CreateMark(
+ Reference<beans::XPropertySet>& rPropSet,
+ const OUString& rServiceName)
+{
+ Reference<lang::XMultiServiceFactory>
+ xFactory(GetImport().GetModel(), UNO_QUERY);
+
+ if( xFactory.is() )
+ {
+ Reference<beans::XPropertySet> xPropSet( xFactory->createInstance(rServiceName), UNO_QUERY );
+ if (xPropSet.is())
+ rPropSet = xPropSet;
+ return true;
+ }
+
+ return false;
+}
+
+namespace {
+
+class XMLTOCMarkImportContext_Impl : public XMLIndexMarkImportContext_Impl
+{
+public:
+
+ XMLTOCMarkImportContext_Impl(
+ SvXMLImport& rImport,
+ XMLHints_Impl& rHints);
+
+protected:
+
+ /** process outline level */
+ virtual void ProcessAttribute(sal_Int32 nElement,
+ const sax_fastparser::FastAttributeList::FastAttributeIter & aIter,
+ Reference<beans::XPropertySet>& rPropSet) override;
+};
+
+}
+
+XMLTOCMarkImportContext_Impl::XMLTOCMarkImportContext_Impl(
+ SvXMLImport& rImport, XMLHints_Impl& rHints) :
+ XMLIndexMarkImportContext_Impl(rImport, rHints)
+{
+}
+
+void XMLTOCMarkImportContext_Impl::ProcessAttribute(
+ sal_Int32 nElement,
+ const sax_fastparser::FastAttributeList::FastAttributeIter & aIter,
+ Reference<beans::XPropertySet>& rPropSet)
+{
+ SAL_WARN_IF(!rPropSet.is(), "xmloff.text", "need PropertySet");
+
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(TEXT, XML_OUTLINE_LEVEL):
+ {
+ // outline level: set Level property
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertNumber( nTmp, aIter.toView() )
+ && nTmp >= 1
+ && nTmp < GetImport().GetTextImport()->
+ GetChapterNumbering()->getCount() )
+ {
+ rPropSet->setPropertyValue("Level", uno::Any(static_cast<sal_Int16>(nTmp - 1)));
+ }
+ // else: value out of range -> ignore
+ break;
+ }
+ default:
+ // else: delegate to superclass
+ XMLIndexMarkImportContext_Impl::ProcessAttribute(
+ nElement, aIter, rPropSet);
+ }
+}
+
+namespace {
+
+class XMLUserIndexMarkImportContext_Impl : public XMLIndexMarkImportContext_Impl
+{
+public:
+
+ XMLUserIndexMarkImportContext_Impl(
+ SvXMLImport& rImport,
+ XMLHints_Impl& rHints);
+
+protected:
+
+ /** process index name */
+ virtual void ProcessAttribute(sal_Int32 nElement,
+ const sax_fastparser::FastAttributeList::FastAttributeIter & aIter,
+ Reference<beans::XPropertySet>& rPropSet) override;
+};
+
+}
+
+XMLUserIndexMarkImportContext_Impl::XMLUserIndexMarkImportContext_Impl(
+ SvXMLImport& rImport, XMLHints_Impl& rHints) :
+ XMLIndexMarkImportContext_Impl(rImport, rHints)
+{
+}
+
+void XMLUserIndexMarkImportContext_Impl::ProcessAttribute(
+ sal_Int32 nElement,
+ const sax_fastparser::FastAttributeList::FastAttributeIter & aIter,
+ Reference<beans::XPropertySet>& rPropSet)
+{
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(TEXT, XML_INDEX_NAME):
+ rPropSet->setPropertyValue("UserIndexName", uno::Any(aIter.toString()));
+ break;
+ case XML_ELEMENT(TEXT, XML_OUTLINE_LEVEL):
+ {
+ // outline level: set Level property
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertNumber(
+ nTmp, aIter.toView(), 0,
+ GetImport().GetTextImport()->GetChapterNumbering()->getCount()))
+ {
+ rPropSet->setPropertyValue("Level", uno::Any(static_cast<sal_Int16>(nTmp - 1)));
+ }
+ // else: value out of range -> ignore
+ break;
+ }
+ default:
+ // else: unknown text property: delegate to super class
+ XMLIndexMarkImportContext_Impl::ProcessAttribute(
+ nElement, aIter, rPropSet);
+ }
+}
+
+namespace {
+
+class XMLAlphaIndexMarkImportContext_Impl : public XMLIndexMarkImportContext_Impl
+{
+public:
+
+ XMLAlphaIndexMarkImportContext_Impl(
+ SvXMLImport& rImport,
+ XMLHints_Impl& rHints);
+
+protected:
+
+ /** process primary + secondary keys */
+ virtual void ProcessAttribute(sal_Int32 nElement,
+ const sax_fastparser::FastAttributeList::FastAttributeIter & aIter,
+ Reference<beans::XPropertySet>& rPropSet) override;
+};
+
+}
+
+XMLAlphaIndexMarkImportContext_Impl::XMLAlphaIndexMarkImportContext_Impl(
+ SvXMLImport& rImport, XMLHints_Impl& rHints) :
+ XMLIndexMarkImportContext_Impl(rImport, rHints)
+{
+}
+
+void XMLAlphaIndexMarkImportContext_Impl::ProcessAttribute(
+ sal_Int32 nElement,
+ const sax_fastparser::FastAttributeList::FastAttributeIter & aIter,
+ Reference<beans::XPropertySet>& rPropSet)
+{
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(TEXT, XML_KEY1):
+ rPropSet->setPropertyValue("PrimaryKey", uno::Any(aIter.toString()));
+ break;
+ case XML_ELEMENT(TEXT, XML_KEY2):
+ rPropSet->setPropertyValue("SecondaryKey", uno::Any(aIter.toString()));
+ break;
+ case XML_ELEMENT(TEXT, XML_KEY1_PHONETIC):
+ rPropSet->setPropertyValue("PrimaryKeyReading", uno::Any(aIter.toString()));
+ break;
+ case XML_ELEMENT(TEXT, XML_KEY2_PHONETIC):
+ rPropSet->setPropertyValue("SecondaryKeyReading", uno::Any(aIter.toString()));
+ break;
+ case XML_ELEMENT(TEXT, XML_STRING_VALUE_PHONETIC):
+ rPropSet->setPropertyValue("TextReading", uno::Any(aIter.toString()));
+ break;
+ case XML_ELEMENT(TEXT, XML_MAIN_ENTRY):
+ {
+ bool bMainEntry = false;
+ bool bTmp(false);
+
+ if (::sax::Converter::convertBool(bTmp, aIter.toView()))
+ bMainEntry = bTmp;
+
+ rPropSet->setPropertyValue("IsMainEntry", uno::Any(bMainEntry));
+ break;
+ }
+ default:
+ XMLIndexMarkImportContext_Impl::ProcessAttribute(
+ nElement, aIter, rPropSet);
+ }
+}
+
+
+XMLImpSpanContext_Impl::XMLImpSpanContext_Impl(
+ SvXMLImport& rImport,
+ sal_Int32 /*nElement*/,
+ const Reference< xml::sax::XFastAttributeList > & xAttrList,
+ XMLHints_Impl& rHints,
+ bool& rIgnLeadSpace,
+ sal_uInt8 nSFConvFlags)
+: SvXMLImportContext( rImport )
+, m_rHints( rHints )
+, pHint( nullptr )
+, rIgnoreLeadingSpace( rIgnLeadSpace )
+, nStarFontsConvFlags( nSFConvFlags & (CONV_FROM_STAR_BATS|CONV_FROM_STAR_MATH) )
+{
+ OUString aStyleName;
+
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ if( aIter.getToken() == XML_ELEMENT(TEXT, XML_STYLE_NAME) )
+ {
+ aStyleName = aIter.toString();
+ break;
+ }
+ }
+
+ if( !aStyleName.isEmpty() )
+ {
+ pHint = new XMLStyleHint_Impl( aStyleName,
+ GetImport().GetTextImport()->GetCursorAsRange()->getStart() );
+ m_rHints.push_back(std::unique_ptr<XMLStyleHint_Impl>(pHint));
+ }
+}
+
+void XMLImpSpanContext_Impl::endFastElement(sal_Int32 )
+{
+ if (!pHint)
+ return;
+
+ Reference<XTextRange> xCrsrRange(GetImport().GetTextImport()->GetCursorAsRange());
+ if (!xCrsrRange.is())
+ return; // Robust (defective file)
+
+ pHint->SetEnd(xCrsrRange->getStart());
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLImpSpanContext_Impl::CreateSpanContext(
+ SvXMLImport& rImport,
+ sal_Int32 nElement,
+ const Reference< xml::sax::XFastAttributeList > & xAttrList,
+ XMLHints_Impl& rHints,
+ bool& rIgnoreLeadingSpace,
+ sal_uInt8 nStarFontsConvFlags
+ )
+{
+ SvXMLImportContext *pContext = nullptr;
+
+ switch( nElement )
+ {
+ case XML_ELEMENT(TEXT, XML_SPAN):
+ pContext = new XMLImpSpanContext_Impl( rImport, nElement,
+ xAttrList,
+ rHints,
+ rIgnoreLeadingSpace
+ ,nStarFontsConvFlags
+ );
+ break;
+
+ case XML_ELEMENT(TEXT, XML_TAB):
+ pContext = new XMLCharContext( rImport, xAttrList,
+ 0x0009, false );
+ rIgnoreLeadingSpace = false;
+ break;
+
+ case XML_ELEMENT(TEXT, XML_LINE_BREAK):
+ if (xAttrList->hasAttribute(XML_ELEMENT(LO_EXT, XML_CLEAR)))
+ {
+ pContext = new SvXMLLineBreakContext(rImport, *rImport.GetTextImport());
+ }
+ else
+ {
+ pContext = new XMLCharContext(rImport, ControlCharacter::LINE_BREAK);
+ }
+ rIgnoreLeadingSpace = false;
+ break;
+
+ case XML_ELEMENT(TEXT, XML_S):
+ pContext = new XMLCharContext( rImport, xAttrList, 0x0020, true );
+ rIgnoreLeadingSpace = false;
+ break;
+
+ case XML_ELEMENT(TEXT, XML_A):
+ {
+ // test for HyperLinkURL property. If present, insert link as
+ // text property (StarWriter), else try to insert as text
+ // field (StarCalc, StarDraw, ...)
+ Reference< beans::XPropertySet > xPropSet( rImport.GetTextImport()->GetCursor(), UNO_QUERY );
+
+ if ( xPropSet->getPropertySetInfo()->hasPropertyByName( "HyperLinkURL" ) )
+ {
+ pContext = new XMLImpHyperlinkContext_Impl(
+ rImport,
+ nElement,
+ xAttrList,
+ rHints,
+ rIgnoreLeadingSpace );
+ }
+ else
+ {
+ pContext = new XMLUrlFieldImportContext(rImport, *rImport.GetTextImport());
+ //whitespace handling like other fields
+ rIgnoreLeadingSpace = false;
+
+ }
+ break;
+ }
+
+ case XML_ELEMENT(TEXT, XML_RUBY):
+ pContext = new XMLImpRubyContext_Impl( rImport, nElement,
+ xAttrList,
+ rHints,
+ rIgnoreLeadingSpace );
+ break;
+
+ case XML_ELEMENT(TEXT, XML_NOTE):
+ if (rImport.GetTextImport()->IsInFrame())
+ {
+ // we must not insert footnotes into text frames
+ pContext = new SvXMLImportContext( rImport );
+ }
+ else
+ {
+ pContext = new XMLFootnoteImportContext(rImport, *rImport.GetTextImport());
+ }
+ rIgnoreLeadingSpace = false;
+ break;
+
+ case XML_ELEMENT(TEXT, XML_REFERENCE_MARK):
+ case XML_ELEMENT(TEXT, XML_BOOKMARK):
+ case XML_ELEMENT(TEXT, XML_BOOKMARK_START):
+ case XML_ELEMENT(TEXT, XML_BOOKMARK_END):
+ pContext = new XMLTextMarkImportContext(rImport, *rImport.GetTextImport(),
+ rHints.GetCrossRefHeadingBookmark());
+ break;
+
+ case XML_ELEMENT(FIELD, XML_FIELDMARK):
+ case XML_ELEMENT(FIELD, XML_FIELDMARK_START):
+ case XML_ELEMENT(FIELD, XML_FIELDMARK_SEPARATOR):
+ case XML_ELEMENT(FIELD, XML_FIELDMARK_END):
+ pContext = new XMLTextMarkImportContext(rImport, *rImport.GetTextImport(),
+ rHints.GetCrossRefHeadingBookmark());
+ break;
+
+ case XML_ELEMENT(TEXT, XML_REFERENCE_MARK_START):
+ pContext = new XMLStartReferenceContext_Impl( rImport,
+ rHints, xAttrList );
+ break;
+
+ case XML_ELEMENT(TEXT, XML_REFERENCE_MARK_END):
+ pContext = new XMLEndReferenceContext_Impl( rImport,
+ rHints, xAttrList );
+ break;
+
+ case XML_ELEMENT(DRAW, XML_FRAME):
+ {
+ Reference < XTextRange > xAnchorPos =
+ rImport.GetTextImport()->GetCursor()->getStart();
+ XMLTextFrameContext *pTextFrameContext =
+ new XMLTextFrameContext(rImport,
+ xAttrList,
+ TextContentAnchorType_AS_CHARACTER );
+ // Remove check for text content. (#i33242#)
+ // Check for text content is done on the processing of the hint
+ if( TextContentAnchorType_AT_CHARACTER ==
+ pTextFrameContext->GetAnchorType() )
+ {
+ rHints.push_back(std::make_unique<XMLTextFrameHint_Impl>(
+ pTextFrameContext, xAnchorPos));
+ }
+ pContext = pTextFrameContext;
+ rIgnoreLeadingSpace = false;
+ }
+ break;
+ case XML_ELEMENT(DRAW, XML_A):
+ {
+ Reference < XTextRange > xAnchorPos(rImport.GetTextImport()->GetCursor()->getStart());
+ pContext =
+ new XMLTextFrameHyperlinkContext( rImport, nElement,
+ xAttrList,
+ TextContentAnchorType_AS_CHARACTER );
+ rHints.push_back(
+ std::make_unique<XMLTextFrameHint_Impl>(pContext, xAnchorPos));
+ }
+ break;
+
+ case XML_ELEMENT(TEXT, XML_TOC_MARK):
+ case XML_ELEMENT(TEXT, XML_TOC_MARK_START):
+ pContext = new XMLTOCMarkImportContext_Impl(
+ rImport, rHints);
+ break;
+
+ case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK):
+ case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_START):
+ pContext = new XMLUserIndexMarkImportContext_Impl(
+ rImport, rHints);
+ break;
+
+ case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK):
+ case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_START):
+ pContext = new XMLAlphaIndexMarkImportContext_Impl(
+ rImport, rHints);
+ break;
+
+ case XML_ELEMENT(TEXT, XML_TOC_MARK_END):
+ case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_END):
+ case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_END):
+ pContext = new XMLIndexMarkImportContext_Impl(
+ rImport, rHints);
+ break;
+
+ case XML_ELEMENT(TEXT, XML_CHANGE_START):
+ case XML_ELEMENT(TEXT, XML_CHANGE_END):
+ case XML_ELEMENT(TEXT, XML_CHANGE):
+ pContext = new XMLChangeImportContext(
+ rImport,
+ ((nElement == XML_ELEMENT(TEXT, XML_CHANGE_END))
+ ? XMLChangeImportContext::Element::END
+ : (nElement == XML_ELEMENT(TEXT, XML_CHANGE_START))
+ ? XMLChangeImportContext::Element::START
+ : XMLChangeImportContext::Element::POINT),
+ false);
+ break;
+
+ case XML_ELEMENT(TEXT, XML_META):
+ pContext = new XMLMetaImportContext(rImport, nElement,
+ rHints, rIgnoreLeadingSpace );
+ break;
+
+ case XML_ELEMENT(TEXT, XML_META_FIELD):
+ pContext = new XMLMetaFieldImportContext(rImport, nElement,
+ rHints, rIgnoreLeadingSpace );
+ break;
+
+ case XML_ELEMENT(LO_EXT, XML_CONTENT_CONTROL):
+ pContext = new XMLContentControlContext(rImport, nElement, rHints, rIgnoreLeadingSpace);
+ break;
+
+ default:
+ // none of the above? then it's probably a text field!
+ pContext = XMLTextFieldImportContext::CreateTextFieldImportContext(
+ rImport, *rImport.GetTextImport(), nElement);
+ // #108784# import draw elements (except control shapes in headers)
+ if( pContext == nullptr &&
+ !( rImport.GetTextImport()->IsInHeaderFooter() &&
+ nElement == XML_ELEMENT(DRAW, XML_CONTROL ) ) )
+ {
+ Reference < XShapes > xShapes;
+ SvXMLShapeContext* pShapeContext = XMLShapeImportHelper::CreateGroupChildContext(
+ rImport, nElement, xAttrList, xShapes );
+ pContext = pShapeContext;
+ // OD 2004-04-20 #i26791# - keep shape in a text frame hint to
+ // adjust its anchor position, if it's at-character anchored
+ Reference < XTextRange > xAnchorPos =
+ rImport.GetTextImport()->GetCursor()->getStart();
+ rHints.push_back(
+ std::make_unique<XMLDrawHint_Impl>(pShapeContext, xAnchorPos));
+ }
+ // Behind fields, shapes and any unknown content blanks aren't ignored
+ rIgnoreLeadingSpace = false;
+ }
+
+ if (!pContext)
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ return pContext;
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLImpSpanContext_Impl::createFastChildContext(
+ sal_Int32 nElement,
+ const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
+{
+ return CreateSpanContext( GetImport(), nElement, xAttrList,
+ m_rHints, rIgnoreLeadingSpace
+ ,nStarFontsConvFlags
+ );
+}
+
+void XMLImpSpanContext_Impl::characters( const OUString& rChars )
+{
+ OUString sStyleName;
+ if( pHint )
+ sStyleName = pHint->GetStyleName();
+ OUString sChars =
+ GetImport().GetTextImport()->ConvertStarFonts( rChars, sStyleName,
+ nStarFontsConvFlags,
+ false, GetImport() );
+ GetImport().GetTextImport()->InsertString( sChars, rIgnoreLeadingSpace );
+}
+
+
+XMLParaContext::XMLParaContext(
+ SvXMLImport& rImport,
+ sal_Int32 nElement,
+ const Reference< xml::sax::XFastAttributeList > & xAttrList ) :
+ SvXMLImportContext( rImport ),
+ xStart( rImport.GetTextImport()->GetCursorAsRange()->getStart() ),
+ m_bHaveAbout(false),
+ nOutlineLevel( (nElement & TOKEN_MASK) == XML_H ? 1 : -1 ),
+ // Lost outline numbering in master document (#i73509#)
+ mbOutlineLevelAttrFound( false ),
+ mbOutlineContentVisible(true),
+ bIgnoreLeadingSpace( true ),
+ bHeading( (nElement & TOKEN_MASK) == XML_H ),
+ bIsListHeader( false ),
+ bIsRestart (false),
+ nStartValue(0),
+ nStarFontsConvFlags( 0 )
+{
+ bool bHaveXmlId( false );
+ OUString aCondStyleName;
+
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ switch( aIter.getToken() )
+ {
+ case XML_ELEMENT(XML, XML_ID):
+ m_sXmlId = aIter.toString();
+ bHaveXmlId = true;
+ break;
+ case XML_ELEMENT(XHTML, XML_ABOUT):
+ m_sAbout = aIter.toString();
+ m_bHaveAbout = true;
+ break;
+ case XML_ELEMENT(XHTML, XML_PROPERTY):
+ m_sProperty = aIter.toString();
+ break;
+ case XML_ELEMENT(XHTML, XML_CONTENT):
+ m_sContent = aIter.toString();
+ break;
+ case XML_ELEMENT(XHTML, XML_DATATYPE):
+ m_sDatatype = aIter.toString();
+ break;
+ case XML_ELEMENT(TEXT, XML_ID):
+ if (!bHaveXmlId) { m_sXmlId = aIter.toString(); }
+ break;
+ case XML_ELEMENT(TEXT, XML_STYLE_NAME):
+ sStyleName = aIter.toString();
+ break;
+ case XML_ELEMENT(TEXT, XML_COND_STYLE_NAME):
+ aCondStyleName = aIter.toString();
+ break;
+ case XML_ELEMENT(TEXT, XML_OUTLINE_LEVEL):
+ {
+ sal_Int32 nTmp = aIter.toInt32();
+ if( nTmp > 0 )
+ {
+ if( nTmp > 127 )
+ nTmp = 127;
+ nOutlineLevel = static_cast<sal_Int8>(nTmp);
+ }
+ // Lost outline numbering in master document (#i73509#)
+ mbOutlineLevelAttrFound = true;
+ }
+ break;
+ case XML_ELEMENT(LO_EXT, XML_OUTLINE_CONTENT_VISIBLE):
+ {
+ bool bBool(false);
+ if (::sax::Converter::convertBool(bBool, aIter.toView()))
+ mbOutlineContentVisible = bBool;
+ }
+ break;
+ case XML_ELEMENT(TEXT, XML_IS_LIST_HEADER):
+ {
+ bool bBool(false);
+ if (::sax::Converter::convertBool(bBool, aIter.toView()))
+ bIsListHeader = bBool;
+ }
+ break;
+ case XML_ELEMENT(TEXT, XML_RESTART_NUMBERING):
+ {
+ bool bBool(false);
+ if (::sax::Converter::convertBool(bBool, aIter.toView()))
+ bIsRestart = bBool;
+ }
+ break;
+ case XML_ELEMENT(TEXT, XML_START_VALUE):
+ {
+ nStartValue = sal::static_int_cast< sal_Int16 >(aIter.toInt32());
+ }
+ break;
+ case XML_ELEMENT(LO_EXT, XML_MARKER_STYLE_NAME):
+ if (auto pStyle = rImport.GetTextImport()->FindAutoCharStyle(aIter.toString()))
+ m_aMarkerStyleName = pStyle->GetAutoName();
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+
+ if( !aCondStyleName.isEmpty() )
+ sStyleName = aCondStyleName;
+}
+
+void XMLParaContext::endFastElement(sal_Int32 )
+{
+ rtl::Reference < XMLTextImportHelper > xTxtImport(
+ GetImport().GetTextImport());
+ Reference<XTextRange> xEnd;
+ try
+ {
+ Reference<XTextRange> const xCrsrRange(xTxtImport->GetCursorAsRange());
+ if (!xCrsrRange.is())
+ return; // Robust (defective file)
+ xEnd = xCrsrRange->getStart();
+ }
+ catch (uno::Exception const&)
+ {
+ SAL_INFO("xmloff.text", "XMLParaContext: cursor disposed?");
+ return;
+ }
+
+ // if we have an id set for this paragraph, get a cursor for this
+ // paragraph and register it with the given identifier
+ // FIXME: this is just temporary, and should be removed when
+ // EditEngine paragraphs implement XMetadatable!
+ if (!m_sXmlId.isEmpty())
+ {
+ Reference < XTextCursor > xIdCursor( xTxtImport->GetText()->createTextCursorByRange( xStart ) );
+ if( xIdCursor.is() )
+ {
+ xIdCursor->gotoRange( xEnd, true );
+ GetImport().getInterfaceToIdentifierMapper().registerReference(
+ m_sXmlId, Reference<XInterface>( xIdCursor, UNO_QUERY ));
+ }
+ }
+
+ // insert a paragraph break
+ xTxtImport->InsertControlCharacter( ControlCharacter::APPEND_PARAGRAPH );
+
+ // create a cursor that select the whole last paragraph
+ Reference < XTextCursor > xAttrCursor;
+ try {
+ xAttrCursor = xTxtImport->GetText()->createTextCursorByRange( xStart );
+ if( !xAttrCursor.is() )
+ return; // Robust (defective file)
+ } catch (const uno::Exception &) {
+ // createTextCursorByRange() likes to throw runtime exception, even
+ // though it just means 'we were unable to create the cursor'
+ return;
+ }
+ xAttrCursor->gotoRange( xEnd, true );
+
+ // xml:id for RDF metadata
+ if (!m_sXmlId.isEmpty() || m_bHaveAbout || !m_sProperty.isEmpty())
+ {
+ try {
+ const uno::Reference<container::XEnumerationAccess> xEA
+ (xAttrCursor, uno::UNO_QUERY_THROW);
+ const uno::Reference<container::XEnumeration> xEnum(
+ xEA->createEnumeration(), uno::UNO_SET_THROW);
+ SAL_WARN_IF(!xEnum->hasMoreElements(), "xmloff.text", "xml:id: no paragraph?");
+ if (xEnum->hasMoreElements()) {
+ uno::Reference<rdf::XMetadatable> xMeta;
+ xEnum->nextElement() >>= xMeta;
+ SAL_WARN_IF(!xMeta.is(), "xmloff.text", "xml:id: not XMetadatable");
+ GetImport().SetXmlId(xMeta, m_sXmlId);
+ if (m_bHaveAbout)
+ {
+ GetImport().AddRDFa(xMeta,
+ m_sAbout, m_sProperty, m_sContent, m_sDatatype);
+ }
+ SAL_WARN_IF(xEnum->hasMoreElements(), "xmloff.text", "xml:id: > 1 paragraph?");
+ }
+ } catch (const uno::Exception &) {
+ SAL_INFO("xmloff.text", "XMLParaContext::~XMLParaContext: exception");
+ }
+ }
+
+ OUString const sCellParaStyleName(xTxtImport->GetCellParaStyleDefault());
+ if( !sCellParaStyleName.isEmpty() )
+ {
+ /* Suppress handling of outline and list attributes,
+ because of side effects of method <SetStyleAndAttrs(..)> (#i80724#)
+ */
+ xTxtImport->SetStyleAndAttrs( GetImport(), xAttrCursor,
+ sCellParaStyleName,
+ true,
+ false, -1, // suppress outline handling
+ false ); // suppress list attributes handling
+ }
+
+ // #103445# for headings without style name, find the proper style
+ if( bHeading && sStyleName.isEmpty() )
+ xTxtImport->FindOutlineStyleName( sStyleName, nOutlineLevel );
+
+ // set style and hard attributes at the previous paragraph
+ // Add parameter <mbOutlineLevelAttrFound> (#i73509#)
+ sStyleName = xTxtImport->SetStyleAndAttrs( GetImport(), xAttrCursor,
+ sStyleName,
+ true,
+ mbOutlineLevelAttrFound,
+ bHeading ? nOutlineLevel : -1,
+ true,
+ mbOutlineContentVisible);
+
+ if (m_aMarkerStyleName.hasValue())
+ {
+ if (auto xPropSet = xStart.query<css::beans::XPropertySet>())
+ {
+ try
+ {
+ xPropSet->setPropertyValue("ListAutoFormat", m_aMarkerStyleName);
+ }
+ catch (const css::beans::UnknownPropertyException&)
+ {
+ // no problem
+ }
+ }
+ }
+
+ // handle list style header
+ if (bHeading && (bIsListHeader || bIsRestart))
+ {
+ Reference<XPropertySet> xPropSet( xAttrCursor, UNO_QUERY );
+
+ if (xPropSet.is())
+ {
+ if (bIsListHeader)
+ {
+ OUString sNumberingIsNumber
+ ("NumberingIsNumber");
+ if(xPropSet->getPropertySetInfo()->
+ hasPropertyByName(sNumberingIsNumber))
+ {
+ xPropSet->setPropertyValue
+ (sNumberingIsNumber, Any( false ) );
+ }
+ }
+ if (bIsRestart)
+ {
+ OUString sParaIsNumberingRestart
+ ("ParaIsNumberingRestart");
+ OUString sNumberingStartValue
+ ("NumberingStartValue");
+ if (xPropSet->getPropertySetInfo()->
+ hasPropertyByName(sParaIsNumberingRestart))
+ {
+ xPropSet->setPropertyValue
+ (sParaIsNumberingRestart, Any(true));
+ }
+
+ if (xPropSet->getPropertySetInfo()->
+ hasPropertyByName(sNumberingStartValue))
+ {
+ xPropSet->setPropertyValue
+ (sNumberingStartValue, Any(nStartValue));
+ }
+ }
+
+ }
+ }
+
+ if (m_xHints)
+ {
+ bool bSetNoFormatAttr = false;
+ uno::Reference<beans::XPropertySet> xCursorProps(xAttrCursor, uno::UNO_QUERY);
+ int nEmptyHints = 0;
+ uno::Reference<text::XTextRangeCompare> xCompare(xTxtImport->GetText(), uno::UNO_QUERY);
+ if (xCompare.is())
+ {
+ try
+ {
+ for (const auto& pHint : m_xHints->GetHints())
+ {
+ if (xCompare->compareRegionStarts(pHint->GetStart(), pHint->GetEnd()) == 0)
+ {
+ ++nEmptyHints;
+ }
+ }
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("xmloff.text", "");
+ }
+ }
+ if (nEmptyHints > 0 || m_aMarkerStyleName.hasValue())
+ {
+ // We have at least one empty hint, then make try to ask the cursor to not upgrade our character
+ // attributes to paragraph-level formatting, which would lead to incorrect rendering.
+ uno::Reference<beans::XPropertySetInfo> xCursorPropsInfo = xCursorProps->getPropertySetInfo();
+ bSetNoFormatAttr = xCursorPropsInfo->hasPropertyByName("NoFormatAttr");
+ }
+ if (bSetNoFormatAttr)
+ {
+ xCursorProps->setPropertyValue("NoFormatAttr", uno::Any(true));
+ }
+ for (const auto & i : m_xHints->GetHints())
+ {
+ XMLHint_Impl *const pHint = i.get();
+ xAttrCursor->gotoRange( pHint->GetStart(), false );
+ xAttrCursor->gotoRange( pHint->GetEnd(), true );
+ switch( pHint->GetType() )
+ {
+ case XMLHintType::XML_HINT_STYLE:
+ {
+ const OUString& rStyleName =
+ static_cast<XMLStyleHint_Impl *>(pHint)->GetStyleName();
+ if( !rStyleName.isEmpty() )
+ xTxtImport->SetStyleAndAttrs( GetImport(),
+ xAttrCursor, rStyleName,
+ false );
+ }
+ break;
+ case XMLHintType::XML_HINT_REFERENCE:
+ {
+ const OUString& rRefName =
+ static_cast<XMLReferenceHint_Impl *>(pHint)->GetRefName();
+ if( !rRefName.isEmpty() )
+ {
+ if( !pHint->GetEnd().is() )
+ pHint->SetEnd(xEnd);
+
+ // reference name uses rStyleName member
+ // borrow from XMLTextMarkImportContext
+ XMLTextMarkImportContext::CreateAndInsertMark(
+ GetImport(),
+ "com.sun.star.text.ReferenceMark",
+ rRefName,
+ xAttrCursor);
+ }
+ }
+ break;
+ case XMLHintType::XML_HINT_HYPERLINK:
+ {
+ const XMLHyperlinkHint_Impl *pHHint =
+ static_cast<const XMLHyperlinkHint_Impl *>(pHint);
+ xTxtImport->SetHyperlink( GetImport(),
+ xAttrCursor,
+ pHHint->GetHRef(),
+ pHHint->GetName(),
+ pHHint->GetTargetFrameName(),
+ pHHint->GetStyleName(),
+ pHHint->GetVisitedStyleName(),
+ pHHint->GetEventsContext() );
+ }
+ break;
+ case XMLHintType::XML_HINT_INDEX_MARK:
+ {
+ Reference<beans::XPropertySet> xMark(
+ static_cast<const XMLIndexMarkHint_Impl *>(pHint)->GetMark());
+ Reference<XTextContent> xContent(xMark, UNO_QUERY);
+ try
+ {
+ xTxtImport->GetText()->insertTextContent(
+ xAttrCursor, xContent, true );
+ }
+ catch (uno::RuntimeException const&)
+ {
+ TOOLS_INFO_EXCEPTION("xmloff.text", "could not insert index mark, presumably in editengine text");
+ }
+ }
+ break;
+ case XMLHintType::XML_HINT_TEXT_FRAME:
+ {
+ const XMLTextFrameHint_Impl *pFHint =
+ static_cast<const XMLTextFrameHint_Impl *>(pHint);
+ // Check for text content (#i33242#)
+ Reference < XTextContent > xTextContent =
+ pFHint->GetTextContent();
+ if ( xTextContent.is() )
+ {
+ /* Core impl. of the unification of drawing objects and
+ Writer fly frames (#i26791#)
+ */
+ if ( pFHint->IsBoundAtChar() )
+ {
+ xTextContent->attach( xAttrCursor );
+ }
+ }
+ /* Consider, that hint can also contain a shape -
+ e.g. drawing object of type 'Text'. (#i33242#)
+ */
+ else
+ {
+ Reference < XShape > xShape = pFHint->GetShape();
+ if ( xShape.is() )
+ {
+ // determine anchor type
+ Reference < XPropertySet > xPropSet( xShape, UNO_QUERY );
+ TextContentAnchorType eAnchorType =
+ TextContentAnchorType_AT_PARAGRAPH;
+ {
+ Any aAny = xPropSet->getPropertyValue( "AnchorType" );
+ aAny >>= eAnchorType;
+ }
+ if ( TextContentAnchorType_AT_CHARACTER == eAnchorType )
+ {
+ // set anchor position for at-character anchored objects
+ xPropSet->setPropertyValue("TextRange", Any(xAttrCursor));
+ }
+ }
+ }
+ }
+ break;
+ /* Core impl. of the unification of drawing objects and
+ Writer fly frames (#i26791#)
+ */
+ case XMLHintType::XML_HINT_DRAW:
+ {
+ const XMLDrawHint_Impl *pDHint =
+ static_cast<const XMLDrawHint_Impl*>(pHint);
+ // Improvement: hint directly provides the shape. (#i33242#)
+ const Reference < XShape >& xShape = pDHint->GetShape();
+ if ( xShape.is() )
+ {
+ // determine anchor type
+ Reference < XPropertySet > xPropSet( xShape, UNO_QUERY );
+ TextContentAnchorType eAnchorType = TextContentAnchorType_AT_PARAGRAPH;
+ {
+ Any aAny = xPropSet->getPropertyValue( "AnchorType" );
+ aAny >>= eAnchorType;
+ }
+ if ( TextContentAnchorType_AT_CHARACTER == eAnchorType )
+ {
+ // set anchor position for at-character anchored objects
+ xPropSet->setPropertyValue("TextRange", Any(xAttrCursor));
+ }
+ }
+ }
+ break;
+ default:
+ SAL_WARN( "xmloff.text", "What's this" );
+ break;
+ }
+ }
+ if (bSetNoFormatAttr)
+ {
+ xCursorProps->setPropertyValue("NoFormatAttr", uno::Any(false));
+ }
+ }
+ m_xHints.reset();
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLParaContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ if (!m_xHints)
+ m_xHints.reset(new XMLHints_Impl);
+ return XMLImpSpanContext_Impl::CreateSpanContext(
+ GetImport(), nElement, xAttrList,
+ *m_xHints, bIgnoreLeadingSpace,
+ nStarFontsConvFlags);
+}
+
+void XMLParaContext::characters( const OUString& rChars )
+{
+ OUString sChars =
+ GetImport().GetTextImport()->ConvertStarFonts( rChars, sStyleName,
+ nStarFontsConvFlags,
+ true, GetImport() );
+ GetImport().GetTextImport()->InsertString( sChars, bIgnoreLeadingSpace );
+}
+
+
+XMLNumberedParaContext::XMLNumberedParaContext(
+ SvXMLImport& i_rImport,
+ sal_Int32 /*nElement*/,
+ const Reference< xml::sax::XFastAttributeList > & xAttrList ) :
+ SvXMLImportContext( i_rImport ),
+ m_Level(0),
+ m_StartValue(-1)
+{
+ OUString StyleName;
+
+ for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
+ {
+ switch( aIter.getToken() )
+ {
+ case XML_ELEMENT(XML, XML_ID):
+//FIXME: there is no UNO API for lists
+ break;
+ case XML_ELEMENT(TEXT, XML_LIST_ID):
+ m_ListId = aIter.toString();
+ break;
+ case XML_ELEMENT(TEXT, XML_LEVEL):
+ {
+ sal_Int32 nTmp = aIter.toInt32();
+ if ( nTmp >= 1 && nTmp <= SHRT_MAX ) {
+ m_Level = static_cast<sal_uInt16>(nTmp) - 1;
+ }
+ }
+ break;
+ case XML_ELEMENT(TEXT, XML_STYLE_NAME):
+ StyleName = aIter.toString();
+ break;
+ case XML_ELEMENT(TEXT, XML_CONTINUE_NUMBERING):
+ // this attribute is deprecated
+// ContinueNumbering = IsXMLToken(sValue, XML_TRUE);
+ break;
+ case XML_ELEMENT(TEXT, XML_START_VALUE):
+ {
+ sal_Int32 nTmp = aIter.toInt32();
+ if ( nTmp >= 0 && nTmp <= SHRT_MAX ) {
+ m_StartValue = static_cast<sal_Int16>(nTmp);
+ }
+ }
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", aIter);
+ }
+ }
+
+ XMLTextListsHelper& rTextListsHelper(
+ i_rImport.GetTextImport()->GetTextListHelper() );
+ if (m_ListId.isEmpty())
+ {
+ SAL_WARN_IF(0 <= i_rImport.GetODFVersion().compareTo(u"1.2"), "xmloff.text", "invalid numbered-paragraph: no list-id (1.2)");
+ m_ListId = rTextListsHelper.GetNumberedParagraphListId(m_Level,
+ StyleName);
+ SAL_WARN_IF(m_ListId.isEmpty(), "xmloff.text", "numbered-paragraph: no ListId");
+ if (m_ListId.isEmpty()) {
+ return;
+ }
+ }
+ m_xNumRules = rTextListsHelper.EnsureNumberedParagraph( i_rImport,
+ m_ListId, m_Level, StyleName);
+
+ SAL_WARN_IF(!m_xNumRules.is(), "xmloff.text", "numbered-paragraph: no NumRules");
+
+ i_rImport.GetTextImport()->GetTextListHelper().PushListContext( this );
+}
+
+void XMLNumberedParaContext::endFastElement(sal_Int32 )
+{
+ if (!m_ListId.isEmpty()) {
+ GetImport().GetTextImport()->PopListContext();
+ }
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLNumberedParaContext::createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ switch (nElement)
+ {
+ case XML_ELEMENT(TEXT, XML_H):
+ case XML_ELEMENT(LO_EXT, XML_H):
+ case XML_ELEMENT(TEXT, XML_P):
+ case XML_ELEMENT(LO_EXT, XML_P):
+ return new XMLParaContext( GetImport(), nElement, xAttrList );
+ default:
+ XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
+ }
+
+ return nullptr;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/txtparai.hxx b/xmloff/source/text/txtparai.hxx
new file mode 100644
index 0000000000..fed2690cb4
--- /dev/null
+++ b/xmloff/source/text/txtparai.hxx
@@ -0,0 +1,146 @@
+/* -*- 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 .
+ */
+#pragma once
+
+
+#include <com/sun/star/container/XIndexReplace.hpp>
+#include <com/sun/star/uno/Reference.h>
+#include <xmloff/xmlictxt.hxx>
+
+class XMLHints_Impl;
+namespace com::sun::star {
+ namespace text { class XTextRange; }
+ namespace xml::sax { class XAttributeList; }
+}
+
+#define CONV_FROM_STAR_BATS 1
+#define CONV_FROM_STAR_MATH 2
+#define CONV_STAR_FONT_FLAGS_VALID 4
+
+class XMLParaContext : public SvXMLImportContext
+{
+ css::uno::Reference < css::text::XTextRange > xStart;
+ OUString sStyleName;
+ OUString m_sXmlId;
+ OUString m_sAbout;
+ OUString m_sProperty;
+ OUString m_sContent;
+ OUString m_sDatatype;
+ css::uno::Any m_aMarkerStyleName;
+ bool m_bHaveAbout;
+ sal_Int8 nOutlineLevel;
+ std::unique_ptr<XMLHints_Impl> m_xHints;
+ // Lost outline numbering in master document (#i73509#)
+ bool mbOutlineLevelAttrFound;
+ bool mbOutlineContentVisible;
+ bool bIgnoreLeadingSpace;
+ bool bHeading;
+ bool bIsListHeader;
+ bool bIsRestart;
+ sal_Int16 nStartValue;
+ sal_uInt8 nStarFontsConvFlags;
+
+public:
+
+
+ XMLParaContext( SvXMLImport& rImport,
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList );
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+
+ virtual void SAL_CALL characters( const OUString& rChars ) override;
+
+};
+
+class XMLNumberedParaContext : public SvXMLImportContext
+{
+ /// text:list-level MINUS 1
+ sal_Int16 m_Level;
+ /// text:start-value
+ sal_Int16 m_StartValue;
+ /// text:list-id
+ OUString m_ListId;
+ /// text:style-name
+ css::uno::Reference< css::container::XIndexReplace > m_xNumRules;
+
+public:
+
+
+ XMLNumberedParaContext( SvXMLImport& i_rImport,
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & i_xAttrList );
+
+ virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+
+ sal_Int16 GetLevel() const { return m_Level; }
+ const css::uno::Reference< css::container::XIndexReplace >& GetNumRules() const
+ { return m_xNumRules; }
+ const OUString& GetListId() const { return m_ListId; }
+ sal_Int16 GetStartValue() const { return m_StartValue; }
+
+};
+
+class XMLHints_Impl;
+class XMLStyleHint_Impl;
+
+class XMLImpSpanContext_Impl : public SvXMLImportContext
+{
+ XMLHints_Impl& m_rHints;
+ XMLStyleHint_Impl *pHint;
+
+ bool& rIgnoreLeadingSpace;
+
+ sal_uInt8 nStarFontsConvFlags;
+
+public:
+
+
+ XMLImpSpanContext_Impl(
+ SvXMLImport& rImport,
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList,
+ XMLHints_Impl& rHints,
+ bool& rIgnLeadSpace,
+ sal_uInt8 nSFConvFlags
+ );
+
+ static css::uno::Reference< css::xml::sax::XFastContextHandler > CreateSpanContext(
+ SvXMLImport& rImport,
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList,
+ XMLHints_Impl& rHints,
+ bool& rIgnLeadSpace,
+ sal_uInt8 nStarFontsConvFlags = 0
+ );
+
+ virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
+ sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
+
+ virtual void SAL_CALL endFastElement( sal_Int32 nElement ) override;
+ virtual void SAL_CALL characters( const OUString& rChars ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/txtparaimphint.hxx b/xmloff/source/text/txtparaimphint.hxx
new file mode 100644
index 0000000000..f244eb5719
--- /dev/null
+++ b/xmloff/source/text/txtparaimphint.hxx
@@ -0,0 +1,241 @@
+/* -*- 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 .
+ */
+#pragma once
+
+#include <rtl/ustring.hxx>
+#include "XMLTextFrameContext.hxx"
+#include "XMLTextFrameHyperlinkContext.hxx"
+#include <utility>
+#include <xmloff/XMLEventsImportContext.hxx>
+
+enum class XMLHintType
+{
+ XML_HINT_STYLE = 1,
+ XML_HINT_REFERENCE = 2,
+ XML_HINT_HYPERLINK = 3,
+ // There is no 4 defined here
+ XML_HINT_INDEX_MARK = 5,
+ XML_HINT_TEXT_FRAME = 6,
+ // Core impl. of the unification of drawing objects and Writer fly frames (#i26791#)
+ XML_HINT_DRAW = 7
+};
+
+class XMLHint_Impl
+{
+ css::uno::Reference < css::text::XTextRange > xStart;
+ css::uno::Reference < css::text::XTextRange > xEnd;
+
+ XMLHintType nType;
+
+public:
+
+ XMLHint_Impl( XMLHintType nTyp,
+ css::uno::Reference < css::text::XTextRange > xS,
+ css::uno::Reference < css::text::XTextRange > xE ) :
+ xStart(std::move( xS )),
+ xEnd(std::move( xE )),
+ nType( nTyp )
+ {
+ }
+
+ virtual ~XMLHint_Impl() {}
+
+ const css::uno::Reference < css::text::XTextRange > & GetStart() const { return xStart; }
+ const css::uno::Reference < css::text::XTextRange > & GetEnd() const { return xEnd; }
+ void SetEnd( const css::uno::Reference < css::text::XTextRange > & rPos ) { xEnd = rPos; }
+
+ // We don't use virtual methods to differ between the sub classes,
+ // because this seems to be too expensive if compared to inline methods.
+ XMLHintType GetType() const { return nType; }
+ bool IsReference() const { return XMLHintType::XML_HINT_REFERENCE==nType; }
+};
+
+class XMLStyleHint_Impl : public XMLHint_Impl
+{
+ OUString sStyleName;
+
+public:
+
+ XMLStyleHint_Impl( OUString aStyleName,
+ const css::uno::Reference < css::text::XTextRange > & rPos ) :
+ XMLHint_Impl( XMLHintType::XML_HINT_STYLE, rPos, rPos ),
+ sStyleName(std::move( aStyleName ))
+ {
+ }
+
+ const OUString& GetStyleName() const { return sStyleName; }
+};
+
+class XMLReferenceHint_Impl : public XMLHint_Impl
+{
+ OUString sRefName;
+
+public:
+
+ XMLReferenceHint_Impl( OUString aRefName,
+ const css::uno::Reference < css::text::XTextRange > & rPos ) :
+ XMLHint_Impl( XMLHintType::XML_HINT_REFERENCE, rPos, rPos ),
+ sRefName(std::move( aRefName ))
+ {
+ }
+
+ const OUString& GetRefName() const { return sRefName; }
+};
+
+class XMLHyperlinkHint_Impl : public XMLHint_Impl
+{
+ OUString sHRef;
+ OUString sName;
+ OUString sTargetFrameName;
+ OUString sStyleName;
+ OUString sVisitedStyleName;
+ rtl::Reference<XMLEventsImportContext> mxEvents;
+
+public:
+
+ XMLHyperlinkHint_Impl( const css::uno::Reference < css::text::XTextRange > & rPos ) :
+ XMLHint_Impl( XMLHintType::XML_HINT_HYPERLINK, rPos, rPos )
+ {
+ }
+
+ void SetHRef( const OUString& s ) { sHRef = s; }
+ const OUString& GetHRef() const { return sHRef; }
+ void SetName( const OUString& s ) { sName = s; }
+ const OUString& GetName() const { return sName; }
+ void SetTargetFrameName( const OUString& s ) { sTargetFrameName = s; }
+ const OUString& GetTargetFrameName() const { return sTargetFrameName; }
+ void SetStyleName( const OUString& s ) { sStyleName = s; }
+ const OUString& GetStyleName() const { return sStyleName; }
+ void SetVisitedStyleName( const OUString& s ) { sVisitedStyleName = s; }
+ const OUString& GetVisitedStyleName() const { return sVisitedStyleName; }
+ XMLEventsImportContext* GetEventsContext() const
+ {
+ return mxEvents.get();
+ }
+ void SetEventsContext( XMLEventsImportContext* pCtxt )
+ {
+ mxEvents.set(pCtxt);
+ }
+};
+
+class XMLIndexMarkHint_Impl : public XMLHint_Impl
+{
+ const css::uno::Reference<css::beans::XPropertySet> xIndexMarkPropSet;
+
+ const OUString sID;
+
+public:
+
+ XMLIndexMarkHint_Impl( css::uno::Reference < css::beans::XPropertySet > xPropSet,
+ const css::uno::Reference < css::text::XTextRange > & rPos ) :
+ XMLHint_Impl( XMLHintType::XML_HINT_INDEX_MARK, rPos, rPos ),
+ xIndexMarkPropSet(std::move( xPropSet )),
+ sID()
+ {
+ }
+
+ XMLIndexMarkHint_Impl( css::uno::Reference < css::beans::XPropertySet > xPropSet,
+ const css::uno::Reference < css::text::XTextRange > & rPos,
+ OUString sIDString) :
+ XMLHint_Impl( XMLHintType::XML_HINT_INDEX_MARK, rPos, rPos ),
+ xIndexMarkPropSet(std::move( xPropSet )),
+ sID(std::move(sIDString))
+ {
+ }
+
+ const css::uno::Reference<css::beans::XPropertySet> & GetMark() const
+ { return xIndexMarkPropSet; }
+ const OUString& GetID() const { return sID; }
+};
+
+class XMLTextFrameHint_Impl : public XMLHint_Impl
+{
+ // OD 2004-04-20 #i26791#
+ SvXMLImportContextRef xContext;
+
+public:
+
+ XMLTextFrameHint_Impl( SvXMLImportContext* pContext,
+ const css::uno::Reference < css::text::XTextRange > & rPos ) :
+ XMLHint_Impl( XMLHintType::XML_HINT_TEXT_FRAME, rPos, rPos ),
+ xContext( pContext )
+ {
+ }
+
+ css::uno::Reference < css::text::XTextContent > GetTextContent() const
+ {
+ css::uno::Reference < css::text::XTextContent > xTxt;
+ SvXMLImportContext *pContext = xContext.get();
+ if (XMLTextFrameContext *pFrameContext = dynamic_cast<XMLTextFrameContext*>(pContext))
+ xTxt = pFrameContext->GetTextContent();
+ else if (XMLTextFrameHyperlinkContext *pLinkContext = dynamic_cast<XMLTextFrameHyperlinkContext*>(pContext))
+ xTxt = pLinkContext->GetTextContent();
+
+ return xTxt;
+ }
+
+ // Frame "to character": anchor moves from first to last char after saving (#i33242#)
+ css::uno::Reference < css::drawing::XShape > GetShape() const
+ {
+ css::uno::Reference < css::drawing::XShape > xShape;
+ SvXMLImportContext *pContext = xContext.get();
+ if (XMLTextFrameContext *pFrameContext = dynamic_cast<XMLTextFrameContext*>(pContext))
+ xShape = pFrameContext->GetShape();
+ else if(XMLTextFrameHyperlinkContext *pLinkContext = dynamic_cast<XMLTextFrameHyperlinkContext*>(pContext))
+ xShape = pLinkContext->GetShape();
+
+ return xShape;
+ }
+
+ bool IsBoundAtChar() const
+ {
+ bool bRet = false;
+ SvXMLImportContext *pContext = xContext.get();
+ if (XMLTextFrameContext *pFrameContext = dynamic_cast<XMLTextFrameContext*>(pContext))
+ bRet = css::text::TextContentAnchorType_AT_CHARACTER ==
+ pFrameContext->GetAnchorType();
+ else if (XMLTextFrameHyperlinkContext *pLinkContext = dynamic_cast<XMLTextFrameHyperlinkContext*>(pContext))
+ bRet = css::text::TextContentAnchorType_AT_CHARACTER ==
+ pLinkContext->GetAnchorType();
+ return bRet;
+ }
+};
+
+// Core impl. of the unification of drawing objects and Writer fly frames (#i26791#)
+class XMLDrawHint_Impl : public XMLHint_Impl
+{
+ rtl::Reference<SvXMLShapeContext> xContext;
+
+public:
+
+ XMLDrawHint_Impl( SvXMLShapeContext* pContext,
+ const css::uno::Reference < css::text::XTextRange > & rPos ) :
+ XMLHint_Impl( XMLHintType::XML_HINT_DRAW, rPos, rPos ),
+ xContext( pContext )
+ {
+ }
+
+ // Frame "to character": anchor moves from first to last char after saving (#i33242#)
+ css::uno::Reference < css::drawing::XShape > const & GetShape() const
+ {
+ return xContext->getShape();
+ }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/txtprhdl.cxx b/xmloff/source/text/txtprhdl.cxx
new file mode 100644
index 0000000000..f7c3a9790d
--- /dev/null
+++ b/xmloff/source/text/txtprhdl.cxx
@@ -0,0 +1,1451 @@
+/* -*- 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 <o3tl/any.hxx>
+#include <osl/diagnose.h>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/style/DropCapFormat.hpp>
+#include <com/sun/star/text/FontRelief.hpp>
+#include <com/sun/star/text/WrapTextMode.hpp>
+#include <com/sun/star/text/XTextColumns.hpp>
+#include <com/sun/star/text/TextColumn.hpp>
+#include <com/sun/star/text/RelOrientation.hpp>
+#include <com/sun/star/text/HoriOrientation.hpp>
+#include <com/sun/star/text/VertOrientation.hpp>
+#include <com/sun/star/text/RubyAdjust.hpp>
+#include <com/sun/star/text/RubyPosition.hpp>
+#include <com/sun/star/text/FontEmphasis.hpp>
+#include <com/sun/star/text/ParagraphVertAlign.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <sax/tools/converter.hxx>
+#include <xmloff/xmltypes.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlement.hxx>
+#include "XMLAnchorTypePropHdl.hxx"
+#include <enummaps.hxx>
+#include <xmloff/XMLConstantsPropertyHandler.hxx>
+#include <XMLClipPropertyHandler.hxx>
+#include <XMLTextColumnsPropertyHandler.hxx>
+#include <xmloff/NamedBoolPropertyHdl.hxx>
+#include "txtprhdl.hxx"
+#include <com/sun/star/text/WrapInfluenceOnPosition.hpp>
+#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
+#include <xmloff/EnumPropertyHdl.hxx>
+#include <XMLFillBitmapSizePropertyHandler.hxx>
+#include <XMLBitmapLogicalSizePropertyHandler.hxx>
+#include <XMLBitmapRepeatOffsetPropertyHandler.hxx>
+#include <xmloff/XMLComplexColorHandler.hxx>
+#include <vcl/graph.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::style;
+using namespace ::com::sun::star::text;
+using namespace ::xmloff::token;
+using namespace ::com::sun::star::drawing;
+
+SvXMLEnumMapEntry<sal_uInt16> const pXML_HoriPos_Enum[] =
+{
+ { XML_FROM_LEFT, HoriOrientation::NONE },
+ { XML_FROM_INSIDE, HoriOrientation::NONE }, // import only
+ { XML_LEFT, HoriOrientation::LEFT },
+ { XML_INSIDE, HoriOrientation::LEFT }, // import only
+ { XML_CENTER, HoriOrientation::CENTER },
+ { XML_RIGHT, HoriOrientation::RIGHT },
+ { XML_OUTSIDE, HoriOrientation::RIGHT }, // import only
+ { XML_TOKEN_INVALID, 0 }
+};
+
+SvXMLEnumMapEntry<sal_uInt16> const pXML_HoriPosMirrored_Enum[] =
+{
+ { XML_FROM_INSIDE, HoriOrientation::NONE },
+ { XML_INSIDE, HoriOrientation::LEFT },
+ { XML_CENTER, HoriOrientation::CENTER },
+ { XML_OUTSIDE, HoriOrientation::RIGHT },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+SvXMLEnumMapEntry<sal_uInt16> const pXML_HoriRel_Enum[] =
+{
+ { XML_PARAGRAPH, RelOrientation::FRAME },
+ { XML_PARAGRAPH_CONTENT, RelOrientation::PRINT_AREA },
+ { XML_PAGE, RelOrientation::PAGE_FRAME },
+ { XML_PAGE_CONTENT, RelOrientation::PAGE_PRINT_AREA },
+ { XML_PARAGRAPH_START_MARGIN, RelOrientation::FRAME_LEFT },
+ { XML_PARAGRAPH_END_MARGIN, RelOrientation::FRAME_RIGHT },
+ { XML_PAGE_START_MARGIN, RelOrientation::PAGE_LEFT },
+ { XML_PAGE_END_MARGIN, RelOrientation::PAGE_RIGHT },
+ { XML_CHAR, RelOrientation::CHAR },
+ { XML_FRAME, RelOrientation::FRAME }, // import only
+ { XML_FRAME_CONTENT, RelOrientation::PRINT_AREA }, // import only
+ { XML_FRAME_START_MARGIN, RelOrientation::FRAME_LEFT }, // import only
+ { XML_FRAME_END_MARGIN, RelOrientation::FRAME_RIGHT }, // import only
+ { XML_TOKEN_INVALID, 0 }
+};
+
+SvXMLEnumMapEntry<sal_uInt16> const pXML_HoriRelFrame_Enum[] =
+{
+ { XML_FRAME, RelOrientation::FRAME },
+ { XML_FRAME_CONTENT, RelOrientation::PRINT_AREA },
+ { XML_PAGE, RelOrientation::PAGE_FRAME },
+ { XML_PAGE_CONTENT, RelOrientation::PAGE_PRINT_AREA },
+ { XML_FRAME_START_MARGIN, RelOrientation::FRAME_LEFT },
+ { XML_FRAME_END_MARGIN, RelOrientation::FRAME_RIGHT },
+ { XML_PAGE_START_MARGIN, RelOrientation::PAGE_LEFT },
+ { XML_PAGE_END_MARGIN, RelOrientation::PAGE_RIGHT },
+ { XML_CHAR, RelOrientation::CHAR },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+SvXMLEnumMapEntry<bool> const pXML_HoriMirror_Enum[] =
+{
+ { XML_FROM_LEFT, false },
+ { XML_FROM_INSIDE, true },
+ { XML_LEFT, false },
+ { XML_INSIDE, true },
+ { XML_CENTER, false },
+ { XML_RIGHT, false },
+ { XML_OUTSIDE, true },
+ { XML_TOKEN_INVALID, false }
+};
+
+SvXMLEnumMapEntry<sal_uInt16> const pXML_VertPosAtChar_Enum[] =
+{
+ { XML_FROM_TOP, VertOrientation::NONE },
+ { XML_TOP, VertOrientation::TOP },
+ { XML_TOP, VertOrientation::CHAR_TOP }, // export only
+ { XML_TOP, VertOrientation::LINE_TOP }, // export only
+ { XML_MIDDLE, VertOrientation::CENTER },
+ { XML_MIDDLE, VertOrientation::CHAR_CENTER }, // export only
+ { XML_MIDDLE, VertOrientation::LINE_CENTER }, // export only
+ { XML_BOTTOM, VertOrientation::BOTTOM },
+ { XML_BELOW, VertOrientation::CHAR_BOTTOM }, // export only
+ { XML_BOTTOM, VertOrientation::LINE_BOTTOM }, // export only
+ { XML_TOKEN_INVALID, 0 }
+};
+
+SvXMLEnumMapEntry<sal_uInt16> const pXML_VertRel_Enum[] =
+{
+ { XML_PARAGRAPH, RelOrientation::FRAME },
+ { XML_PARAGRAPH_CONTENT, RelOrientation::PRINT_AREA },
+ { XML_CHAR, RelOrientation::CHAR },
+ // DVO, OD 17.09.2003 #i18732# - allow vertical alignment at page
+ { XML_PAGE, RelOrientation::PAGE_FRAME },
+ { XML_PAGE_CONTENT, RelOrientation::PAGE_PRINT_AREA },
+ { XML_PAGE_CONTENT_TOP, RelOrientation::PAGE_PRINT_AREA_TOP },
+ { XML_PAGE_CONTENT_BOTTOM, RelOrientation::PAGE_PRINT_AREA_BOTTOM },
+ { XML_FRAME, RelOrientation::FRAME }, // import only
+ { XML_FRAME_CONTENT, RelOrientation::PRINT_AREA }, // import only
+ // OD 13.11.2003 #i22341# - new vertical alignment at top of line
+ { XML_LINE, RelOrientation::TEXT_LINE },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+SvXMLEnumMapEntry<sal_uInt16> const pXML_VertRelPage_Enum[] =
+{
+ { XML_PAGE, RelOrientation::FRAME },
+ { XML_PAGE_CONTENT, RelOrientation::PRINT_AREA },
+ { XML_PAGE, RelOrientation::PAGE_FRAME },
+ { XML_PAGE_CONTENT, RelOrientation::PAGE_PRINT_AREA },
+ { XML_PAGE_CONTENT_TOP, RelOrientation::PAGE_PRINT_AREA_TOP },
+ { XML_PAGE_CONTENT_BOTTOM, RelOrientation::PAGE_PRINT_AREA_BOTTOM },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+SvXMLEnumMapEntry<sal_uInt16> const pXML_VertRelFrame_Enum[] =
+{
+ { XML_FRAME, RelOrientation::FRAME },
+ { XML_FRAME_CONTENT, RelOrientation::PRINT_AREA },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+SvXMLEnumMapEntry<sal_uInt16> const pXML_VertRelAsChar_Enum[] =
+{
+ { XML_BASELINE, VertOrientation::TOP },
+ { XML_BASELINE, VertOrientation::CENTER }, // export only
+ { XML_BASELINE, VertOrientation::BOTTOM }, // export only
+ { XML_TEXT, VertOrientation::CHAR_TOP },
+ { XML_TEXT, VertOrientation::CHAR_CENTER }, // export only
+ { XML_TEXT, VertOrientation::CHAR_BOTTOM }, // export only
+ { XML_LINE, VertOrientation::LINE_TOP },
+ { XML_LINE, VertOrientation::LINE_CENTER }, // export only
+ { XML_LINE, VertOrientation::LINE_BOTTOM }, // export only
+ { XML_TOKEN_INVALID, 0 }
+};
+
+SvXMLEnumMapEntry<RubyAdjust> const pXML_RubyAdjust_Enum[] =
+{
+ { XML_LEFT, RubyAdjust_LEFT },
+ { XML_CENTER, RubyAdjust_CENTER },
+ { XML_RIGHT, RubyAdjust_RIGHT },
+ { XML_DISTRIBUTE_LETTER, RubyAdjust_BLOCK },
+ { XML_DISTRIBUTE_SPACE, RubyAdjust_INDENT_BLOCK },
+ { XML_TOKEN_INVALID, RubyAdjust(0) }
+};
+
+SvXMLEnumMapEntry<sal_Int16> const pXML_RubyPosition_Enum[] =
+{
+ { XML_ABOVE, RubyPosition::ABOVE},
+ { XML_BELOW, RubyPosition::BELOW},
+ { XML_INTER_CHARACTER, RubyPosition::INTER_CHARACTER},
+ { XML_TOKEN_INVALID, 0 }
+};
+
+SvXMLEnumMapEntry<sal_uInt16> const pXML_FontRelief_Enum[] =
+{
+ { XML_NONE, FontRelief::NONE },
+ { XML_ENGRAVED, FontRelief::ENGRAVED },
+ { XML_EMBOSSED, FontRelief::EMBOSSED },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+SvXMLEnumMapEntry<sal_uInt16> const pXML_ParaVerticalAlign_Enum[] =
+{
+ { XML_TOP, ParagraphVertAlign::TOP },
+ { XML_MIDDLE, ParagraphVertAlign::CENTER },
+ { XML_BOTTOM, ParagraphVertAlign::BOTTOM },
+ { XML_BASELINE, ParagraphVertAlign::BASELINE },
+ { XML_AUTO, ParagraphVertAlign::AUTOMATIC },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+// OD 2004-05-05 #i28701#
+SvXMLEnumMapEntry<sal_uInt16> const pXML_WrapInfluenceOnPosition_Enum[] =
+{
+ // Tokens have been renamed and <XML_ITERATIVE> has been added (#i35017#)
+ { XML_ONCE_SUCCESSIVE, WrapInfluenceOnPosition::ONCE_SUCCESSIVE },
+ { XML_ONCE_CONCURRENT, WrapInfluenceOnPosition::ONCE_CONCURRENT },
+ { XML_ITERATIVE, WrapInfluenceOnPosition::ITERATIVE },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+SvXMLEnumMapEntry<drawing::TextVerticalAdjust> const pXML_VerticalAlign_Enum[] =
+{
+ { XML_TOP, drawing::TextVerticalAdjust_TOP },
+ { XML_MIDDLE, drawing::TextVerticalAdjust_CENTER },
+ { XML_BOTTOM, drawing::TextVerticalAdjust_BOTTOM },
+ { XML_JUSTIFY, drawing::TextVerticalAdjust_BLOCK },
+ { XML_TOKEN_INVALID, drawing::TextVerticalAdjust(0) }
+};
+
+namespace {
+
+class XMLDropCapPropHdl_Impl : public XMLPropertyHandler
+{
+public:
+ virtual bool equals(
+ const css::uno::Any& r1,
+ const css::uno::Any& r2 ) const override;
+
+ /// TabStops will be imported/exported as XML-Elements. So the Import/Export-work must be done at another place.
+ virtual bool importXML(
+ const OUString& rStrImpValue,
+ css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+ virtual bool exportXML(
+ OUString& rStrExpValue,
+ const css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+};
+
+}
+
+bool XMLDropCapPropHdl_Impl::equals(
+ const Any& r1,
+ const Any& r2 ) const
+{
+ DropCapFormat aFormat1, aFormat2;
+ r1 >>= aFormat1;
+ r2 >>= aFormat2;
+
+ return (aFormat1.Lines <=1 && aFormat2.Lines <=1) ||
+ (aFormat1.Lines == aFormat2.Lines &&
+ aFormat1.Count == aFormat2.Count &&
+ aFormat1.Distance == aFormat2.Distance);
+}
+
+bool XMLDropCapPropHdl_Impl::importXML(
+ const OUString&,
+ Any&,
+ const SvXMLUnitConverter& ) const
+{
+ SAL_WARN( "xmloff", "drop caps are an element import property" );
+ return false;
+}
+
+bool XMLDropCapPropHdl_Impl::exportXML(
+ OUString&,
+ const Any&,
+ const SvXMLUnitConverter& ) const
+{
+ SAL_WARN( "xmloff", "drop caps are an element export property" );
+ return false;
+}
+
+namespace {
+
+class XMLOpaquePropHdl_Impl : public XMLPropertyHandler
+{
+public:
+ virtual bool importXML(
+ const OUString& rStrImpValue,
+ css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+ virtual bool exportXML(
+ OUString& rStrExpValue,
+ const css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+};
+
+}
+
+bool XMLOpaquePropHdl_Impl::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ bool bRet = true;
+ bool bVal = false;
+ if( IsXMLToken( rStrImpValue, XML_FOREGROUND ) )
+ bVal = true;
+ else if( !IsXMLToken( rStrImpValue, XML_BACKGROUND ) )
+ bRet = false;
+
+ if( bRet )
+ rValue <<= bVal;
+
+ return bRet;
+}
+
+bool XMLOpaquePropHdl_Impl::exportXML(
+ OUString& rStrExpValue,
+ const Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ if( *o3tl::doAccess<bool>(rValue) )
+ rStrExpValue = GetXMLToken( XML_FOREGROUND );
+ else
+ rStrExpValue = GetXMLToken( XML_BACKGROUND );
+
+ return true;
+}
+
+namespace {
+
+class XMLContourModePropHdl_Impl : public XMLPropertyHandler
+{
+public:
+ virtual bool importXML(
+ const OUString& rStrImpValue,
+ css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+ virtual bool exportXML(
+ OUString& rStrExpValue,
+ const css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+};
+
+}
+
+bool XMLContourModePropHdl_Impl::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ bool bRet = true;
+ bool bVal = false;
+ if( IsXMLToken( rStrImpValue, XML_OUTSIDE ) )
+ bVal = true;
+ else if( ! IsXMLToken( rStrImpValue, XML_FULL ) )
+ bRet = false;
+
+ if( bRet )
+ rValue <<= bVal;
+
+ return bRet;
+}
+
+bool XMLContourModePropHdl_Impl::exportXML(
+ OUString& rStrExpValue,
+ const Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ if( *o3tl::doAccess<bool>(rValue) )
+ rStrExpValue = GetXMLToken( XML_OUTSIDE );
+ else
+ rStrExpValue = GetXMLToken( XML_FULL );
+
+ return true;
+}
+
+namespace {
+
+class XMLParagraphOnlyPropHdl_Impl : public XMLPropertyHandler
+{
+public:
+ virtual bool importXML(
+ const OUString& rStrImpValue,
+ css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+ virtual bool exportXML(
+ OUString& rStrExpValue,
+ const css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+};
+
+}
+
+bool XMLParagraphOnlyPropHdl_Impl::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ bool bRet = true;
+ bool bVal = false;
+
+ if( ! IsXMLToken( rStrImpValue, XML_NO_LIMIT ) )
+ {
+ sal_Int32 nValue = 0;
+ bRet = ::sax::Converter::convertNumber( nValue, rStrImpValue );
+ bVal = 1 == nValue;
+ }
+
+ if( bRet )
+ rValue <<= bVal;
+
+ return bRet;
+}
+
+bool XMLParagraphOnlyPropHdl_Impl::exportXML(
+ OUString& rStrExpValue,
+ const Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ if( *o3tl::doAccess<bool>(rValue) )
+ rStrExpValue = GetXMLToken( XML_1 );
+ else
+ rStrExpValue = GetXMLToken( XML_NO_LIMIT );
+
+ return true;
+}
+
+SvXMLEnumMapEntry<WrapTextMode> const pXML_Wrap_Enum[] =
+{
+ { XML_NONE, WrapTextMode_NONE },
+ { XML_RUN_THROUGH, WrapTextMode_THROUGH },
+ { XML_PARALLEL, WrapTextMode_PARALLEL },
+ { XML_DYNAMIC, WrapTextMode_DYNAMIC },
+ { XML_LEFT, WrapTextMode_LEFT },
+ { XML_RIGHT, WrapTextMode_RIGHT },
+ { XML_TOKEN_INVALID, WrapTextMode(0) }
+};
+
+namespace {
+
+class XMLWrapPropHdl_Impl : public XMLPropertyHandler
+{
+public:
+ virtual bool importXML(
+ const OUString& rStrImpValue,
+ css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+ virtual bool exportXML(
+ OUString& rStrExpValue,
+ const css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+};
+
+}
+
+bool XMLWrapPropHdl_Impl::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ WrapTextMode nWrap;
+ bool bRet = SvXMLUnitConverter::convertEnum( nWrap, rStrImpValue,
+ pXML_Wrap_Enum );
+
+ if( bRet )
+ rValue <<= nWrap;
+
+ return bRet;
+}
+
+bool XMLWrapPropHdl_Impl::exportXML(
+ OUString& rStrExpValue,
+ const Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ OUStringBuffer aOut;
+ WrapTextMode eVal;
+
+ rValue >>= eVal;
+
+ bool bRet = SvXMLUnitConverter::convertEnum( aOut, eVal, pXML_Wrap_Enum, XML_NONE );
+
+ rStrExpValue = aOut.makeStringAndClear();
+
+ return bRet;
+}
+
+namespace {
+
+class XMLFrameProtectPropHdl_Impl : public XMLPropertyHandler
+{
+ const OUString sVal;
+public:
+ explicit XMLFrameProtectPropHdl_Impl( enum XMLTokenEnum eVal ) :
+ sVal( GetXMLToken(eVal) ) {}
+
+ virtual bool importXML(
+ const OUString& rStrImpValue,
+ css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+ virtual bool exportXML(
+ OUString& rStrExpValue,
+ const css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+};
+
+}
+
+bool XMLFrameProtectPropHdl_Impl::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ bool bRet = true;
+ bool bVal = false;
+ if( ! IsXMLToken( rStrImpValue, XML_NONE ) )
+ {
+ bRet = false;
+ SvXMLTokenEnumerator aTokenEnum( rStrImpValue );
+ std::u16string_view aToken;
+ while( aTokenEnum.getNextToken( aToken ) )
+ {
+ bRet = true;
+ if( aToken == sVal )
+ {
+ bVal = true;
+ break;
+ }
+ }
+ }
+
+ if( bRet )
+ rValue <<= bVal;
+
+ return bRet;
+}
+
+bool XMLFrameProtectPropHdl_Impl::exportXML(
+ OUString& rStrExpValue,
+ const Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ if( *o3tl::doAccess<bool>(rValue) )
+ {
+ if( rStrExpValue.isEmpty() ||
+ IsXMLToken( rStrExpValue, XML_NONE ) )
+ {
+ rStrExpValue = sVal;
+ }
+ else
+ {
+ rStrExpValue += " " + sVal;
+ }
+ }
+ else if( rStrExpValue.isEmpty() )
+ {
+ rStrExpValue = GetXMLToken( XML_NONE );
+ }
+
+ return true;
+}
+
+SvXMLEnumMapEntry<TextContentAnchorType> const pXML_Anchor_Enum[] =
+{
+ { XML_CHAR, TextContentAnchorType_AT_CHARACTER },
+ { XML_PAGE, TextContentAnchorType_AT_PAGE },
+ { XML_FRAME, TextContentAnchorType_AT_FRAME },
+ { XML_PARAGRAPH, TextContentAnchorType_AT_PARAGRAPH },
+ { XML_AS_CHAR, TextContentAnchorType_AS_CHARACTER },
+ { XML_TOKEN_INVALID, TextContentAnchorType(0) }
+};
+
+bool XMLAnchorTypePropHdl::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ TextContentAnchorType nAnchor;
+ bool bRet = SvXMLUnitConverter::convertEnum( nAnchor, rStrImpValue,
+ pXML_Anchor_Enum );
+
+ if( bRet )
+ rValue <<= nAnchor;
+
+ return bRet;
+}
+
+bool XMLAnchorTypePropHdl::exportXML(
+ OUString& rStrExpValue,
+ const Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ OUStringBuffer aOut;
+ TextContentAnchorType eVal;
+
+ rValue >>= eVal;
+
+ bool bRet = SvXMLUnitConverter::convertEnum( aOut, eVal, pXML_Anchor_Enum, XML_PARAGRAPH );
+
+ rStrExpValue = aOut.makeStringAndClear();
+
+ return bRet;
+}
+
+XMLAnchorTypePropHdl::~XMLAnchorTypePropHdl()
+{
+}
+
+bool XMLAnchorTypePropHdl::convert( std::string_view rStrImpValue,
+ TextContentAnchorType& rType )
+{
+ TextContentAnchorType nAnchor;
+ bool bRet = SvXMLUnitConverter::convertEnum( nAnchor, rStrImpValue,
+ pXML_Anchor_Enum );
+ if( bRet )
+ rType = nAnchor;
+ return bRet;
+}
+
+XMLTextColumnsPropertyHandler::~XMLTextColumnsPropertyHandler ()
+{
+}
+
+bool XMLTextColumnsPropertyHandler::equals(
+ const Any& r1,
+ const Any& r2 ) const
+{
+ Reference < XTextColumns > xColumns1;
+ r1 >>= xColumns1;
+
+ Reference < XTextColumns > xColumns2;
+ r2 >>= xColumns2;
+
+ if (!xColumns1 || !xColumns2)
+ return (!xColumns1 && !xColumns2);
+
+ if( xColumns1->getColumnCount() != xColumns2->getColumnCount() ||
+ xColumns1->getReferenceValue() != xColumns2->getReferenceValue() )
+ return false;
+
+ const Sequence < TextColumn > aColumns1 = xColumns1->getColumns();
+ const Sequence < TextColumn > aColumns2 = xColumns2->getColumns();
+
+ return std::equal(aColumns1.begin(), aColumns1.end(), aColumns2.begin(), aColumns2.end(),
+ [](const TextColumn& a, const TextColumn& b) {
+ return a.Width == b.Width
+ && a.LeftMargin == b.LeftMargin
+ && a.RightMargin == b.RightMargin;
+ });
+}
+
+bool XMLTextColumnsPropertyHandler::importXML(
+ const OUString&,
+ Any&,
+ const SvXMLUnitConverter& ) const
+{
+ SAL_WARN( "xmloff", "columns are an element import property" );
+ return false;
+}
+
+bool XMLTextColumnsPropertyHandler::exportXML(
+ OUString&,
+ const Any&,
+ const SvXMLUnitConverter& ) const
+{
+ SAL_WARN( "xmloff", "columns are an element export property" );
+ return false;
+}
+
+namespace {
+
+class XMLHoriMirrorPropHdl_Impl : public XMLPropertyHandler
+{
+public:
+ virtual bool importXML(
+ const OUString& rStrImpValue,
+ css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+ virtual bool exportXML(
+ OUString& rStrExpValue,
+ const css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+};
+
+}
+
+bool XMLHoriMirrorPropHdl_Impl::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ bool nHoriMirror;
+ bool bRet = SvXMLUnitConverter::convertEnum( nHoriMirror, rStrImpValue,
+ pXML_HoriMirror_Enum );
+
+ if( bRet )
+ {
+ rValue <<= nHoriMirror;
+ }
+
+ return bRet;
+}
+
+bool XMLHoriMirrorPropHdl_Impl::exportXML(
+ OUString&,
+ const Any&,
+ const SvXMLUnitConverter& ) const
+{
+ SAL_WARN( "xmloff", "HorMirror property shouldn't be exported" );
+
+ return false;
+}
+
+namespace {
+
+class XMLGrfMirrorPropHdl_Impl : public XMLPropertyHandler
+{
+ const OUString sVal;
+ bool bHori;
+
+public:
+ XMLGrfMirrorPropHdl_Impl( enum XMLTokenEnum eVal, bool bH ) :
+ sVal( GetXMLToken( eVal ) ),
+ bHori( bH ) {}
+
+ virtual bool importXML(
+ const OUString& rStrImpValue,
+ css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+ virtual bool exportXML(
+ OUString& rStrExpValue,
+ const css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+};
+
+}
+
+bool XMLGrfMirrorPropHdl_Impl::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ bool bRet = true;
+ bool bVal = false;
+ if( ! IsXMLToken( rStrImpValue, XML_NONE ) )
+ {
+ bRet = false;
+ SvXMLTokenEnumerator aTokenEnum( rStrImpValue );
+ std::u16string_view aToken;
+ while( aTokenEnum.getNextToken( aToken ) )
+ {
+ bRet = true;
+ if( aToken == sVal ||
+ (bHori && IsXMLToken( aToken, XML_HORIZONTAL ) ) )
+ {
+ bVal = true;
+ break;
+ }
+ }
+ }
+
+ if( bRet )
+ rValue <<= bVal;
+
+ return bRet;
+}
+
+bool XMLGrfMirrorPropHdl_Impl::exportXML(
+ OUString& rStrExpValue,
+ const Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ if( *o3tl::doAccess<bool>(rValue) )
+ {
+ if( rStrExpValue.isEmpty() ||
+ IsXMLToken( rStrExpValue, XML_NONE ) )
+ {
+ rStrExpValue = sVal;
+ }
+ else if( bHori &&
+ /* XML_HORIZONTAL_ON_LEFT_PAGES and XML_HORIZONTAL_ON_RIGHT_PAGES
+ are replaced by XML_HORIZONTAL_ON_EVEN and XML_HORIZONTAL_ON_ODD.
+ (#i49139#)
+ */
+ ( IsXMLToken( rStrExpValue, XML_HORIZONTAL_ON_EVEN ) ||
+ IsXMLToken( rStrExpValue, XML_HORIZONTAL_ON_ODD ) ))
+ {
+ rStrExpValue = GetXMLToken( XML_HORIZONTAL );
+ }
+ else
+ {
+ rStrExpValue += " " + sVal;
+ }
+ }
+ else if( rStrExpValue.isEmpty() )
+ {
+ rStrExpValue = GetXMLToken( XML_NONE );
+ }
+
+ return true;
+}
+
+SvXMLEnumMapEntry<sal_uInt16> const pXML_Emphasize_Enum[] =
+{
+ { XML_NONE, FontEmphasis::NONE },
+ { XML_DOT, FontEmphasis::DOT_ABOVE },
+ { XML_CIRCLE, FontEmphasis::CIRCLE_ABOVE },
+ { XML_DISC, FontEmphasis::DISK_ABOVE },
+ { XML_ACCENT, FontEmphasis::ACCENT_ABOVE },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+namespace {
+
+class XMLTextEmphasizePropHdl_Impl : public XMLPropertyHandler
+{
+public:
+ XMLTextEmphasizePropHdl_Impl() {}
+
+ virtual bool importXML(
+ const OUString& rStrImpValue,
+ css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+ virtual bool exportXML(
+ OUString& rStrExpValue,
+ const css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+};
+
+}
+
+bool XMLTextEmphasizePropHdl_Impl::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ bool bRet = true;
+ sal_uInt16 nVal = FontEmphasis::NONE;
+ bool bBelow = false;
+ bool bHasPos = false, bHasType = false;
+ std::u16string_view aToken;
+
+ SvXMLTokenEnumerator aTokenEnum( rStrImpValue );
+ while( aTokenEnum.getNextToken( aToken ) )
+ {
+ if( !bHasPos && IsXMLToken( aToken, XML_ABOVE ) )
+ {
+ bBelow = false;
+ bHasPos = true;
+ }
+ else if( !bHasPos && IsXMLToken( aToken, XML_BELOW ) )
+ {
+ bBelow = true;
+ bHasPos = true;
+ }
+ else if( !bHasType &&
+ SvXMLUnitConverter::convertEnum( nVal, aToken,
+ pXML_Emphasize_Enum ))
+ {
+ bHasType = true;
+ }
+ else
+ {
+ bRet = false;
+ break;
+ }
+ }
+
+ if( bRet )
+ {
+ if( FontEmphasis::NONE != nVal && bBelow )
+ nVal += 10;
+ rValue <<= static_cast<sal_Int16>(nVal);
+ }
+
+ return bRet;
+}
+
+bool XMLTextEmphasizePropHdl_Impl::exportXML(
+ OUString& rStrExpValue,
+ const Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ OUStringBuffer aOut( 15 );
+ bool bRet = true;
+ sal_uInt16 nType = sal_uInt16();
+ if( rValue >>= nType )
+ {
+ bool bBelow = false;
+ if( nType > 10 )
+ {
+ bBelow = true;
+ nType -= 10;
+ }
+ bRet = SvXMLUnitConverter::convertEnum( aOut, nType,
+ pXML_Emphasize_Enum,
+ XML_DOT );
+ if( bRet )
+ {
+ if( nType != 0 )
+ {
+ enum XMLTokenEnum ePos = bBelow ? XML_BELOW : XML_ABOVE;
+ aOut.append( " " + GetXMLToken(ePos) );
+ }
+ rStrExpValue = aOut.makeStringAndClear();
+ }
+ }
+
+ return bRet;
+}
+
+namespace {
+
+class XMLTextCombineCharPropHdl_Impl : public XMLPropertyHandler
+{
+public:
+ XMLTextCombineCharPropHdl_Impl() {}
+
+ virtual bool importXML(
+ const OUString& rStrImpValue,
+ css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+ virtual bool exportXML(
+ OUString& rStrExpValue,
+ const css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+};
+
+}
+
+bool XMLTextCombineCharPropHdl_Impl::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ if( !rStrImpValue.isEmpty() )
+ rValue <<= rStrImpValue.copy( 0, 1 );
+ else
+ rValue <<= rStrImpValue;
+
+ return true;
+}
+
+bool XMLTextCombineCharPropHdl_Impl::exportXML(
+ OUString& rStrExpValue,
+ const Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ rValue >>= rStrExpValue;
+
+ // #i114107# attribute of type "character": export only if length is 1
+ return (1 == rStrExpValue.getLength());
+}
+
+namespace {
+
+class XMLTextRelWidthHeightPropHdl_Impl : public XMLPropertyHandler
+{
+public:
+ XMLTextRelWidthHeightPropHdl_Impl() {}
+
+ virtual bool importXML(
+ const OUString& rStrImpValue,
+ css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+ virtual bool exportXML(
+ OUString& rStrExpValue,
+ const css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+};
+
+}
+
+bool XMLTextRelWidthHeightPropHdl_Impl::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ sal_Int32 nValue;
+ bool const bRet = ::sax::Converter::convertPercent( nValue, rStrImpValue );
+ if( bRet )
+ rValue <<= static_cast<sal_Int16>(nValue);
+
+ return bRet;
+}
+
+bool XMLTextRelWidthHeightPropHdl_Impl::exportXML(
+ OUString& rStrExpValue,
+ const Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ sal_Int16 nValue = sal_Int16();
+ if( (rValue >>= nValue) && nValue > 0 )
+ {
+ OUStringBuffer aOut;
+ ::sax::Converter::convertPercent( aOut, nValue );
+ rStrExpValue = aOut.makeStringAndClear();
+
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+namespace {
+
+class XMLTextSyncWidthHeightPropHdl_Impl : public XMLPropertyHandler
+{
+ const OUString sValue;
+
+public:
+ explicit XMLTextSyncWidthHeightPropHdl_Impl( enum XMLTokenEnum eValue ) :
+ sValue( GetXMLToken(eValue) ) {}
+
+ virtual bool importXML(
+ const OUString& rStrImpValue,
+ css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+ virtual bool exportXML(
+ OUString& rStrExpValue,
+ const css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+};
+
+}
+
+bool XMLTextSyncWidthHeightPropHdl_Impl::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ rValue <<= (rStrImpValue == sValue);
+
+ return true;
+}
+
+bool XMLTextSyncWidthHeightPropHdl_Impl::exportXML(
+ OUString& rStrExpValue,
+ const Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ bool bRet = false;
+ if( *o3tl::doAccess<bool>(rValue) )
+ {
+ rStrExpValue = sValue;
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+namespace {
+
+class XMLTextRotationAnglePropHdl_Impl : public XMLPropertyHandler
+{
+
+public:
+ XMLTextRotationAnglePropHdl_Impl() {}
+
+ virtual bool importXML(
+ const OUString& rStrImpValue,
+ css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+ virtual bool exportXML(
+ OUString& rStrExpValue,
+ const css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+};
+
+}
+
+bool XMLTextRotationAnglePropHdl_Impl::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ sal_Int32 nValue;
+ bool const bRet = ::sax::Converter::convertNumber( nValue, rStrImpValue );
+ if( bRet )
+ {
+ nValue = (nValue % 360 );
+ if( nValue < 0 )
+ nValue = 360 + nValue;
+ sal_Int16 nAngle;
+ if( nValue < 45 || nValue > 315 )
+ nAngle = 0;
+ else if( nValue < 180 )
+ nAngle = 900;
+ else /* if nValue <= 315 ) */
+ nAngle = 2700;
+ rValue <<= nAngle;
+ }
+
+ return bRet;
+}
+
+bool XMLTextRotationAnglePropHdl_Impl::exportXML(
+ OUString& rStrExpValue,
+ const Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ sal_Int16 nAngle = sal_Int16();
+ bool bRet = ( rValue >>= nAngle );
+ if( bRet )
+ {
+ rStrExpValue = OUString::number( nAngle / 10 );
+ }
+ OSL_ENSURE( bRet, "illegal rotation angle" );
+
+ return bRet;
+}
+
+namespace {
+
+class XMLNumber8OneBasedHdl : public XMLPropertyHandler
+{
+
+public:
+ XMLNumber8OneBasedHdl() {}
+
+ virtual bool importXML(
+ const OUString& rStrImpValue,
+ css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+ virtual bool exportXML(
+ OUString& rStrExpValue,
+ const css::uno::Any& rValue,
+ const SvXMLUnitConverter& ) const override;
+};
+
+}
+
+bool XMLNumber8OneBasedHdl::importXML(
+ const OUString& rStrImpValue,
+ Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ sal_Int32 nValue = 0;
+ bool const bRet = ::sax::Converter::convertNumber(nValue, rStrImpValue);
+ if( bRet )
+ rValue <<= static_cast<sal_Int8>( nValue - 1 );
+ return bRet;
+}
+
+bool XMLNumber8OneBasedHdl::exportXML(
+ OUString& rStrExpValue,
+ const Any& rValue,
+ const SvXMLUnitConverter& ) const
+{
+ sal_Int8 nValue = sal_Int8();
+ bool bRet = ( rValue >>= nValue );
+ if( bRet )
+ {
+ rStrExpValue = OUString::number( nValue + 1 );
+ }
+ return bRet;
+}
+
+namespace {
+
+class XMLGraphicPropertyHandler : public XMLPropertyHandler
+{
+public:
+ XMLGraphicPropertyHandler() {}
+
+ virtual bool importXML(const OUString& , uno::Any& , const SvXMLUnitConverter& ) const override
+ {
+ SAL_WARN( "xmloff", "drop caps are an element import property" );
+ return false;
+ }
+
+ virtual bool exportXML(OUString& , const uno::Any& , const SvXMLUnitConverter& ) const override
+ {
+ SAL_WARN( "xmloff", "drop caps are an element import property" );
+ return false;
+ }
+
+ virtual bool equals(const css::uno::Any& rAny1, const css::uno::Any& rAny2) const override;
+};
+
+}
+
+bool XMLGraphicPropertyHandler::equals(const Any& rAny1, const Any& rAny2) const
+{
+ uno::Reference<graphic::XGraphic> xGraphic1;
+ uno::Reference<graphic::XGraphic> xGraphic2;
+ rAny1 >>= xGraphic1;
+ rAny2 >>= xGraphic2;
+ Graphic aGraphic1(xGraphic1);
+ Graphic aGraphic2(xGraphic2);
+
+ return aGraphic1 == aGraphic2;
+}
+
+static const XMLPropertyHandler *GetPropertyHandler
+ ( sal_Int32 nType )
+{
+ const XMLPropertyHandler* pHdl = nullptr;
+ switch( nType )
+ {
+ case XML_TYPE_TEXT_DROPCAP:
+ pHdl = new XMLDropCapPropHdl_Impl;
+ break;
+ case XML_TYPE_TEXT_WRAP:
+ pHdl = new XMLWrapPropHdl_Impl;
+ break;
+ case XML_TYPE_TEXT_PARAGRAPH_ONLY:
+ pHdl = new XMLParagraphOnlyPropHdl_Impl;
+ break;
+ case XML_TYPE_TEXT_WRAP_OUTSIDE:
+ pHdl = new XMLContourModePropHdl_Impl;
+ break;
+ case XML_TYPE_TEXT_OPAQUE:
+ pHdl = new XMLOpaquePropHdl_Impl;
+ break;
+ case XML_TYPE_TEXT_PROTECT_CONTENT:
+ pHdl = new XMLFrameProtectPropHdl_Impl( XML_CONTENT );
+ break;
+ case XML_TYPE_TEXT_PROTECT_SIZE:
+ pHdl = new XMLFrameProtectPropHdl_Impl( XML_SIZE );
+ break;
+ case XML_TYPE_TEXT_PROTECT_POSITION:
+ pHdl = new XMLFrameProtectPropHdl_Impl( XML_POSITION );
+ break;
+ case XML_TYPE_TEXT_ANCHOR_TYPE:
+ pHdl = new XMLAnchorTypePropHdl;
+ break;
+ case XML_TYPE_TEXT_COLUMNS:
+ pHdl = new XMLTextColumnsPropertyHandler;
+ break;
+ case XML_TYPE_TEXT_HORIZONTAL_POS:
+ pHdl = new XMLConstantsPropertyHandler( pXML_HoriPos_Enum, XML_TOKEN_INVALID );
+ break;
+ case XML_TYPE_TEXT_HORIZONTAL_POS_MIRRORED:
+ pHdl = new XMLConstantsPropertyHandler( pXML_HoriPosMirrored_Enum, XML_TOKEN_INVALID );
+ break;
+ case XML_TYPE_TEXT_HORIZONTAL_REL:
+ pHdl = new XMLConstantsPropertyHandler( pXML_HoriRel_Enum, XML_TOKEN_INVALID );
+ break;
+ case XML_TYPE_TEXT_HORIZONTAL_REL_FRAME:
+ pHdl = new XMLConstantsPropertyHandler( pXML_HoriRelFrame_Enum, XML_TOKEN_INVALID );
+ break;
+ case XML_TYPE_TEXT_HORIZONTAL_MIRROR:
+ pHdl = new XMLHoriMirrorPropHdl_Impl;
+ break;
+ case XML_TYPE_TEXT_VERTICAL_POS_AT_CHAR:
+ pHdl = new XMLConstantsPropertyHandler( pXML_VertPosAtChar_Enum, XML_TOKEN_INVALID );
+ break;
+ case XML_TYPE_TEXT_VERTICAL_REL:
+ pHdl = new XMLConstantsPropertyHandler( pXML_VertRel_Enum, XML_TOKEN_INVALID );
+ break;
+ case XML_TYPE_TEXT_VERTICAL_REL_PAGE:
+ pHdl = new XMLConstantsPropertyHandler( pXML_VertRelPage_Enum, XML_TOKEN_INVALID );
+ break;
+ case XML_TYPE_TEXT_VERTICAL_REL_FRAME:
+ pHdl = new XMLConstantsPropertyHandler( pXML_VertRelFrame_Enum, XML_TOKEN_INVALID );
+ break;
+ case XML_TYPE_TEXT_VERTICAL_REL_AS_CHAR:
+ pHdl = new XMLConstantsPropertyHandler( pXML_VertRelAsChar_Enum, XML_TOKEN_INVALID );
+ break;
+ case XML_TYPE_TEXT_MIRROR_VERTICAL:
+ pHdl = new XMLGrfMirrorPropHdl_Impl( XML_VERTICAL, false );
+ break;
+ case XML_TYPE_TEXT_MIRROR_HORIZONTAL_LEFT:
+ // XML_HORIZONTAL_ON_LEFT_PAGES is replaced by XML_HORIZONTAL_ON_EVEN. (#i49139#)
+ pHdl = new XMLGrfMirrorPropHdl_Impl( XML_HORIZONTAL_ON_EVEN, true );
+ break;
+ case XML_TYPE_TEXT_MIRROR_HORIZONTAL_RIGHT:
+ // XML_HORIZONTAL_ON_RIGHT_PAGES is replaced by XML_HORIZONTAL_ON_ODD. (#i49139#)
+ pHdl = new XMLGrfMirrorPropHdl_Impl( XML_HORIZONTAL_ON_ODD, true );
+ break;
+ case XML_TYPE_TEXT_CLIP:
+ pHdl = new XMLClipPropertyHandler( false );
+ break;
+ case XML_TYPE_TEXT_CLIP11:
+ pHdl = new XMLClipPropertyHandler( true );
+ break;
+ case XML_TYPE_TEXT_EMPHASIZE:
+ pHdl = new XMLTextEmphasizePropHdl_Impl;
+ break;
+ case XML_TYPE_TEXT_COMBINE:
+ pHdl = new XMLNamedBoolPropertyHdl( GetXMLToken( XML_LINES ),
+ GetXMLToken( XML_NONE ) );
+ break;
+ case XML_TYPE_TEXT_COMBINE_CHARACTERS:
+ pHdl = new XMLNamedBoolPropertyHdl( GetXMLToken( XML_LETTERS ),
+ GetXMLToken( XML_NONE ) );
+ break;
+ case XML_TYPE_TEXT_COMBINECHAR:
+ pHdl = new XMLTextCombineCharPropHdl_Impl;
+ break;
+ case XML_TYPE_TEXT_AUTOSPACE:
+ pHdl = new XMLNamedBoolPropertyHdl( GetXMLToken( XML_IDEOGRAPH_ALPHA ),
+ GetXMLToken( XML_NONE ) );
+ break;
+ case XML_TYPE_TEXT_PUNCTUATION_WRAP:
+ pHdl = new XMLNamedBoolPropertyHdl( GetXMLToken( XML_HANGING ),
+ GetXMLToken( XML_SIMPLE ) );
+ break;
+ case XML_TYPE_TEXT_LINE_BREAK:
+ pHdl = new XMLNamedBoolPropertyHdl( GetXMLToken( XML_STRICT ),
+ GetXMLToken( XML_NORMAL ) );
+ break;
+ case XML_TYPE_TEXT_REL_WIDTH_HEIGHT:
+ pHdl = new XMLTextRelWidthHeightPropHdl_Impl;
+ break;
+ case XML_TYPE_TEXT_SYNC_WIDTH_HEIGHT:
+ pHdl = new XMLTextSyncWidthHeightPropHdl_Impl( XML_SCALE );
+ break;
+ case XML_TYPE_TEXT_SYNC_WIDTH_HEIGHT_MIN:
+ pHdl = new XMLTextSyncWidthHeightPropHdl_Impl( XML_SCALE_MIN );
+ break;
+ case XML_TYPE_TEXT_RUBY_ADJUST:
+ pHdl = new XMLConstantsPropertyHandler( pXML_RubyAdjust_Enum, XML_TOKEN_INVALID );
+ break;
+ case XML_TYPE_TEXT_FONT_RELIEF:
+ pHdl = new XMLConstantsPropertyHandler( pXML_FontRelief_Enum, XML_TOKEN_INVALID );
+ break;
+ case XML_TYPE_TEXT_ROTATION_ANGLE:
+ pHdl = new XMLTextRotationAnglePropHdl_Impl;
+ break;
+ case XML_TYPE_TEXT_ROTATION_SCALE:
+ pHdl = new XMLNamedBoolPropertyHdl( GetXMLToken( XML_FIXED ),
+ GetXMLToken( XML_LINE_HEIGHT ) );
+ break;
+ case XML_TYPE_TEXT_VERTICAL_ALIGN:
+ pHdl = new XMLConstantsPropertyHandler( pXML_ParaVerticalAlign_Enum, XML_TOKEN_INVALID );
+ break;
+ case XML_TYPE_TEXT_RUBY_POSITION:
+ pHdl = new XMLConstantsPropertyHandler( pXML_RubyPosition_Enum, XML_TOKEN_INVALID );
+ break;
+ case XML_TYPE_TEXT_RUBY_IS_ABOVE:
+ pHdl = new XMLNamedBoolPropertyHdl(::xmloff::token::XML_ABOVE, ::xmloff::token::XML_BELOW);
+ break;
+ // OD 2004-05-05 #i28701#
+ case XML_TYPE_WRAP_INFLUENCE_ON_POSITION:
+ pHdl = new XMLConstantsPropertyHandler( pXML_WrapInfluenceOnPosition_Enum,
+ XML_TOKEN_INVALID );
+ break;
+ case XML_TYPE_BORDER_MODEL:
+ pHdl = new XMLNamedBoolPropertyHdl( xmloff::token::XML_COLLAPSING,
+ xmloff::token::XML_SEPARATING );
+ break;
+ case XML_TYPE_TEXT_LINE_MODE:
+ pHdl = new XMLNamedBoolPropertyHdl(
+ ::xmloff::token::XML_SKIP_WHITE_SPACE,
+ ::xmloff::token::XML_CONTINUOUS);
+ break;
+ case XML_TYPE_TEXT_KEEP:
+ pHdl = new XMLNamedBoolPropertyHdl(
+ ::xmloff::token::XML_ALWAYS,
+ ::xmloff::token::XML_AUTO);
+ break;
+ case XML_TYPE_TEXT_NKEEP:
+ pHdl = new XMLNamedBoolPropertyHdl(
+ ::xmloff::token::XML_AUTO,
+ ::xmloff::token::XML_ALWAYS);
+ break;
+ case XML_TYPE_TEXT_NUMBER8_ONE_BASED:
+ pHdl = new XMLNumber8OneBasedHdl();
+ break;
+ case XML_TYPE_VERTICAL_ALIGN:
+ pHdl = new XMLConstantsPropertyHandler( pXML_VerticalAlign_Enum, XML_TOKEN_INVALID );
+ break;
+
+ case XML_SW_TYPE_FILLSTYLE:
+ pHdl = new XMLEnumPropertyHdl( aXML_FillStyle_EnumMap);
+ break;
+ case XML_SW_TYPE_FILLBITMAPSIZE:
+ pHdl = new XMLFillBitmapSizePropertyHandler();
+ break;
+ case XML_SW_TYPE_LOGICAL_SIZE:
+ pHdl = new XMLBitmapLogicalSizePropertyHandler();
+ break;
+ case XML_SW_TYPE_BITMAP_REFPOINT:
+ pHdl = new XMLEnumPropertyHdl( aXML_RefPoint_EnumMap);
+ break;
+ case XML_SW_TYPE_BITMAP_MODE:
+ pHdl = new XMLEnumPropertyHdl( aXML_BitmapMode_EnumMap);
+ break;
+ case XML_SW_TYPE_BITMAPREPOFFSETX:
+ case XML_SW_TYPE_BITMAPREPOFFSETY:
+ pHdl = new XMLBitmapRepeatOffsetPropertyHandler(XML_SW_TYPE_BITMAPREPOFFSETX == nType);
+ break;
+ case XML_TYPE_GRAPHIC:
+ pHdl = new XMLGraphicPropertyHandler;
+ break;
+ case XML_TYPE_COMPLEX_COLOR:
+ pHdl = new XMLComplexColorHandler;
+ break;
+ default:
+ {
+ OSL_ENSURE(false, "XMLPropertyHandler missing (!)");
+ break;
+ }
+ }
+
+ return pHdl;
+}
+
+XMLTextPropertyHandlerFactory::XMLTextPropertyHandlerFactory()
+{
+}
+
+const XMLPropertyHandler *XMLTextPropertyHandlerFactory::GetPropertyHandler(
+ sal_Int32 nType ) const
+{
+ const XMLPropertyHandler *pHdl =
+ XMLPropertyHandlerFactory::GetPropertyHandler( nType );
+
+ if( !pHdl )
+ {
+ const XMLPropertyHandler *pNewHdl = ::GetPropertyHandler( nType );
+
+ if( pNewHdl )
+ PutHdlCache( nType, pNewHdl );
+
+ pHdl = pNewHdl;
+ }
+
+ return pHdl;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/txtprhdl.hxx b/xmloff/source/text/txtprhdl.hxx
new file mode 100644
index 0000000000..632d4fe88d
--- /dev/null
+++ b/xmloff/source/text/txtprhdl.hxx
@@ -0,0 +1,31 @@
+/* -*- 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 .
+ */
+#pragma once
+
+#include <xmloff/prhdlfac.hxx>
+
+class XMLTextPropertyHandlerFactory : public XMLPropertyHandlerFactory
+{
+public:
+ XMLTextPropertyHandlerFactory();
+
+ virtual const XMLPropertyHandler* GetPropertyHandler(sal_Int32 nType) const override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/txtprmap.cxx b/xmloff/source/text/txtprmap.cxx
new file mode 100644
index 0000000000..cf6adc9a19
--- /dev/null
+++ b/xmloff/source/text/txtprmap.cxx
@@ -0,0 +1,1159 @@
+/* -*- 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 <xmloff/txtprmap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/maptype.hxx>
+#include <xmloff/xmltypes.hxx>
+#include "txtprhdl.hxx"
+#include <xmlsdtypes.hxx>
+#include <sal/log.hxx>
+#include <rtl/ref.hxx>
+#include <xmlprop.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::xmloff::token;
+
+#define M_E_( a, p, l, t, c ) \
+ { a, p, l, t, c, SvtSaveOptions::ODFSVER_010, false }
+
+#define M_EV_( a, p, l, t, c, v ) \
+ { a, p, l, t, c, v, false }
+
+#define M_ED_( a, p, l, t, c ) \
+ { a, p, l, (t) | MID_FLAG_DEFAULT_ITEM_EXPORT, c, SvtSaveOptions::ODFSVER_010, false }
+
+// text properties
+#define MT_E( a, p, l, t, c ) \
+ M_E_( a, p, l, (t|XML_TYPE_PROP_TEXT), c )
+#define MT_ED( a, p, l, t, c ) \
+ M_ED_( a, p, l, (t|XML_TYPE_PROP_TEXT), c )
+
+// paragraph properties
+#define MP_E( a, p, l, t, c ) \
+ M_E_( a, p, l, (t|XML_TYPE_PROP_PARAGRAPH), c )
+#define MP_ED( a, p, l, t, c ) \
+ M_ED_( a, p, l, (t|XML_TYPE_PROP_PARAGRAPH), c )
+
+// graphic properties
+#define MG_E( a, p, l, t, c ) \
+ M_E_( a, p, l, (t|XML_TYPE_PROP_GRAPHIC), c )
+#define MG_ED( a, p, l, t, c ) \
+ M_ED_( a, p, l, (t|XML_TYPE_PROP_GRAPHIC), c )
+#define MG_EV( a, p, l, t, c, v ) \
+ M_EV_( a, p, l, (t|XML_TYPE_PROP_GRAPHIC), c, v )
+
+// section properties
+#define MS_E( a, p, l, t, c ) \
+ M_E_( a, p, l, (t|XML_TYPE_PROP_SECTION), c )
+
+// ruby properties
+#define MR_E( a, p, l, t, c ) \
+ M_E_( a, p, l, (t|XML_TYPE_PROP_RUBY), c )
+#define MR_EV( a, p, l, t, c, v ) \
+ M_EV_( a, p, l, (t|XML_TYPE_PROP_RUBY), c, v )
+
+// cell properties
+#define MC_E( a, p, l, t, c ) \
+ M_E_( a, p, l, (t|XML_TYPE_PROP_TABLE_CELL), c )
+
+#define MAP_ODF13(name,prefix,token,type,context) { name, prefix, token, type, context, SvtSaveOptions::ODFSVER_013, false }
+
+// extensions import/export
+#define MAP_EXT(name,prefix,token,type,context) { name, prefix, token, type, context, SvtSaveOptions::ODFSVER_FUTURE_EXTENDED, false }
+// extensions import only
+#define MAP_EXT_I(name,prefix,token,type,context) { name, prefix, token, type, context, SvtSaveOptions::ODFSVER_FUTURE_EXTENDED, true }
+
+#define M_END() { nullptr }
+
+#define MAP_(name,prefix,token,type,context) { name, prefix, token, type, context, SvtSaveOptions::ODFSVER_010, false }
+#define GMAP(name,prefix,token,type,context) MAP_(name,prefix,token,static_cast<sal_Int32>(type|XML_TYPE_PROP_GRAPHIC),context)
+
+XMLPropertyMapEntry constexpr aXMLParaPropMap[] =
+{
+ // RES_UNKNOWNATR_CONTAINER
+ MP_E( PROP_ParaUserDefinedAttributes, XML_NAMESPACE_TEXT, XML_XMLNS, XML_TYPE_ATTRIBUTE_CONTAINER | MID_FLAG_SPECIAL_ITEM, 0 ),
+
+ // fill attributes for paragraph backgrounds
+ // #i125045# moved to the front to be able to exclude these in lcl_txtprmap_getMap
+ // for TextPropMap::SHAPE_PARA to not have these double for Shapes (which already have these)
+ GMAP( PROP_FillStyle, XML_NAMESPACE_DRAW, XML_FILL, XML_SW_TYPE_FILLSTYLE, 0 ),
+ GMAP( PROP_FillColor, XML_NAMESPACE_DRAW, XML_FILL_COLOR, XML_TYPE_COLOR, 0 ),
+ GMAP( PROP_FillColor2, XML_NAMESPACE_DRAW, XML_SECONDARY_FILL_COLOR, XML_TYPE_COLOR, 0 ),
+ GMAP( PROP_FillGradientName, XML_NAMESPACE_DRAW, XML_FILL_GRADIENT_NAME, XML_TYPE_STYLENAME|MID_FLAG_NO_PROPERTY_IMPORT, CTF_FILLGRADIENTNAME ),
+ GMAP( PROP_FillGradientStepCount, XML_NAMESPACE_DRAW, XML_GRADIENT_STEP_COUNT, XML_TYPE_NUMBER16, 0 ),
+ GMAP( PROP_FillHatchName, XML_NAMESPACE_DRAW, XML_FILL_HATCH_NAME, XML_TYPE_STYLENAME|MID_FLAG_NO_PROPERTY_IMPORT, CTF_FILLHATCHNAME ),
+ GMAP( PROP_FillBackground, XML_NAMESPACE_DRAW, XML_FILL_HATCH_SOLID, XML_TYPE_BOOL, 0 ),
+ GMAP( PROP_FillBitmapName, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_NAME, XML_TYPE_STYLENAME|MID_FLAG_NO_PROPERTY_IMPORT, CTF_FILLBITMAPNAME ),
+ GMAP( PROP_FillTransparence, XML_NAMESPACE_DRAW, XML_OPACITY, XML_TYPE_NEG_PERCENT16|MID_FLAG_MULTI_PROPERTY, 0 ), // exists in SW, too
+ GMAP( PROP_FillTransparenceGradientName, XML_NAMESPACE_DRAW, XML_OPACITY_NAME, XML_TYPE_STYLENAME|MID_FLAG_NO_PROPERTY_IMPORT, CTF_FILLTRANSNAME ),
+ GMAP( PROP_FillBitmapSizeX, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_WIDTH, XML_SW_TYPE_FILLBITMAPSIZE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ GMAP( PROP_FillBitmapLogicalSize, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_WIDTH, XML_SW_TYPE_LOGICAL_SIZE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ GMAP( PROP_FillBitmapSizeY, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_HEIGHT, XML_SW_TYPE_FILLBITMAPSIZE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ GMAP( PROP_FillBitmapLogicalSize, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_HEIGHT, XML_SW_TYPE_LOGICAL_SIZE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ GMAP( PROP_FillBitmapMode, XML_NAMESPACE_STYLE,XML_REPEAT, XML_SW_TYPE_BITMAP_MODE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ GMAP( PROP_FillBitmapPositionOffsetX, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_REF_POINT_X, XML_TYPE_PERCENT, 0 ),
+ GMAP( PROP_FillBitmapPositionOffsetY, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_REF_POINT_Y, XML_TYPE_PERCENT, 0 ),
+ GMAP( PROP_FillBitmapRectanglePoint, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_REF_POINT, XML_SW_TYPE_BITMAP_REFPOINT, 0 ),
+ GMAP( PROP_FillBitmapOffsetX, XML_NAMESPACE_DRAW, XML_TILE_REPEAT_OFFSET, XML_SW_TYPE_BITMAPREPOFFSETX|MID_FLAG_MULTI_PROPERTY, CTF_REPEAT_OFFSET_X ),
+ GMAP( PROP_FillBitmapOffsetY, XML_NAMESPACE_DRAW, XML_TILE_REPEAT_OFFSET, XML_SW_TYPE_BITMAPREPOFFSETY|MID_FLAG_MULTI_PROPERTY, CTF_REPEAT_OFFSET_Y ),
+
+ // RES_LR_SPACE
+ // !!! DO NOT REORDER THE MARGINS !!!
+ MP_E( PROP_ParaLeftMargin, XML_NAMESPACE_FO, XML_MARGIN, XML_TYPE_MEASURE|MID_FLAG_MULTI_PROPERTY, CTF_PARAMARGINALL ),
+ MP_E( PROP_ParaLeftMarginRelative, XML_NAMESPACE_FO, XML_MARGIN, XML_TYPE_PERCENT16, CTF_PARAMARGINALL_REL ),
+ MP_E( PROP_ParaLeftMargin, XML_NAMESPACE_FO, XML_MARGIN_LEFT, XML_TYPE_MEASURE|MID_FLAG_MULTI_PROPERTY, CTF_PARALEFTMARGIN ),
+ MP_E( PROP_ParaLeftMarginRelative, XML_NAMESPACE_FO, XML_MARGIN_LEFT, XML_TYPE_PERCENT16, CTF_PARALEFTMARGIN_REL ),
+ MP_E( PROP_ParaRightMargin, XML_NAMESPACE_FO, XML_MARGIN_RIGHT, XML_TYPE_MEASURE|MID_FLAG_MULTI_PROPERTY, CTF_PARARIGHTMARGIN ),
+ MP_E( PROP_ParaRightMarginRelative, XML_NAMESPACE_FO, XML_MARGIN_RIGHT, XML_TYPE_PERCENT16, CTF_PARARIGHTMARGIN_REL ),
+ // RES_UL_SPACE
+ MP_E( PROP_ParaTopMargin, XML_NAMESPACE_FO, XML_MARGIN_TOP, XML_TYPE_MEASURE|MID_FLAG_MULTI_PROPERTY, CTF_PARATOPMARGIN ),
+ MP_E( PROP_ParaTopMarginRelative, XML_NAMESPACE_FO, XML_MARGIN_TOP, XML_TYPE_PERCENT16, CTF_PARATOPMARGIN_REL ),
+ MP_E( PROP_ParaBottomMargin, XML_NAMESPACE_FO, XML_MARGIN_BOTTOM, XML_TYPE_MEASURE|MID_FLAG_MULTI_PROPERTY, CTF_PARABOTTOMMARGIN ),
+ MP_E( PROP_ParaBottomMarginRelative, XML_NAMESPACE_FO, XML_MARGIN_BOTTOM, XML_TYPE_PERCENT16, CTF_PARABOTTOMMARGIN_REL ),
+ MAP_ODF13( PROP_ParaContextMargin, XML_NAMESPACE_STYLE, XML_CONTEXTUAL_SPACING, XML_TYPE_BOOL|XML_TYPE_PROP_PARAGRAPH, 0 ), // ODF 1.3 OFFICE-3767 and was written by LO<=4.2
+ MAP_ODF13( PROP_ParaContextMargin, XML_NAMESPACE_LO_EXT, XML_CONTEXTUAL_SPACING, XML_TYPE_BOOL|XML_TYPE_PROP_PARAGRAPH, 0 ), // extension namespace
+ // RES_CHRATR_CASEMAP
+ MT_E( PROP_CharCaseMap, XML_NAMESPACE_FO, XML_FONT_VARIANT, XML_TYPE_TEXT_CASEMAP_VAR, 0 ),
+ MT_E( PROP_CharCaseMap, XML_NAMESPACE_FO, XML_TEXT_TRANSFORM, XML_TYPE_TEXT_CASEMAP, 0 ),
+ // RES_CHRATR_COLOR
+ MT_ED( PROP_CharColor, XML_NAMESPACE_FO, XML_COLOR, XML_TYPE_COLORAUTO|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_ED( PROP_CharColor, XML_NAMESPACE_STYLE, XML_USE_WINDOW_FONT_COLOR, XML_TYPE_ISAUTOCOLOR|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MAP_EXT_I( PROP_CharTransparence, XML_NAMESPACE_DRAW, XML_OPACITY, XML_TYPE_NEG_PERCENT16 | XML_TYPE_PROP_TEXT, 0 ),
+ MAP_EXT( PROP_CharTransparence, XML_NAMESPACE_LO_EXT, XML_OPACITY, XML_TYPE_NEG_PERCENT16 | XML_TYPE_PROP_TEXT, 0 ),
+ MAP_EXT( PROP_CharComplexColor, XML_NAMESPACE_LO_EXT, XML_CHAR_COMPLEX_COLOR, XML_TYPE_COMPLEX_COLOR|XML_TYPE_PROP_TEXT|MID_FLAG_ELEMENT_ITEM, CTF_COMPLEX_COLOR ),
+ // RES_CHRATR_CONTOUR
+ MT_E( PROP_CharContoured, XML_NAMESPACE_STYLE, XML_TEXT_OUTLINE, XML_TYPE_BOOL, 0 ),
+ // RES_CHRATR_CROSSEDOUT
+ MT_E( PROP_CharStrikeout, XML_NAMESPACE_STYLE, XML_TEXT_LINE_THROUGH_STYLE, XML_TYPE_TEXT_CROSSEDOUT_STYLE|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_E( PROP_CharStrikeout, XML_NAMESPACE_STYLE, XML_TEXT_LINE_THROUGH_TYPE, XML_TYPE_TEXT_CROSSEDOUT_TYPE|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_E( PROP_CharStrikeout, XML_NAMESPACE_STYLE, XML_TEXT_LINE_THROUGH_WIDTH, XML_TYPE_TEXT_CROSSEDOUT_WIDTH|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_E( PROP_CharStrikeout, XML_NAMESPACE_STYLE, XML_TEXT_LINE_THROUGH_TEXT, XML_TYPE_TEXT_CROSSEDOUT_TEXT|MID_FLAG_MERGE_PROPERTY, 0 ),
+ // RES_CHRATR_ESCAPEMENT
+ MT_E( PROP_CharEscapement, XML_NAMESPACE_STYLE, XML_TEXT_POSITION, XML_TYPE_TEXT_ESCAPEMENT|MID_FLAG_MERGE_ATTRIBUTE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ MT_E( PROP_CharEscapementHeight, XML_NAMESPACE_STYLE, XML_TEXT_POSITION, XML_TYPE_TEXT_ESCAPEMENT_HEIGHT|MID_FLAG_MERGE_ATTRIBUTE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ // RES_CHRATR_FONT
+ MT_ED( PROP_CharFontName, XML_NAMESPACE_STYLE, XML_FONT_NAME, XML_TYPE_STRING|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_FONTNAME ),
+ MT_ED( PROP_CharFontName, XML_NAMESPACE_FO, XML_FONT_FAMILY, XML_TYPE_TEXT_FONTFAMILYNAME|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_FONTFAMILYNAME ),
+ MT_ED( PROP_CharFontStyleName, XML_NAMESPACE_STYLE, XML_FONT_STYLE_NAME, XML_TYPE_STRING, CTF_FONTSTYLENAME ),
+ MT_ED( PROP_CharFontFamily, XML_NAMESPACE_STYLE, XML_FONT_FAMILY_GENERIC, XML_TYPE_TEXT_FONTFAMILY, CTF_FONTFAMILY ),
+ MT_ED( PROP_CharFontPitch, XML_NAMESPACE_STYLE, XML_FONT_PITCH, XML_TYPE_TEXT_FONTPITCH, CTF_FONTPITCH ),
+ MT_ED( PROP_CharFontCharSet, XML_NAMESPACE_STYLE, XML_FONT_CHARSET, XML_TYPE_TEXT_FONTENCODING, CTF_FONTCHARSET ),
+ // RES_CHRATR_FONTSIZE
+ MT_ED( PROP_CharHeight, XML_NAMESPACE_FO, XML_FONT_SIZE, XML_TYPE_CHAR_HEIGHT|MID_FLAG_MULTI_PROPERTY, CTF_CHARHEIGHT ),
+ MT_ED( PROP_CharPropHeight, XML_NAMESPACE_FO, XML_FONT_SIZE, XML_TYPE_CHAR_HEIGHT_PROP|MID_FLAG_MULTI_PROPERTY, CTF_CHARHEIGHT_REL ),
+ MT_ED( PROP_CharDiffHeight, XML_NAMESPACE_STYLE, XML_FONT_SIZE_REL, XML_TYPE_CHAR_HEIGHT_DIFF, CTF_CHARHEIGHT_DIFF ),
+ // RES_CHRATR_KERNING
+ MT_E( PROP_CharKerning, XML_NAMESPACE_FO, XML_LETTER_SPACING, XML_TYPE_TEXT_KERNING, 0 ),
+ // RES_CHRATR_LANGUAGE
+ MT_ED( PROP_CharLocale, XML_NAMESPACE_STYLE, XML_RFC_LANGUAGE_TAG, XML_TYPE_CHAR_RFC_LANGUAGE_TAG|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_ED( PROP_CharLocale, XML_NAMESPACE_FO, XML_LANGUAGE, XML_TYPE_CHAR_LANGUAGE|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_ED( PROP_CharLocale, XML_NAMESPACE_FO, XML_SCRIPT, XML_TYPE_CHAR_SCRIPT|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_ED( PROP_CharLocale, XML_NAMESPACE_FO, XML_COUNTRY, XML_TYPE_CHAR_COUNTRY|MID_FLAG_MERGE_PROPERTY, 0 ),
+ // RES_CHRATR_POSTURE
+ MT_E( PROP_CharPosture, XML_NAMESPACE_FO, XML_FONT_STYLE, XML_TYPE_TEXT_POSTURE, 0 ),
+ // RES_CHRATR_UNUSED1
+ // RES_CHRATR_SHADOWED
+ MT_E( PROP_CharShadowed, XML_NAMESPACE_FO, XML_TEXT_SHADOW, XML_TYPE_TEXT_SHADOWED, 0 ),
+ // RES_CHRATR_UNDERLINE
+ MT_E( PROP_CharUnderline, XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_STYLE, XML_TYPE_TEXT_UNDERLINE_STYLE|MID_FLAG_MERGE_PROPERTY, CTF_UNDERLINE ),
+ MT_E( PROP_CharUnderline, XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_TYPE, XML_TYPE_TEXT_UNDERLINE_TYPE|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_E( PROP_CharUnderline, XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_WIDTH, XML_TYPE_TEXT_UNDERLINE_WIDTH|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_E( PROP_CharUnderlineColor, XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_COLOR, XML_TYPE_TEXT_UNDERLINE_COLOR|MID_FLAG_MULTI_PROPERTY, CTF_UNDERLINE_COLOR ),
+ MT_E( PROP_CharUnderlineHasColor, XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_COLOR, XML_TYPE_TEXT_UNDERLINE_HASCOLOR|MID_FLAG_MERGE_ATTRIBUTE, CTF_UNDERLINE_HASCOLOR ),
+ // RES_CHRATR_WEIGHT
+ MT_E( PROP_CharWeight, XML_NAMESPACE_FO, XML_FONT_WEIGHT, XML_TYPE_TEXT_WEIGHT, 0 ),
+ // RES_CHRATR_RSID
+ { PROP_Rsid, XML_NAMESPACE_OFFICE_EXT, XML_RSID, XML_TYPE_HEX|XML_TYPE_PROP_TEXT, 0, SvtSaveOptions::ODFSVER_FUTURE_EXTENDED, false },
+ // RES_PARATR_RSID
+ { PROP_ParRsid, XML_NAMESPACE_OFFICE_EXT, XML_PARRSID, XML_TYPE_HEX|XML_TYPE_PROP_TEXT, 0, SvtSaveOptions::ODFSVER_FUTURE_EXTENDED, false },
+ // RES_CHRATR_WORDLINEMODE
+ MT_E( PROP_CharWordMode, XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_MODE, XML_TYPE_TEXT_LINE_MODE|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_E( PROP_CharWordMode, XML_NAMESPACE_STYLE, XML_TEXT_OVERLINE_MODE, XML_TYPE_TEXT_LINE_MODE|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_E( PROP_CharWordMode, XML_NAMESPACE_STYLE, XML_TEXT_LINE_THROUGH_MODE, XML_TYPE_TEXT_LINE_MODE|MID_FLAG_MERGE_PROPERTY, 0 ),
+ // RES_CHRATR_AUTOKERN
+ MT_E( PROP_CharAutoKerning, XML_NAMESPACE_STYLE, XML_LETTER_KERNING, XML_TYPE_BOOL, 0 ),
+ // RES_CHRATR_BLINK
+ MT_E( PROP_CharFlash, XML_NAMESPACE_STYLE, XML_TEXT_BLINKING, XML_TYPE_BOOL, 0 ),
+ // RES_CHRATR_NOHYPHEN
+ // TODO: not used?
+ // RES_CHRATR_UNUSED2
+ // RES_CHRATR_BACKGROUND
+ MT_E( PROP_CharBackColor, XML_NAMESPACE_FO, XML_BACKGROUND_COLOR, XML_TYPE_COLORTRANSPARENT|MID_FLAG_MULTI_PROPERTY, CTF_CHAR_BACKGROUND ),
+ MT_E( PROP_CharBackTransparent, XML_NAMESPACE_FO, XML_BACKGROUND_COLOR, XML_TYPE_ISTRANSPARENT|MID_FLAG_MERGE_ATTRIBUTE, CTF_CHAR_BACKGROUND_TRANSPARENCY),
+ MT_E( PROP_CharBackColor, XML_NAMESPACE_FO, XML_TEXT_BACKGROUND_COLOR, XML_TYPE_COLOR|MID_FLAG_SPECIAL_ITEM_EXPORT, CTF_OLDTEXTBACKGROUND ),
+ // RES_CHRATR_CJK_FONT
+ MT_ED( PROP_CharFontNameAsian, XML_NAMESPACE_STYLE, XML_FONT_NAME_ASIAN, XML_TYPE_STRING|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_FONTNAME_CJK ),
+ MT_ED( PROP_CharFontNameAsian, XML_NAMESPACE_STYLE, XML_FONT_FAMILY_ASIAN, XML_TYPE_TEXT_FONTFAMILYNAME|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_FONTFAMILYNAME_CJK ),
+ MT_ED( PROP_CharFontStyleNameAsian, XML_NAMESPACE_STYLE, XML_FONT_STYLE_NAME_ASIAN, XML_TYPE_STRING, CTF_FONTSTYLENAME_CJK ),
+ MT_ED( PROP_CharFontFamilyAsian, XML_NAMESPACE_STYLE, XML_FONT_FAMILY_GENERIC_ASIAN, XML_TYPE_TEXT_FONTFAMILY, CTF_FONTFAMILY_CJK ),
+ MT_ED( PROP_CharFontPitchAsian, XML_NAMESPACE_STYLE, XML_FONT_PITCH_ASIAN, XML_TYPE_TEXT_FONTPITCH, CTF_FONTPITCH_CJK ),
+ MT_ED( PROP_CharFontCharSetAsian, XML_NAMESPACE_STYLE, XML_FONT_CHARSET_ASIAN, XML_TYPE_TEXT_FONTENCODING, CTF_FONTCHARSET_CJK ),
+ // RES_CHRATR_CJK_FONTSIZE
+ MT_ED( PROP_CharHeightAsian, XML_NAMESPACE_STYLE, XML_FONT_SIZE_ASIAN, XML_TYPE_CHAR_HEIGHT|MID_FLAG_MULTI_PROPERTY, CTF_CHARHEIGHT_CJK ),
+ MT_ED( PROP_CharPropHeightAsian, XML_NAMESPACE_STYLE, XML_FONT_SIZE_ASIAN, XML_TYPE_CHAR_HEIGHT_PROP|MID_FLAG_MULTI_PROPERTY, CTF_CHARHEIGHT_REL_CJK ),
+ MT_ED( PROP_CharDiffHeightAsian, XML_NAMESPACE_STYLE, XML_FONT_SIZE_REL_ASIAN, XML_TYPE_CHAR_HEIGHT_DIFF, CTF_CHARHEIGHT_DIFF_CJK ),
+ // RES_CHRATR_CJK_LANGUAGE
+ MT_ED( PROP_CharLocaleAsian, XML_NAMESPACE_STYLE, XML_RFC_LANGUAGE_TAG_ASIAN, XML_TYPE_CHAR_RFC_LANGUAGE_TAG|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_ED( PROP_CharLocaleAsian, XML_NAMESPACE_STYLE, XML_LANGUAGE_ASIAN, XML_TYPE_CHAR_LANGUAGE|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_ED( PROP_CharLocaleAsian, XML_NAMESPACE_STYLE, XML_SCRIPT_ASIAN, XML_TYPE_CHAR_SCRIPT|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_ED( PROP_CharLocaleAsian, XML_NAMESPACE_STYLE, XML_COUNTRY_ASIAN, XML_TYPE_CHAR_COUNTRY|MID_FLAG_MERGE_PROPERTY, 0 ),
+ // RES_CHRATR_CJK_POSTURE
+ MT_E( PROP_CharPostureAsian, XML_NAMESPACE_STYLE, XML_FONT_STYLE_ASIAN, XML_TYPE_TEXT_POSTURE, 0 ),
+ // RES_CHRATR_CJK_WEIGHT
+ MT_E( PROP_CharWeightAsian, XML_NAMESPACE_STYLE, XML_FONT_WEIGHT_ASIAN, XML_TYPE_TEXT_WEIGHT, 0 ),
+ // RES_CHRATR_CTL_FONT
+ MT_ED( PROP_CharFontNameComplex, XML_NAMESPACE_STYLE, XML_FONT_NAME_COMPLEX, XML_TYPE_STRING|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_FONTNAME_CTL ),
+ MT_ED( PROP_CharFontNameComplex, XML_NAMESPACE_STYLE, XML_FONT_FAMILY_COMPLEX, XML_TYPE_TEXT_FONTFAMILYNAME|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_FONTFAMILYNAME_CTL ),
+ MT_ED( PROP_CharFontStyleNameComplex, XML_NAMESPACE_STYLE, XML_FONT_STYLE_NAME_COMPLEX, XML_TYPE_STRING, CTF_FONTSTYLENAME_CTL ),
+ MT_ED( PROP_CharFontFamilyComplex, XML_NAMESPACE_STYLE, XML_FONT_FAMILY_GENERIC_COMPLEX, XML_TYPE_TEXT_FONTFAMILY, CTF_FONTFAMILY_CTL ),
+ MT_ED( PROP_CharFontPitchComplex, XML_NAMESPACE_STYLE, XML_FONT_PITCH_COMPLEX, XML_TYPE_TEXT_FONTPITCH, CTF_FONTPITCH_CTL ),
+ MT_ED( PROP_CharFontCharSetComplex, XML_NAMESPACE_STYLE, XML_FONT_CHARSET_COMPLEX, XML_TYPE_TEXT_FONTENCODING, CTF_FONTCHARSET_CTL ),
+ // RES_CHRATR_CTL_FONTSIZE
+ MT_ED( PROP_CharHeightComplex, XML_NAMESPACE_STYLE, XML_FONT_SIZE_COMPLEX, XML_TYPE_CHAR_HEIGHT|MID_FLAG_MULTI_PROPERTY, CTF_CHARHEIGHT_CTL ),
+ MT_ED( PROP_CharPropHeightComplex, XML_NAMESPACE_STYLE, XML_FONT_SIZE_COMPLEX, XML_TYPE_CHAR_HEIGHT_PROP|MID_FLAG_MULTI_PROPERTY, CTF_CHARHEIGHT_REL_CTL ),
+ MT_ED( PROP_CharDiffHeightComplex, XML_NAMESPACE_STYLE, XML_FONT_SIZE_REL_COMPLEX, XML_TYPE_CHAR_HEIGHT_DIFF, CTF_CHARHEIGHT_DIFF_CTL ),
+ // RES_CHRATR_CTL_LANGUAGE
+ MT_ED( PROP_CharLocaleComplex, XML_NAMESPACE_STYLE, XML_RFC_LANGUAGE_TAG_COMPLEX, XML_TYPE_CHAR_RFC_LANGUAGE_TAG|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_ED( PROP_CharLocaleComplex, XML_NAMESPACE_STYLE, XML_LANGUAGE_COMPLEX, XML_TYPE_CHAR_LANGUAGE|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_ED( PROP_CharLocaleComplex, XML_NAMESPACE_STYLE, XML_SCRIPT_COMPLEX, XML_TYPE_CHAR_SCRIPT|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_ED( PROP_CharLocaleComplex, XML_NAMESPACE_STYLE, XML_COUNTRY_COMPLEX, XML_TYPE_CHAR_COUNTRY|MID_FLAG_MERGE_PROPERTY, 0 ),
+ // RES_CHRATR_CTL_POSTURE
+ MT_E( PROP_CharPostureComplex, XML_NAMESPACE_STYLE, XML_FONT_STYLE_COMPLEX, XML_TYPE_TEXT_POSTURE, 0 ),
+ // RES_CHRATR_CTL_WEIGHT
+ MT_E( PROP_CharWeightComplex, XML_NAMESPACE_STYLE, XML_FONT_WEIGHT_COMPLEX, XML_TYPE_TEXT_WEIGHT, 0 ),
+ // RES_CHRATR_ROTATE
+ MT_E( PROP_CharRotation, XML_NAMESPACE_STYLE, XML_TEXT_ROTATION_ANGLE, XML_TYPE_TEXT_ROTATION_ANGLE, 0 ),
+ MT_E( PROP_CharRotationIsFitToLine, XML_NAMESPACE_STYLE, XML_TEXT_ROTATION_SCALE, XML_TYPE_TEXT_ROTATION_SCALE, 0 ),
+ // RES_CHRATR_EMPHASIS_MARK
+ MT_E( PROP_CharEmphasis, XML_NAMESPACE_STYLE, XML_TEXT_EMPHASIZE, XML_TYPE_TEXT_EMPHASIZE, 0 ),
+ // RES_CHRATR_TWO_LINES
+ MT_E( PROP_CharCombineIsOn, XML_NAMESPACE_STYLE, XML_TEXT_COMBINE, XML_TYPE_TEXT_COMBINE, 0 ),
+ MT_E( PROP_CharCombinePrefix, XML_NAMESPACE_STYLE, XML_TEXT_COMBINE_START_CHAR, XML_TYPE_TEXT_COMBINECHAR, 0 ),
+ MT_E( PROP_CharCombineSuffix, XML_NAMESPACE_STYLE, XML_TEXT_COMBINE_END_CHAR, XML_TYPE_TEXT_COMBINECHAR, 0 ),
+ // RES_CHRATR_SCALEW
+ MT_E( PROP_CharScaleWidth, XML_NAMESPACE_STYLE, XML_TEXT_SCALE, XML_TYPE_PERCENT16, 0 ),
+ //RES_CHRATR_RELIEF
+ MT_E( PROP_CharRelief, XML_NAMESPACE_STYLE, XML_FONT_RELIEF, XML_TYPE_TEXT_FONT_RELIEF, 0 ),
+ // RES_CHRATR_HIDDEN
+ MT_E( PROP_CharHidden, XML_NAMESPACE_TEXT, XML_DISPLAY, XML_TYPE_TEXT_HIDDEN_AS_DISPLAY|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_TEXT_DISPLAY ),
+ // RES_CHRATR_OVERLINE
+ MT_E( PROP_CharOverline, XML_NAMESPACE_STYLE, XML_TEXT_OVERLINE_STYLE, XML_TYPE_TEXT_OVERLINE_STYLE|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_E( PROP_CharOverline, XML_NAMESPACE_STYLE, XML_TEXT_OVERLINE_TYPE, XML_TYPE_TEXT_OVERLINE_TYPE|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_E( PROP_CharOverline, XML_NAMESPACE_STYLE, XML_TEXT_OVERLINE_WIDTH, XML_TYPE_TEXT_OVERLINE_WIDTH|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_E( PROP_CharOverlineColor, XML_NAMESPACE_STYLE, XML_TEXT_OVERLINE_COLOR, XML_TYPE_TEXT_OVERLINE_COLOR|MID_FLAG_MULTI_PROPERTY, 0 ),
+ MT_E( PROP_CharOverlineHasColor, XML_NAMESPACE_STYLE, XML_TEXT_OVERLINE_COLOR, XML_TYPE_TEXT_OVERLINE_HASCOLOR|MID_FLAG_MERGE_ATTRIBUTE, 0 ),
+ // RES_CHRATR_BOX
+ MAP_EXT( PROP_CharLeftBorder, XML_NAMESPACE_LO_EXT, XML_BORDER_LINE_WIDTH, XML_TYPE_BORDER_WIDTH|XML_TYPE_PROP_TEXT, CTF_CHARALLBORDERWIDTH ),
+ MAP_EXT( PROP_CharLeftBorder, XML_NAMESPACE_LO_EXT, XML_BORDER_LINE_WIDTH_LEFT, XML_TYPE_BORDER_WIDTH|XML_TYPE_PROP_TEXT, CTF_CHARLEFTBORDERWIDTH ),
+ MAP_EXT( PROP_CharRightBorder, XML_NAMESPACE_LO_EXT, XML_BORDER_LINE_WIDTH_RIGHT, XML_TYPE_BORDER_WIDTH|XML_TYPE_PROP_TEXT, CTF_CHARRIGHTBORDERWIDTH ),
+ MAP_EXT( PROP_CharTopBorder, XML_NAMESPACE_LO_EXT, XML_BORDER_LINE_WIDTH_TOP, XML_TYPE_BORDER_WIDTH|XML_TYPE_PROP_TEXT, CTF_CHARTOPBORDERWIDTH ),
+ MAP_EXT( PROP_CharBottomBorder, XML_NAMESPACE_LO_EXT, XML_BORDER_LINE_WIDTH_BOTTOM, XML_TYPE_BORDER_WIDTH|XML_TYPE_PROP_TEXT, CTF_CHARBOTTOMBORDERWIDTH ),
+ MAP_EXT_I( PROP_CharLeftBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH, XML_TYPE_BORDER_WIDTH|XML_TYPE_PROP_TEXT, CTF_CHARALLBORDERWIDTH ),
+ MAP_EXT_I( PROP_CharLeftBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_LEFT, XML_TYPE_BORDER_WIDTH|XML_TYPE_PROP_TEXT, CTF_CHARLEFTBORDERWIDTH ),
+ MAP_EXT_I( PROP_CharRightBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_RIGHT, XML_TYPE_BORDER_WIDTH|XML_TYPE_PROP_TEXT, CTF_CHARRIGHTBORDERWIDTH ),
+ MAP_EXT_I( PROP_CharTopBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_TOP, XML_TYPE_BORDER_WIDTH|XML_TYPE_PROP_TEXT, CTF_CHARTOPBORDERWIDTH ),
+ MAP_EXT_I( PROP_CharBottomBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_BOTTOM, XML_TYPE_BORDER_WIDTH|XML_TYPE_PROP_TEXT, CTF_CHARBOTTOMBORDERWIDTH ),
+
+ MAP_EXT( PROP_CharLeftBorderDistance, XML_NAMESPACE_LO_EXT, XML_PADDING, XML_TYPE_MEASURE|XML_TYPE_PROP_TEXT, CTF_CHARALLBORDERDISTANCE ),
+ MAP_EXT( PROP_CharLeftBorderDistance, XML_NAMESPACE_LO_EXT, XML_PADDING_LEFT, XML_TYPE_MEASURE|XML_TYPE_PROP_TEXT, CTF_CHARLEFTBORDERDISTANCE ),
+ MAP_EXT( PROP_CharRightBorderDistance, XML_NAMESPACE_LO_EXT, XML_PADDING_RIGHT, XML_TYPE_MEASURE|XML_TYPE_PROP_TEXT, CTF_CHARRIGHTBORDERDISTANCE ),
+ MAP_EXT( PROP_CharTopBorderDistance, XML_NAMESPACE_LO_EXT, XML_PADDING_TOP, XML_TYPE_MEASURE|XML_TYPE_PROP_TEXT, CTF_CHARTOPBORDERDISTANCE ),
+ MAP_EXT( PROP_CharBottomBorderDistance, XML_NAMESPACE_LO_EXT, XML_PADDING_BOTTOM, XML_TYPE_MEASURE|XML_TYPE_PROP_TEXT, CTF_CHARBOTTOMBORDERDISTANCE ),
+ MAP_EXT_I( PROP_CharLeftBorderDistance, XML_NAMESPACE_FO, XML_PADDING, XML_TYPE_MEASURE|XML_TYPE_PROP_TEXT, CTF_CHARALLBORDERDISTANCE ),
+ MAP_EXT_I( PROP_CharLeftBorderDistance, XML_NAMESPACE_FO, XML_PADDING_LEFT, XML_TYPE_MEASURE|XML_TYPE_PROP_TEXT, CTF_CHARLEFTBORDERDISTANCE ),
+ MAP_EXT_I( PROP_CharRightBorderDistance, XML_NAMESPACE_FO, XML_PADDING_RIGHT, XML_TYPE_MEASURE|XML_TYPE_PROP_TEXT, CTF_CHARRIGHTBORDERDISTANCE ),
+ MAP_EXT_I( PROP_CharTopBorderDistance, XML_NAMESPACE_FO, XML_PADDING_TOP, XML_TYPE_MEASURE|XML_TYPE_PROP_TEXT, CTF_CHARTOPBORDERDISTANCE ),
+ MAP_EXT_I( PROP_CharBottomBorderDistance, XML_NAMESPACE_FO, XML_PADDING_BOTTOM, XML_TYPE_MEASURE|XML_TYPE_PROP_TEXT, CTF_CHARBOTTOMBORDERDISTANCE ),
+
+ MAP_EXT( PROP_CharLeftBorder, XML_NAMESPACE_LO_EXT, XML_BORDER, XML_TYPE_BORDER|XML_TYPE_PROP_TEXT, CTF_CHARALLBORDER ),
+ MAP_EXT( PROP_CharLeftBorder, XML_NAMESPACE_LO_EXT, XML_BORDER_LEFT, XML_TYPE_BORDER|XML_TYPE_PROP_TEXT, CTF_CHARLEFTBORDER ),
+ MAP_EXT( PROP_CharRightBorder, XML_NAMESPACE_LO_EXT, XML_BORDER_RIGHT, XML_TYPE_BORDER|XML_TYPE_PROP_TEXT, CTF_CHARRIGHTBORDER ),
+ MAP_EXT( PROP_CharTopBorder, XML_NAMESPACE_LO_EXT, XML_BORDER_TOP, XML_TYPE_BORDER|XML_TYPE_PROP_TEXT, CTF_CHARTOPBORDER ),
+ MAP_EXT( PROP_CharBottomBorder, XML_NAMESPACE_LO_EXT, XML_BORDER_BOTTOM, XML_TYPE_BORDER|XML_TYPE_PROP_TEXT, CTF_CHARBOTTOMBORDER ),
+ MAP_EXT_I( PROP_CharLeftBorder, XML_NAMESPACE_FO, XML_BORDER, XML_TYPE_BORDER|XML_TYPE_PROP_TEXT, CTF_CHARALLBORDER ),
+ MAP_EXT_I( PROP_CharLeftBorder, XML_NAMESPACE_FO, XML_BORDER_LEFT, XML_TYPE_BORDER|XML_TYPE_PROP_TEXT, CTF_CHARLEFTBORDER ),
+ MAP_EXT_I( PROP_CharRightBorder, XML_NAMESPACE_FO, XML_BORDER_RIGHT, XML_TYPE_BORDER|XML_TYPE_PROP_TEXT, CTF_CHARRIGHTBORDER ),
+ MAP_EXT_I( PROP_CharTopBorder, XML_NAMESPACE_FO, XML_BORDER_TOP, XML_TYPE_BORDER|XML_TYPE_PROP_TEXT, CTF_CHARTOPBORDER ),
+ MAP_EXT_I( PROP_CharBottomBorder, XML_NAMESPACE_FO, XML_BORDER_BOTTOM, XML_TYPE_BORDER|XML_TYPE_PROP_TEXT, CTF_CHARBOTTOMBORDER ),
+ // RES_CHRATR_SHADOW
+ MAP_EXT( PROP_CharShadowFormat, XML_NAMESPACE_LO_EXT, XML_SHADOW, XML_TYPE_TEXT_SHADOW|XML_TYPE_PROP_TEXT, 0 ),
+ MAP_EXT_I( PROP_CharShadowFormat, XML_NAMESPACE_STYLE, XML_SHADOW, XML_TYPE_TEXT_SHADOW|XML_TYPE_PROP_TEXT, 0 ),
+ // RES_CHRATR_HIGHLIGHT
+ MT_E( PROP_CharHighlight, XML_NAMESPACE_FO, XML_BACKGROUND_COLOR, XML_TYPE_COLORTRANSPARENT|MID_FLAG_MULTI_PROPERTY| MID_FLAG_NO_PROPERTY_IMPORT, CTF_CHAR_HIGHLIGHT ),
+ // RES_TXTATR_INETFMT
+ // TODO
+ // RES_TXTATR_REFMARK
+ // TODO
+ // RES_TXTATR_TOXMARK
+ // TODO
+ // RES_TXTATR_CHARFMT
+// M_E_SI( TEXT, style_name, RES_TXTATR_CHARFMT, 0 ),
+ // RES_TXTATR_CJK_RUBY
+ // TODO
+ // RES_TXTATR_FIELD
+ // TODO
+ // RES_TXTATR_FLYCNT
+ // TODO
+ // RES_TXTATR_FTN
+ // TODO
+ // RES_TXTATR_SOFTHYPH
+ // TODO
+ // RES_TXTATR_HARDBLANK
+ // TODO
+
+ // RES_PARATR_LINESPACING
+ MP_E( PROP_ParaLineSpacing, XML_NAMESPACE_FO, XML_LINE_HEIGHT, XML_TYPE_LINE_SPACE_FIXED, 0 ),
+ MP_E( PROP_ParaLineSpacing, XML_NAMESPACE_STYLE, XML_LINE_HEIGHT_AT_LEAST, XML_TYPE_LINE_SPACE_MINIMUM, 0 ),
+ MP_E( PROP_ParaLineSpacing, XML_NAMESPACE_STYLE, XML_LINE_SPACING, XML_TYPE_LINE_SPACE_DISTANCE, 0 ),
+ // RES_PARATR_ADJUST
+ MP_E( PROP_ParaAdjust, XML_NAMESPACE_FO, XML_TEXT_ALIGN, XML_TYPE_TEXT_ADJUST, CTF_SD_SHAPE_PARA_ADJUST ),
+ MP_E( PROP_ParaLastLineAdjust, XML_NAMESPACE_FO, XML_TEXT_ALIGN_LAST, XML_TYPE_TEXT_ADJUSTLAST, CTF_PARA_ADJUSTLAST ),
+ MP_E( PROP_ParaExpandSingleWord, XML_NAMESPACE_STYLE, XML_JUSTIFY_SINGLE_WORD, XML_TYPE_BOOL, 0 ),
+ // RES_PARATR_SPLIT
+ MP_E( PROP_ParaSplit, XML_NAMESPACE_FO, XML_KEEP_TOGETHER, XML_TYPE_TEXT_SPLIT, 0 ),
+ // RES_PARATR_ORPHANS
+ MP_E( PROP_ParaOrphans, XML_NAMESPACE_FO, XML_ORPHANS, XML_TYPE_NUMBER8, 0 ),
+ // RES_PARATR_WIDOWS
+ MP_E( PROP_ParaWidows, XML_NAMESPACE_FO, XML_WIDOWS, XML_TYPE_NUMBER8, 0 ),
+ // RES_PARATR_TABSTOP
+ MP_ED( PROP_ParaTabStops, XML_NAMESPACE_STYLE, XML_TAB_STOPS, MID_FLAG_ELEMENT_ITEM|XML_TYPE_TEXT_TABSTOP, CTF_TABSTOP ), // this is not really a string!
+ // RES_PARATR_HYPHENZONE
+ MT_E( PROP_ParaIsHyphenation, XML_NAMESPACE_FO, XML_HYPHENATE, XML_TYPE_BOOL, 0 ),
+ MT_E( PROP_ParaHyphenationMaxLeadingChars, XML_NAMESPACE_FO, XML_HYPHENATION_REMAIN_CHAR_COUNT, XML_TYPE_NUMBER16_NO_ZERO, 0 ),
+ MT_E( PROP_ParaHyphenationMaxTrailingChars, XML_NAMESPACE_FO, XML_HYPHENATION_PUSH_CHAR_COUNT, XML_TYPE_NUMBER16_NO_ZERO, 0 ),
+ MP_E( PROP_ParaHyphenationMaxHyphens, XML_NAMESPACE_FO, XML_HYPHENATION_LADDER_COUNT, XML_TYPE_NUMBER16_NONE, 0 ),
+ MAP_EXT( PROP_ParaHyphenationNoCaps, XML_NAMESPACE_LO_EXT, XML_HYPHENATION_NO_CAPS, XML_TYPE_BOOL|XML_TYPE_PROP_TEXT, 0 ),
+ MAP_EXT( PROP_ParaHyphenationNoLastWord, XML_NAMESPACE_LO_EXT, XML_HYPHENATION_NO_LAST_WORD, XML_TYPE_BOOL|XML_TYPE_PROP_TEXT, 0 ),
+ MAP_EXT( PROP_ParaHyphenationMinWordLength, XML_NAMESPACE_LO_EXT, XML_HYPHENATION_WORD_CHAR_COUNT, XML_TYPE_NUMBER16_NONE|XML_TYPE_PROP_TEXT, 0 ),
+ MAP_EXT( PROP_ParaHyphenationZone, XML_NAMESPACE_LO_EXT, XML_HYPHENATION_ZONE, XML_TYPE_NUMBER16_NONE|XML_TYPE_PROP_TEXT, 0 ),
+ // RES_PARATR_DROP
+ MP_E( PROP_DropCapWholeWord, XML_NAMESPACE_STYLE, XML_LENGTH, MID_FLAG_SPECIAL_ITEM|XML_TYPE_BOOL, CTF_DROPCAPWHOLEWORD ),
+ MP_E( PROP_DropCapCharStyleName, XML_NAMESPACE_STYLE, XML_STYLE_NAME, MID_FLAG_SPECIAL_ITEM|XML_TYPE_STRING, CTF_DROPCAPCHARSTYLE ),
+ MP_E( PROP_DropCapFormat, XML_NAMESPACE_STYLE, XML_DROP_CAP, MID_FLAG_ELEMENT_ITEM|XML_TYPE_TEXT_DROPCAP, CTF_DROPCAPFORMAT ),
+ // RES_PARATR_REGISTER
+ MP_E( PROP_ParaRegisterModeActive, XML_NAMESPACE_STYLE, XML_REGISTER_TRUE, XML_TYPE_BOOL, 0 ),
+ // RES_PARATR_NUMRULE
+ MP_E( PROP_NumberingStyleName, XML_NAMESPACE_STYLE, XML_LIST_STYLE_NAME, MID_FLAG_SPECIAL_ITEM|XML_TYPE_STYLENAME, CTF_NUMBERINGSTYLENAME ),
+
+ // RES_FILL_ORDER
+ // not required
+ // RES_FRM_SIZE
+ // not required
+ // RES_PAPER_BIN
+ // not required
+ // RES_LR_SPACE
+
+ MP_E( PROP_ParaFirstLineIndent, XML_NAMESPACE_FO, XML_TEXT_INDENT, XML_TYPE_MEASURE|MID_FLAG_MULTI_PROPERTY, CTF_PARAFIRSTLINE ),
+ MP_E( PROP_ParaFirstLineIndentRelative, XML_NAMESPACE_FO, XML_TEXT_INDENT, XML_TYPE_PERCENT, CTF_PARAFIRSTLINE_REL ),
+ MP_E( PROP_ParaIsAutoFirstLineIndent, XML_NAMESPACE_STYLE, XML_AUTO_TEXT_INDENT, XML_TYPE_BOOL, 0 ),
+ // RES_PAGEDESC
+ MP_E( PROP_PageDescName, XML_NAMESPACE_STYLE, XML_MASTER_PAGE_NAME, MID_FLAG_SPECIAL_ITEM|XML_TYPE_STYLENAME, CTF_PAGEDESCNAME ),
+ MP_E( PROP_PageNumberOffset, XML_NAMESPACE_STYLE, XML_PAGE_NUMBER, XML_TYPE_NUMBER16_AUTO|MID_FLAG_SPECIAL_ITEM_EXPORT, CTF_PAGENUMBEROFFSET ),
+ // RES_BREAK : TODO: does this work?
+ MP_E( PROP_BreakType, XML_NAMESPACE_FO, XML_BREAK_BEFORE, XML_TYPE_TEXT_BREAKBEFORE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ MP_E( PROP_BreakType, XML_NAMESPACE_FO, XML_BREAK_AFTER, XML_TYPE_TEXT_BREAKAFTER, 0 ),
+ // RES_CNTNT
+ // not required
+ // RES_HEADER
+ // not required
+ // RES_FOOTER
+ // not required
+ // RES_PRINT
+ // not required
+ // RES_OPAQUE
+ // not required
+ // RES_PROTECT
+ // not required
+ // RES_SURROUND
+ // not required
+ // RES_VERT_ORIENT
+ // not required
+ // RES_HORI_ORIENT
+ // not required
+ // RES_ANCHOR
+ // not required
+ // RES_BACKGROUND
+ // DO NOT REORDER these!
+ MP_E( PROP_ParaBackColor, XML_NAMESPACE_FO, XML_BACKGROUND_COLOR, XML_TYPE_COLORTRANSPARENT|MID_FLAG_MULTI_PROPERTY, 0 ),
+ MP_E( PROP_ParaBackTransparent, XML_NAMESPACE_FO, XML_BACKGROUND_COLOR, XML_TYPE_ISTRANSPARENT|MID_FLAG_MERGE_ATTRIBUTE, 0 ),
+ MP_E( PROP_ParaBackGraphicLocation, XML_NAMESPACE_STYLE, XML_POSITION, MID_FLAG_SPECIAL_ITEM|XML_TYPE_BUILDIN_CMP_ONLY, CTF_BACKGROUND_POS ),
+ MP_E( PROP_ParaBackGraphicFilter, XML_NAMESPACE_STYLE, XML_FILTER_NAME, MID_FLAG_SPECIAL_ITEM|XML_TYPE_STRING, CTF_BACKGROUND_FILTER ),
+ MP_E( PROP_ParaBackGraphic, XML_NAMESPACE_STYLE, XML_BACKGROUND_IMAGE, MID_FLAG_ELEMENT_ITEM|XML_TYPE_GRAPHIC, CTF_BACKGROUND_URL ),
+
+ // RES_BOX
+ MP_E( PROP_LeftBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH, XML_TYPE_BORDER_WIDTH, CTF_ALLBORDERWIDTH ),
+ MP_E( PROP_LeftBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_LEFT, XML_TYPE_BORDER_WIDTH, CTF_LEFTBORDERWIDTH ),
+ MP_E( PROP_RightBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_RIGHT, XML_TYPE_BORDER_WIDTH, CTF_RIGHTBORDERWIDTH ),
+ MP_E( PROP_TopBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_TOP, XML_TYPE_BORDER_WIDTH, CTF_TOPBORDERWIDTH ),
+ MP_E( PROP_BottomBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_BOTTOM, XML_TYPE_BORDER_WIDTH, CTF_BOTTOMBORDERWIDTH ),
+
+ MP_E( PROP_LeftBorderDistance, XML_NAMESPACE_FO, XML_PADDING, XML_TYPE_MEASURE|MID_FLAG_MULTI_PROPERTY, CTF_ALLBORDERDISTANCE ), // need special import filtering
+ MP_E( PROP_LeftBorderDistance, XML_NAMESPACE_FO, XML_PADDING_LEFT, XML_TYPE_MEASURE|MID_FLAG_MULTI_PROPERTY, CTF_LEFTBORDERDISTANCE ),
+ MP_E( PROP_RightBorderDistance, XML_NAMESPACE_FO, XML_PADDING_RIGHT, XML_TYPE_MEASURE|MID_FLAG_MULTI_PROPERTY, CTF_RIGHTBORDERDISTANCE ),
+ MP_E( PROP_TopBorderDistance, XML_NAMESPACE_FO, XML_PADDING_TOP, XML_TYPE_MEASURE|MID_FLAG_MULTI_PROPERTY, CTF_TOPBORDERDISTANCE ),
+ MP_E( PROP_BottomBorderDistance, XML_NAMESPACE_FO, XML_PADDING_BOTTOM, XML_TYPE_MEASURE|MID_FLAG_MULTI_PROPERTY, CTF_BOTTOMBORDERDISTANCE ),
+
+ MP_E( PROP_LeftBorder, XML_NAMESPACE_FO, XML_BORDER, XML_TYPE_BORDER, CTF_ALLBORDER ),
+ MP_E( PROP_LeftBorder, XML_NAMESPACE_FO, XML_BORDER_LEFT, XML_TYPE_BORDER, CTF_LEFTBORDER ),
+ MP_E( PROP_RightBorder, XML_NAMESPACE_FO, XML_BORDER_RIGHT, XML_TYPE_BORDER, CTF_RIGHTBORDER ),
+ MP_E( PROP_TopBorder, XML_NAMESPACE_FO, XML_BORDER_TOP, XML_TYPE_BORDER, CTF_TOPBORDER ),
+ MP_E( PROP_BottomBorder, XML_NAMESPACE_FO, XML_BORDER_BOTTOM, XML_TYPE_BORDER, CTF_BOTTOMBORDER ),
+ // RES_SHADOW
+ MP_E( PROP_ParaShadowFormat, XML_NAMESPACE_STYLE, XML_SHADOW, XML_TYPE_TEXT_SHADOW, 0 ),
+ // RES_FRMMACRO
+ // not required
+ // RES_COL
+ // not required
+ // RES_KEEP
+ MP_E( PROP_ParaKeepTogether, XML_NAMESPACE_FO, XML_KEEP_WITH_NEXT, XML_TYPE_TEXT_KEEP, 0 ),
+ // RES_URL
+ // not required
+ // RES_EDIT_IN_READONLY
+ // not required
+ // RES_LAYOUT_SPLIT
+ // not required
+ // RES_CHAIN
+ // not required
+
+ // RES_LINENUMBER
+ MP_E( PROP_ParaLineNumberCount, XML_NAMESPACE_TEXT, XML_NUMBER_LINES, XML_TYPE_BOOL, 0 ),
+ MP_E( PROP_ParaLineNumberStartValue, XML_NAMESPACE_TEXT, XML_LINE_NUMBER, XML_TYPE_NUMBER, 0 ),
+
+ // RES_FTN_AT_TXTEND
+ // not required
+ // RES_END_AT_TXTEND
+ // not required
+ MP_ED( PROP_ParaIsCharacterDistance, XML_NAMESPACE_STYLE, XML_TEXT_AUTOSPACE, XML_TYPE_TEXT_AUTOSPACE, 0 ),
+ MP_ED( PROP_ParaIsHangingPunctuation, XML_NAMESPACE_STYLE, XML_PUNCTUATION_WRAP, XML_TYPE_TEXT_PUNCTUATION_WRAP, 0 ),
+ MP_ED( PROP_ParaIsForbiddenRules, XML_NAMESPACE_STYLE, XML_LINE_BREAK, XML_TYPE_TEXT_LINE_BREAK, 0 ),
+ MP_E( PROP_TabStopDistance, XML_NAMESPACE_STYLE, XML_TAB_STOP_DISTANCE, XML_TYPE_MEASURE, 0 ),
+ MAP_EXT_I( PROP_ParaTabStopDefaultDistance, XML_NAMESPACE_STYLE, XML_TAB_STOP_DISTANCE, XML_TYPE_MEASURE|XML_TYPE_PROP_PARAGRAPH, 0 ),
+ MAP_EXT( PROP_ParaTabStopDefaultDistance, XML_NAMESPACE_LO_EXT, XML_TAB_STOP_DISTANCE, XML_TYPE_MEASURE|XML_TYPE_PROP_PARAGRAPH, 0 ),
+
+ // RES_PARATR_VERTALIGN
+ MP_E( PROP_ParaVertAlignment, XML_NAMESPACE_STYLE, XML_VERTICAL_ALIGN, XML_TYPE_TEXT_VERTICAL_ALIGN, 0 ),
+
+ // RES_PARATR_SNAPTOGRID
+ MP_E( PROP_SnapToGrid, XML_NAMESPACE_STYLE, XML_SNAP_TO_LAYOUT_GRID, XML_TYPE_BOOL, 0 ),
+
+ MP_ED( PROP_WritingMode, XML_NAMESPACE_STYLE, XML_WRITING_MODE, XML_TYPE_TEXT_WRITING_MODE_WITH_DEFAULT, CTF_TEXTWRITINGMODE ),
+
+ MP_E( PROP_ParaIsConnectBorder, XML_NAMESPACE_STYLE, XML_JOIN_BORDER, XML_TYPE_BOOL, 0 ),
+
+ MP_E( PROP_DefaultOutlineLevel, XML_NAMESPACE_STYLE, XML_DEFAULT_OUTLINE_LEVEL, XML_TYPE_TEXT_NUMBER8_ONE_BASED|MID_FLAG_SPECIAL_ITEM_EXPORT|MID_FLAG_NO_PROPERTY_IMPORT, CTF_DEFAULT_OUTLINE_LEVEL ),
+
+ MP_ED( PROP_FontIndependentLineSpacing, XML_NAMESPACE_STYLE, XML_FONT_INDEPENDENT_LINE_SPACING, XML_TYPE_BOOL, 0 ),
+
+ MAP_EXT( PROP_ListAutoFormat, XML_NAMESPACE_LO_EXT, XML_MARKER_STYLE_NAME, XML_TYPE_STYLENAME|XML_TYPE_PROP_PARAGRAPH, 0 ),
+
+ M_END()
+};
+
+
+XMLPropertyMapEntry constexpr aXMLAdditionalTextDefaultsMap[] =
+{
+ // RES_FOLLOW_TEXT_FLOW - DVO #i18732#
+ MG_ED( PROP_IsFollowingTextFlow, XML_NAMESPACE_STYLE, XML_FLOW_WITH_TEXT, XML_TYPE_BOOL, 0 ),
+
+ // #i28701# - RES_WRAP_INFLUENCE_ON_OBJPOS
+ MG_ED( PROP_WrapInfluenceOnPosition, XML_NAMESPACE_DRAW, XML_WRAP_INFLUENCE_ON_POSITION, XML_TYPE_WRAP_INFLUENCE_ON_POSITION, 0 ),
+
+ M_END()
+};
+
+XMLPropertyMapEntry constexpr aXMLTextPropMap[] =
+{
+ // RES_CHRATR_CASEMAP
+ MT_E( PROP_CharCaseMap, XML_NAMESPACE_FO, XML_FONT_VARIANT, XML_TYPE_TEXT_CASEMAP_VAR, 0 ),
+ MT_E( PROP_CharCaseMap, XML_NAMESPACE_FO, XML_TEXT_TRANSFORM, XML_TYPE_TEXT_CASEMAP, 0 ),
+ // RES_CHRATR_COLOR
+ MT_ED( PROP_CharColor, XML_NAMESPACE_FO, XML_COLOR, XML_TYPE_COLORAUTO|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_ED( PROP_CharColor, XML_NAMESPACE_STYLE, XML_USE_WINDOW_FONT_COLOR, XML_TYPE_ISAUTOCOLOR|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MAP_EXT_I( PROP_CharTransparence, XML_NAMESPACE_DRAW, XML_OPACITY, XML_TYPE_NEG_PERCENT16 | XML_TYPE_PROP_TEXT, 0 ),
+ MAP_EXT( PROP_CharTransparence, XML_NAMESPACE_LO_EXT, XML_OPACITY, XML_TYPE_NEG_PERCENT16 | XML_TYPE_PROP_TEXT, 0 ),
+ MAP_EXT( PROP_CharComplexColor, XML_NAMESPACE_LO_EXT, XML_CHAR_COMPLEX_COLOR, XML_TYPE_COMPLEX_COLOR|XML_TYPE_PROP_TEXT|MID_FLAG_ELEMENT_ITEM, CTF_COMPLEX_COLOR ),
+ // RES_CHRATR_CONTOUR
+ MT_E( PROP_CharContoured, XML_NAMESPACE_STYLE, XML_TEXT_OUTLINE, XML_TYPE_BOOL, 0 ),
+ // RES_CHRATR_CROSSEDOUT
+ MT_E( PROP_CharStrikeout, XML_NAMESPACE_STYLE, XML_TEXT_LINE_THROUGH_STYLE, XML_TYPE_TEXT_CROSSEDOUT_STYLE|MID_FLAG_MERGE_PROPERTY, 0),
+ MT_E( PROP_CharStrikeout, XML_NAMESPACE_STYLE, XML_TEXT_LINE_THROUGH_TYPE, XML_TYPE_TEXT_CROSSEDOUT_TYPE|MID_FLAG_MERGE_PROPERTY, 0),
+ MT_E( PROP_CharStrikeout, XML_NAMESPACE_STYLE, XML_TEXT_LINE_THROUGH_WIDTH, XML_TYPE_TEXT_CROSSEDOUT_WIDTH|MID_FLAG_MERGE_PROPERTY, 0),
+ MT_E( PROP_CharStrikeout, XML_NAMESPACE_STYLE, XML_TEXT_LINE_THROUGH_TEXT, XML_TYPE_TEXT_CROSSEDOUT_TEXT|MID_FLAG_MERGE_PROPERTY, 0),
+ // RES_CHRATR_ESCAPEMENT
+ MT_E( PROP_CharEscapement, XML_NAMESPACE_STYLE, XML_TEXT_POSITION, XML_TYPE_TEXT_ESCAPEMENT|MID_FLAG_MERGE_ATTRIBUTE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ MT_E( PROP_CharEscapementHeight, XML_NAMESPACE_STYLE, XML_TEXT_POSITION, XML_TYPE_TEXT_ESCAPEMENT_HEIGHT|MID_FLAG_MERGE_ATTRIBUTE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ // RES_CHRATR_FONT
+ MT_ED( PROP_CharFontName, XML_NAMESPACE_STYLE, XML_FONT_NAME, XML_TYPE_STRING|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_FONTNAME ),
+ MT_ED( PROP_CharFontName, XML_NAMESPACE_FO, XML_FONT_FAMILY, XML_TYPE_TEXT_FONTFAMILYNAME|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_FONTFAMILYNAME ),
+ MT_ED( PROP_CharFontStyleName, XML_NAMESPACE_STYLE, XML_FONT_STYLE_NAME, XML_TYPE_STRING, CTF_FONTSTYLENAME ),
+ MT_ED( PROP_CharFontFamily, XML_NAMESPACE_STYLE, XML_FONT_FAMILY_GENERIC, XML_TYPE_TEXT_FONTFAMILY, CTF_FONTFAMILY ),
+ MT_ED( PROP_CharFontPitch, XML_NAMESPACE_STYLE, XML_FONT_PITCH, XML_TYPE_TEXT_FONTPITCH, CTF_FONTPITCH ),
+ MT_ED( PROP_CharFontCharSet, XML_NAMESPACE_STYLE, XML_FONT_CHARSET, XML_TYPE_TEXT_FONTENCODING, CTF_FONTCHARSET ),
+ // RES_CHRATR_FONTSIZE
+ MT_ED( PROP_CharHeight, XML_NAMESPACE_FO, XML_FONT_SIZE, XML_TYPE_CHAR_HEIGHT|MID_FLAG_MULTI_PROPERTY, CTF_CHARHEIGHT ),
+ MT_ED( PROP_CharPropHeight, XML_NAMESPACE_FO, XML_FONT_SIZE, XML_TYPE_CHAR_HEIGHT_PROP|MID_FLAG_MULTI_PROPERTY, CTF_CHARHEIGHT_REL ),
+ MT_ED( PROP_CharDiffHeight, XML_NAMESPACE_STYLE, XML_FONT_SIZE_REL, XML_TYPE_CHAR_HEIGHT_DIFF, CTF_CHARHEIGHT_DIFF ),
+ // RES_CHRATR_KERNING
+ MT_E( PROP_CharKerning, XML_NAMESPACE_FO, XML_LETTER_SPACING, XML_TYPE_TEXT_KERNING, 0 ),
+ // RES_CHRATR_LANGUAGE
+ MT_ED( PROP_CharLocale, XML_NAMESPACE_STYLE, XML_RFC_LANGUAGE_TAG, XML_TYPE_CHAR_RFC_LANGUAGE_TAG|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_ED( PROP_CharLocale, XML_NAMESPACE_FO, XML_LANGUAGE, XML_TYPE_CHAR_LANGUAGE|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_ED( PROP_CharLocale, XML_NAMESPACE_FO, XML_SCRIPT, XML_TYPE_CHAR_SCRIPT|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_ED( PROP_CharLocale, XML_NAMESPACE_FO, XML_COUNTRY, XML_TYPE_CHAR_COUNTRY|MID_FLAG_MERGE_PROPERTY, 0 ),
+ // RES_CHRATR_POSTURE
+ MT_E( PROP_CharPosture, XML_NAMESPACE_FO, XML_FONT_STYLE, XML_TYPE_TEXT_POSTURE, 0 ),
+ // RES_CHRATR_UNUSED1
+ // RES_CHRATR_SHADOWED
+ MT_E( PROP_CharShadowed, XML_NAMESPACE_FO, XML_TEXT_SHADOW, XML_TYPE_TEXT_SHADOWED, 0 ),
+ // VALIDATED UP TO THIS LINE
+ // RES_CHRATR_UNDERLINE
+ MT_E( PROP_CharUnderline, XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_STYLE, XML_TYPE_TEXT_UNDERLINE_STYLE|MID_FLAG_MERGE_PROPERTY, CTF_UNDERLINE ),
+ MT_E( PROP_CharUnderline, XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_TYPE, XML_TYPE_TEXT_UNDERLINE_TYPE|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_E( PROP_CharUnderline, XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_WIDTH, XML_TYPE_TEXT_UNDERLINE_WIDTH|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_E( PROP_CharUnderlineColor, XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_COLOR, XML_TYPE_TEXT_UNDERLINE_COLOR|MID_FLAG_MULTI_PROPERTY, CTF_UNDERLINE_COLOR ),
+ MT_E( PROP_CharUnderlineHasColor, XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_COLOR, XML_TYPE_TEXT_UNDERLINE_HASCOLOR|MID_FLAG_MERGE_ATTRIBUTE, CTF_UNDERLINE_HASCOLOR ),
+ // RES_CHRATR_WEIGHT
+ MT_E( PROP_CharWeight, XML_NAMESPACE_FO, XML_FONT_WEIGHT, XML_TYPE_TEXT_WEIGHT, 0 ),
+ // RES_CHRATR_RSID
+ { PROP_Rsid, XML_NAMESPACE_OFFICE_EXT, XML_RSID, XML_TYPE_HEX|XML_TYPE_PROP_TEXT, 0, SvtSaveOptions::ODFSVER_FUTURE_EXTENDED, false },
+ // RES_PARATR_RSID
+ { PROP_ParRsid, XML_NAMESPACE_OFFICE_EXT, XML_PARRSID, XML_TYPE_HEX|XML_TYPE_PROP_TEXT, 0, SvtSaveOptions::ODFSVER_FUTURE_EXTENDED, false },
+ // RES_CHRATR_WORDLINEMODE
+ MT_E( PROP_CharWordMode, XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_MODE, XML_TYPE_TEXT_LINE_MODE|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_E( PROP_CharWordMode, XML_NAMESPACE_STYLE, XML_TEXT_OVERLINE_MODE, XML_TYPE_TEXT_LINE_MODE|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_E( PROP_CharWordMode, XML_NAMESPACE_STYLE, XML_TEXT_LINE_THROUGH_MODE, XML_TYPE_TEXT_LINE_MODE|MID_FLAG_MERGE_PROPERTY, 0 ),
+ // RES_CHRATR_AUTOKERN
+ MT_E( PROP_CharAutoKerning, XML_NAMESPACE_STYLE, XML_LETTER_KERNING, XML_TYPE_BOOL, 0 ),
+ // RES_CHRATR_BLINK
+ MT_E( PROP_CharFlash, XML_NAMESPACE_STYLE, XML_TEXT_BLINKING, XML_TYPE_BOOL, 0 ),
+ // RES_CHRATR_NOHYPHEN
+ // TODO: not used?
+ // RES_CHRATR_UNUSED2
+ // RES_CHRATR_BACKGROUND
+ MT_E( PROP_CharBackColor, XML_NAMESPACE_FO, XML_BACKGROUND_COLOR, XML_TYPE_COLORTRANSPARENT|MID_FLAG_MULTI_PROPERTY, CTF_CHAR_BACKGROUND ),
+ MT_E( PROP_CharBackTransparent, XML_NAMESPACE_FO, XML_BACKGROUND_COLOR, XML_TYPE_ISTRANSPARENT|MID_FLAG_MERGE_ATTRIBUTE, CTF_CHAR_BACKGROUND_TRANSPARENCY),
+ { PROP_CharShadingValue, XML_NAMESPACE_LO_EXT, XML_CHAR_SHADING_VALUE, XML_TYPE_NUMBER|XML_TYPE_PROP_TEXT, 0, SvtSaveOptions::ODFSVER_FUTURE_EXTENDED, false },
+ MT_E( PROP_CharBackColor, XML_NAMESPACE_FO, XML_TEXT_BACKGROUND_COLOR, XML_TYPE_COLOR|MID_FLAG_SPECIAL_ITEM_EXPORT, CTF_OLDTEXTBACKGROUND ),
+ // RES_CHRATR_CJK_FONT
+ MT_ED( PROP_CharFontNameAsian, XML_NAMESPACE_STYLE, XML_FONT_NAME_ASIAN, XML_TYPE_STRING|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_FONTNAME_CJK ),
+ MT_ED( PROP_CharFontNameAsian, XML_NAMESPACE_STYLE, XML_FONT_FAMILY_ASIAN, XML_TYPE_TEXT_FONTFAMILYNAME|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_FONTFAMILYNAME_CJK ),
+ MT_ED( PROP_CharFontStyleNameAsian, XML_NAMESPACE_STYLE, XML_FONT_STYLE_NAME_ASIAN, XML_TYPE_STRING, CTF_FONTSTYLENAME_CJK ),
+ MT_ED( PROP_CharFontFamilyAsian, XML_NAMESPACE_STYLE, XML_FONT_FAMILY_GENERIC_ASIAN, XML_TYPE_TEXT_FONTFAMILY, CTF_FONTFAMILY_CJK ),
+ MT_ED( PROP_CharFontPitchAsian, XML_NAMESPACE_STYLE, XML_FONT_PITCH_ASIAN, XML_TYPE_TEXT_FONTPITCH, CTF_FONTPITCH_CJK ),
+ MT_ED( PROP_CharFontCharSetAsian, XML_NAMESPACE_STYLE, XML_FONT_CHARSET_ASIAN, XML_TYPE_TEXT_FONTENCODING, CTF_FONTCHARSET_CJK ),
+ // RES_CHRATR_CJK_FONTSIZE
+ MT_ED( PROP_CharHeightAsian, XML_NAMESPACE_STYLE, XML_FONT_SIZE_ASIAN, XML_TYPE_CHAR_HEIGHT|MID_FLAG_MULTI_PROPERTY, CTF_CHARHEIGHT_CJK ),
+ MT_ED( PROP_CharPropHeightAsian, XML_NAMESPACE_STYLE, XML_FONT_SIZE_ASIAN, XML_TYPE_CHAR_HEIGHT_PROP|MID_FLAG_MULTI_PROPERTY, CTF_CHARHEIGHT_REL_CJK ),
+ MT_ED( PROP_CharDiffHeightAsian, XML_NAMESPACE_STYLE, XML_FONT_SIZE_REL_ASIAN, XML_TYPE_CHAR_HEIGHT_DIFF, CTF_CHARHEIGHT_DIFF_CJK ),
+ // RES_CHRATR_CJK_LANGUAGE
+ MT_ED( PROP_CharLocaleAsian, XML_NAMESPACE_STYLE, XML_RFC_LANGUAGE_TAG_ASIAN, XML_TYPE_CHAR_RFC_LANGUAGE_TAG|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_ED( PROP_CharLocaleAsian, XML_NAMESPACE_STYLE, XML_LANGUAGE_ASIAN, XML_TYPE_CHAR_LANGUAGE|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_ED( PROP_CharLocaleAsian, XML_NAMESPACE_STYLE, XML_SCRIPT_ASIAN, XML_TYPE_CHAR_SCRIPT|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_ED( PROP_CharLocaleAsian, XML_NAMESPACE_STYLE, XML_COUNTRY_ASIAN, XML_TYPE_CHAR_COUNTRY|MID_FLAG_MERGE_PROPERTY, 0 ),
+ // RES_CHRATR_CJK_POSTURE
+ MT_E( PROP_CharPostureAsian, XML_NAMESPACE_STYLE, XML_FONT_STYLE_ASIAN, XML_TYPE_TEXT_POSTURE, 0 ),
+ // RES_CHRATR_CJK_WEIGHT
+ MT_E( PROP_CharWeightAsian, XML_NAMESPACE_STYLE, XML_FONT_WEIGHT_ASIAN, XML_TYPE_TEXT_WEIGHT, 0 ),
+ // RES_CHRATR_CTL_FONT
+ MT_ED( PROP_CharFontNameComplex, XML_NAMESPACE_STYLE, XML_FONT_NAME_COMPLEX, XML_TYPE_STRING|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_FONTNAME_CTL ),
+ MT_ED( PROP_CharFontNameComplex, XML_NAMESPACE_STYLE, XML_FONT_FAMILY_COMPLEX, XML_TYPE_TEXT_FONTFAMILYNAME|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_FONTFAMILYNAME_CTL ),
+ MT_ED( PROP_CharFontStyleNameComplex, XML_NAMESPACE_STYLE, XML_FONT_STYLE_NAME_COMPLEX, XML_TYPE_STRING, CTF_FONTSTYLENAME_CTL ),
+ MT_ED( PROP_CharFontFamilyComplex, XML_NAMESPACE_STYLE, XML_FONT_FAMILY_GENERIC_COMPLEX, XML_TYPE_TEXT_FONTFAMILY, CTF_FONTFAMILY_CTL ),
+ MT_ED( PROP_CharFontPitchComplex, XML_NAMESPACE_STYLE, XML_FONT_PITCH_COMPLEX, XML_TYPE_TEXT_FONTPITCH, CTF_FONTPITCH_CTL ),
+ MT_ED( PROP_CharFontCharSetComplex, XML_NAMESPACE_STYLE, XML_FONT_CHARSET_COMPLEX, XML_TYPE_TEXT_FONTENCODING, CTF_FONTCHARSET_CTL ),
+ // RES_CHRATR_CTL_FONTSIZE
+ MT_ED( PROP_CharHeightComplex, XML_NAMESPACE_STYLE, XML_FONT_SIZE_COMPLEX, XML_TYPE_CHAR_HEIGHT|MID_FLAG_MULTI_PROPERTY, CTF_CHARHEIGHT_CTL ),
+ MT_ED( PROP_CharPropHeightComplex, XML_NAMESPACE_STYLE, XML_FONT_SIZE_COMPLEX, XML_TYPE_CHAR_HEIGHT_PROP|MID_FLAG_MULTI_PROPERTY, CTF_CHARHEIGHT_REL_CTL ),
+ MT_ED( PROP_CharDiffHeightComplex, XML_NAMESPACE_STYLE, XML_FONT_SIZE_REL_COMPLEX, XML_TYPE_CHAR_HEIGHT_DIFF, CTF_CHARHEIGHT_DIFF_CTL ),
+ // RES_CHRATR_CTL_LANGUAGE
+ MT_ED( PROP_CharLocaleComplex, XML_NAMESPACE_STYLE, XML_RFC_LANGUAGE_TAG_COMPLEX, XML_TYPE_CHAR_RFC_LANGUAGE_TAG|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_ED( PROP_CharLocaleComplex, XML_NAMESPACE_STYLE, XML_LANGUAGE_COMPLEX, XML_TYPE_CHAR_LANGUAGE|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_ED( PROP_CharLocaleComplex, XML_NAMESPACE_STYLE, XML_SCRIPT_COMPLEX, XML_TYPE_CHAR_SCRIPT|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_ED( PROP_CharLocaleComplex, XML_NAMESPACE_STYLE, XML_COUNTRY_COMPLEX, XML_TYPE_CHAR_COUNTRY|MID_FLAG_MERGE_PROPERTY, 0 ),
+ // RES_CHRATR_CTL_POSTURE
+ MT_E( PROP_CharPostureComplex, XML_NAMESPACE_STYLE, XML_FONT_STYLE_COMPLEX, XML_TYPE_TEXT_POSTURE, 0 ),
+ // RES_CHRATR_CTL_WEIGHT
+ MT_E( PROP_CharWeightComplex, XML_NAMESPACE_STYLE, XML_FONT_WEIGHT_COMPLEX, XML_TYPE_TEXT_WEIGHT, 0 ),
+ // RES_CHRATR_ROTATE
+ MT_E( PROP_CharRotation, XML_NAMESPACE_STYLE, XML_TEXT_ROTATION_ANGLE, XML_TYPE_TEXT_ROTATION_ANGLE, 0 ),
+ MT_E( PROP_CharRotationIsFitToLine, XML_NAMESPACE_STYLE, XML_TEXT_ROTATION_SCALE, XML_TYPE_TEXT_ROTATION_SCALE, 0 ),
+ // RES_CHRATR_EMPHASIS_MARK
+ MT_E( PROP_CharEmphasis, XML_NAMESPACE_STYLE, XML_TEXT_EMPHASIZE, XML_TYPE_TEXT_EMPHASIZE, 0 ),
+ // RES_CHRATR_TWO_LINES
+ MT_E( PROP_CharCombineIsOn, XML_NAMESPACE_STYLE, XML_TEXT_COMBINE, XML_TYPE_TEXT_COMBINE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ MT_E( PROP_CharCombinePrefix, XML_NAMESPACE_STYLE, XML_TEXT_COMBINE_START_CHAR, XML_TYPE_TEXT_COMBINECHAR, 0 ),
+ MT_E( PROP_CharCombineSuffix, XML_NAMESPACE_STYLE, XML_TEXT_COMBINE_END_CHAR, XML_TYPE_TEXT_COMBINECHAR, 0 ),
+ // RES_CHRATR_SCALEW
+ MT_E( PROP_CharScaleWidth, XML_NAMESPACE_STYLE, XML_TEXT_SCALE, XML_TYPE_PERCENT16, 0 ),
+ // combined characters field, does not correspond to a property
+ MT_E( PROP_, XML_NAMESPACE_STYLE, XML_TEXT_COMBINE, XML_TYPE_TEXT_COMBINE_CHARACTERS|MID_FLAG_NO_PROPERTY, CTF_COMBINED_CHARACTERS_FIELD ),
+ //RES_CHRATR_RELIEF
+ MT_E( PROP_CharRelief, XML_NAMESPACE_STYLE, XML_FONT_RELIEF, XML_TYPE_TEXT_FONT_RELIEF, 0 ),
+ // RES_CHRATR_HIDDEN
+ MT_E( PROP_CharHidden, XML_NAMESPACE_TEXT, XML_DISPLAY, XML_TYPE_TEXT_HIDDEN_AS_DISPLAY|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_TEXT_DISPLAY ),
+ // RES_CHRATR_OVERLINE
+ MT_E( PROP_CharOverline, XML_NAMESPACE_STYLE, XML_TEXT_OVERLINE_STYLE, XML_TYPE_TEXT_OVERLINE_STYLE|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_E( PROP_CharOverline, XML_NAMESPACE_STYLE, XML_TEXT_OVERLINE_TYPE, XML_TYPE_TEXT_OVERLINE_TYPE|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_E( PROP_CharOverline, XML_NAMESPACE_STYLE, XML_TEXT_OVERLINE_WIDTH, XML_TYPE_TEXT_OVERLINE_WIDTH|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_E( PROP_CharOverlineColor, XML_NAMESPACE_STYLE, XML_TEXT_OVERLINE_COLOR, XML_TYPE_TEXT_OVERLINE_COLOR|MID_FLAG_MULTI_PROPERTY, 0 ),
+ MT_E( PROP_CharOverlineHasColor, XML_NAMESPACE_STYLE, XML_TEXT_OVERLINE_COLOR, XML_TYPE_TEXT_OVERLINE_HASCOLOR|MID_FLAG_MERGE_ATTRIBUTE, 0 ),
+ // RES_CHRATR_BOX
+ MAP_EXT( PROP_CharLeftBorder, XML_NAMESPACE_LO_EXT, XML_BORDER_LINE_WIDTH, XML_TYPE_BORDER_WIDTH|XML_TYPE_PROP_TEXT, CTF_CHARALLBORDERWIDTH ),
+ MAP_EXT( PROP_CharLeftBorder, XML_NAMESPACE_LO_EXT, XML_BORDER_LINE_WIDTH_LEFT, XML_TYPE_BORDER_WIDTH|XML_TYPE_PROP_TEXT, CTF_CHARLEFTBORDERWIDTH ),
+ MAP_EXT( PROP_CharRightBorder, XML_NAMESPACE_LO_EXT, XML_BORDER_LINE_WIDTH_RIGHT, XML_TYPE_BORDER_WIDTH|XML_TYPE_PROP_TEXT, CTF_CHARRIGHTBORDERWIDTH ),
+ MAP_EXT( PROP_CharTopBorder, XML_NAMESPACE_LO_EXT, XML_BORDER_LINE_WIDTH_TOP, XML_TYPE_BORDER_WIDTH|XML_TYPE_PROP_TEXT, CTF_CHARTOPBORDERWIDTH ),
+ MAP_EXT( PROP_CharBottomBorder, XML_NAMESPACE_LO_EXT, XML_BORDER_LINE_WIDTH_BOTTOM, XML_TYPE_BORDER_WIDTH|XML_TYPE_PROP_TEXT, CTF_CHARBOTTOMBORDERWIDTH ),
+ MAP_EXT_I( PROP_CharLeftBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH, XML_TYPE_BORDER_WIDTH|XML_TYPE_PROP_TEXT, CTF_CHARALLBORDERWIDTH ),
+ MAP_EXT_I( PROP_CharLeftBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_LEFT, XML_TYPE_BORDER_WIDTH|XML_TYPE_PROP_TEXT, CTF_CHARLEFTBORDERWIDTH ),
+ MAP_EXT_I( PROP_CharRightBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_RIGHT, XML_TYPE_BORDER_WIDTH|XML_TYPE_PROP_TEXT, CTF_CHARRIGHTBORDERWIDTH ),
+ MAP_EXT_I( PROP_CharTopBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_TOP, XML_TYPE_BORDER_WIDTH|XML_TYPE_PROP_TEXT, CTF_CHARTOPBORDERWIDTH ),
+ MAP_EXT_I( PROP_CharBottomBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_BOTTOM, XML_TYPE_BORDER_WIDTH|XML_TYPE_PROP_TEXT, CTF_CHARBOTTOMBORDERWIDTH ),
+
+ MAP_EXT( PROP_CharLeftBorderDistance, XML_NAMESPACE_LO_EXT, XML_PADDING, XML_TYPE_MEASURE|XML_TYPE_PROP_TEXT, CTF_CHARALLBORDERDISTANCE ),
+ MAP_EXT( PROP_CharLeftBorderDistance, XML_NAMESPACE_LO_EXT, XML_PADDING_LEFT, XML_TYPE_MEASURE|XML_TYPE_PROP_TEXT, CTF_CHARLEFTBORDERDISTANCE ),
+ MAP_EXT( PROP_CharRightBorderDistance, XML_NAMESPACE_LO_EXT, XML_PADDING_RIGHT, XML_TYPE_MEASURE|XML_TYPE_PROP_TEXT, CTF_CHARRIGHTBORDERDISTANCE ),
+ MAP_EXT( PROP_CharTopBorderDistance, XML_NAMESPACE_LO_EXT, XML_PADDING_TOP, XML_TYPE_MEASURE|XML_TYPE_PROP_TEXT, CTF_CHARTOPBORDERDISTANCE ),
+ MAP_EXT( PROP_CharBottomBorderDistance, XML_NAMESPACE_LO_EXT, XML_PADDING_BOTTOM, XML_TYPE_MEASURE|XML_TYPE_PROP_TEXT, CTF_CHARBOTTOMBORDERDISTANCE ),
+ MAP_EXT_I( PROP_CharLeftBorderDistance, XML_NAMESPACE_FO, XML_PADDING, XML_TYPE_MEASURE|XML_TYPE_PROP_TEXT, CTF_CHARALLBORDERDISTANCE ),
+ MAP_EXT_I( PROP_CharLeftBorderDistance, XML_NAMESPACE_FO, XML_PADDING_LEFT, XML_TYPE_MEASURE|XML_TYPE_PROP_TEXT, CTF_CHARLEFTBORDERDISTANCE ),
+ MAP_EXT_I( PROP_CharRightBorderDistance, XML_NAMESPACE_FO, XML_PADDING_RIGHT, XML_TYPE_MEASURE|XML_TYPE_PROP_TEXT, CTF_CHARRIGHTBORDERDISTANCE ),
+ MAP_EXT_I( PROP_CharTopBorderDistance, XML_NAMESPACE_FO, XML_PADDING_TOP, XML_TYPE_MEASURE|XML_TYPE_PROP_TEXT, CTF_CHARTOPBORDERDISTANCE ),
+ MAP_EXT_I( PROP_CharBottomBorderDistance, XML_NAMESPACE_FO, XML_PADDING_BOTTOM, XML_TYPE_MEASURE|XML_TYPE_PROP_TEXT, CTF_CHARBOTTOMBORDERDISTANCE ),
+
+ MAP_EXT( PROP_CharLeftBorder, XML_NAMESPACE_LO_EXT, XML_BORDER, XML_TYPE_BORDER|XML_TYPE_PROP_TEXT, CTF_CHARALLBORDER ),
+ MAP_EXT( PROP_CharLeftBorder, XML_NAMESPACE_LO_EXT, XML_BORDER_LEFT, XML_TYPE_BORDER|XML_TYPE_PROP_TEXT, CTF_CHARLEFTBORDER ),
+ MAP_EXT( PROP_CharRightBorder, XML_NAMESPACE_LO_EXT, XML_BORDER_RIGHT, XML_TYPE_BORDER|XML_TYPE_PROP_TEXT, CTF_CHARRIGHTBORDER ),
+ MAP_EXT( PROP_CharTopBorder, XML_NAMESPACE_LO_EXT, XML_BORDER_TOP, XML_TYPE_BORDER|XML_TYPE_PROP_TEXT, CTF_CHARTOPBORDER ),
+ MAP_EXT( PROP_CharBottomBorder, XML_NAMESPACE_LO_EXT, XML_BORDER_BOTTOM, XML_TYPE_BORDER|XML_TYPE_PROP_TEXT, CTF_CHARBOTTOMBORDER ),
+ MAP_EXT_I( PROP_CharLeftBorder, XML_NAMESPACE_FO, XML_BORDER, XML_TYPE_BORDER|XML_TYPE_PROP_TEXT, CTF_CHARALLBORDER ),
+ MAP_EXT_I( PROP_CharLeftBorder, XML_NAMESPACE_FO, XML_BORDER_LEFT, XML_TYPE_BORDER|XML_TYPE_PROP_TEXT, CTF_CHARLEFTBORDER ),
+ MAP_EXT_I( PROP_CharRightBorder, XML_NAMESPACE_FO, XML_BORDER_RIGHT, XML_TYPE_BORDER|XML_TYPE_PROP_TEXT, CTF_CHARRIGHTBORDER ),
+ MAP_EXT_I( PROP_CharTopBorder, XML_NAMESPACE_FO, XML_BORDER_TOP, XML_TYPE_BORDER|XML_TYPE_PROP_TEXT, CTF_CHARTOPBORDER ),
+ MAP_EXT_I( PROP_CharBottomBorder, XML_NAMESPACE_FO, XML_BORDER_BOTTOM, XML_TYPE_BORDER|XML_TYPE_PROP_TEXT, CTF_CHARBOTTOMBORDER ),
+ // RES_CHRATR_SHADOW
+ MAP_EXT( PROP_CharShadowFormat, XML_NAMESPACE_LO_EXT, XML_SHADOW, XML_TYPE_TEXT_SHADOW|XML_TYPE_PROP_TEXT, 0 ),
+ MAP_EXT_I( PROP_CharShadowFormat, XML_NAMESPACE_STYLE, XML_SHADOW, XML_TYPE_TEXT_SHADOW|XML_TYPE_PROP_TEXT, 0 ),
+ // RES_CHRATR_HIGHLIGHT
+ MT_E( PROP_CharHighlight, XML_NAMESPACE_FO, XML_BACKGROUND_COLOR, XML_TYPE_COLORTRANSPARENT|MID_FLAG_MULTI_PROPERTY|MID_FLAG_NO_PROPERTY_IMPORT, CTF_CHAR_HIGHLIGHT ),
+ // RES_TXTATR_INETFMT
+ MT_E( PROP_HyperLinkURL, XML_NAMESPACE_TEXT, XML_XMLNS, XML_TYPE_STRING|MID_FLAG_NO_PROPERTY_IMPORT, CTF_HYPERLINK_URL ),
+ // RES_TXTATR_REFMARK
+ // TODO
+ // RES_TXTATR_TOXMARK
+ // TODO
+ // RES_TXTATR_CHARFMT
+ MT_E( PROP_CharStyleName, XML_NAMESPACE_TEXT, XML_STYLE_NAME, XML_TYPE_STRING|MID_FLAG_NO_PROPERTY_IMPORT, CTF_CHAR_STYLE_NAME ),
+ // RES_TXTATR_CJK_RUBY
+ // TODO
+ // RES_TXTATR_FIELD
+ // TODO
+ // RES_TXTATR_FLYCNT
+ // TODO
+ // RES_TXTATR_FTN
+ // TODO
+ // RES_TXTATR_SOFTHYPH
+ // TODO
+ // RES_TXTATR_HARDBLANK
+ // TODO
+ // RES_UNKNOWNATR_CONTAINER
+ MT_E( PROP_TextUserDefinedAttributes, XML_NAMESPACE_TEXT, XML_XMLNS, XML_TYPE_ATTRIBUTE_CONTAINER | MID_FLAG_SPECIAL_ITEM, 0 ),
+ MT_ED( PROP_ParaIsCharacterDistance, XML_NAMESPACE_STYLE, XML_TEXT_AUTOSPACE, XML_TYPE_TEXT_AUTOSPACE, 0 ),
+ MT_ED( PROP_ParaIsHangingPunctuation, XML_NAMESPACE_STYLE, XML_PUNCTUATION_WRAP, XML_TYPE_TEXT_PUNCTUATION_WRAP, 0 ),
+ MT_ED( PROP_ParaIsForbiddenRules, XML_NAMESPACE_STYLE, XML_LINE_BREAK, XML_TYPE_TEXT_LINE_BREAK, 0 ),
+ MT_E( PROP_TabStopDistance, XML_NAMESPACE_STYLE, XML_TAB_STOP_DISTANCE, XML_TYPE_MEASURE, 0 ),
+
+ M_END()
+};
+
+XMLPropertyMapEntry constexpr aXMLFramePropMap[] =
+{
+ // RES_FILL_ORDER
+ // TODO: not required???
+ // RES_FRM_SIZE
+ MG_ED( PROP_Width, XML_NAMESPACE_SVG, XML_WIDTH, XML_TYPE_MEASURE, CTF_FRAMEWIDTH_ABS ),
+ MG_ED( PROP_Width, XML_NAMESPACE_FO, XML_MIN_WIDTH, XML_TYPE_MEASURE|MID_FLAG_MULTI_PROPERTY, CTF_FRAMEWIDTH_MIN_ABS ),
+ MG_ED( PROP_RelativeWidth, XML_NAMESPACE_FO, XML_MIN_WIDTH, XML_TYPE_TEXT_REL_WIDTH_HEIGHT, CTF_FRAMEWIDTH_MIN_REL ),
+ MG_ED( PROP_RelativeWidth, XML_NAMESPACE_STYLE, XML_REL_WIDTH, XML_TYPE_TEXT_REL_WIDTH_HEIGHT, CTF_FRAMEWIDTH_REL ),
+ MG_ED( PROP_WidthType, XML_NAMESPACE_FO, XML_TEXT_BOX, XML_TYPE_NUMBER16|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_FRAMEWIDTH_TYPE ),
+// M_ED( "RelativeWidth", XML_NAMESPACE_STYLE, XML_REL_WIDTH, XML_TYPE_TEXT_REL_WIDTH_HEIGHT|MID_FLAG_MULTI_PROPERTY, 0 ),
+// M_ED( "IsSyncWidthToHeight", XML_NAMESPACE_STYLE, XML_REL_WIDTH, XML_TYPE_TEXT_SYNC_WIDTH_HEIGHT|MID_FLAG_MULTI_PROPERTY, 0 ),
+
+ MG_ED( PROP_Height, XML_NAMESPACE_SVG, XML_HEIGHT, XML_TYPE_MEASURE, CTF_FRAMEHEIGHT_ABS ),
+ MG_ED( PROP_Height, XML_NAMESPACE_FO, XML_MIN_HEIGHT, XML_TYPE_MEASURE|MID_FLAG_MULTI_PROPERTY, CTF_FRAMEHEIGHT_MIN_ABS ),
+ MG_ED( PROP_RelativeHeight, XML_NAMESPACE_FO, XML_MIN_HEIGHT, XML_TYPE_TEXT_REL_WIDTH_HEIGHT, CTF_FRAMEHEIGHT_MIN_REL ),
+ MG_ED( PROP_RelativeHeight, XML_NAMESPACE_STYLE, XML_REL_HEIGHT, XML_TYPE_TEXT_REL_WIDTH_HEIGHT, CTF_FRAMEHEIGHT_REL ),
+// M_ED( "RelativeHeight", XML_NAMESPACE_STYLE, XML_REL_HEIGHT, XML_TYPE_TEXT_REL_WIDTH_HEIGHT|MID_FLAG_MULTI_PROPERTY, CTF_FRAMEHEIGHT_REL ),
+// M_ED( "IsSyncHeightToWidth", XML_NAMESPACE_STYLE, XML_REL_HEIGHT, XML_TYPE_TEXT_SYNC_WIDTH_HEIGHT|MID_FLAG_MULTI_PROPERTY, CTF_SYNCHEIGHT ),
+// M_ED( "IsSyncHeightToWidth", XML_NAMESPACE_STYLE, XML_REL_HEIGHT, XML_TYPE_TEXT_SYNC_WIDTH_HEIGHT_MIN, CTF_SYNCHEIGHT_MIN ),
+ MG_ED( PROP_SizeType, XML_NAMESPACE_FO, XML_TEXT_BOX, XML_TYPE_NUMBER16|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_SIZETYPE ),
+ // RES_PAPER_BIN
+ // not required
+ // RES_ANCHOR
+ // moved to here because it is not used for automatic styles
+ MG_ED( PROP_AnchorType, XML_NAMESPACE_TEXT, XML_ANCHOR_TYPE, XML_TYPE_TEXT_ANCHOR_TYPE, CTF_ANCHORTYPE ),
+ // AnchorPage number is not required for styles!
+ MG_ED( PROP_HoriOrientPosition, XML_NAMESPACE_SVG, XML_X, XML_TYPE_MEASURE, 0 ),
+ MG_ED( PROP_VertOrientPosition, XML_NAMESPACE_SVG, XML_Y, XML_TYPE_MEASURE, 0 ),
+ // ***** The map for automatic styles starts here *****
+ // RES_LR_SPACE
+ MG_E( PROP_LeftMargin, XML_NAMESPACE_FO, XML_MARGIN, XML_TYPE_MEASURE, CTF_MARGINALL ),
+ MG_E( PROP_LeftMargin, XML_NAMESPACE_FO, XML_MARGIN_LEFT, XML_TYPE_MEASURE, CTF_MARGINLEFT ),
+ MG_E( PROP_RightMargin, XML_NAMESPACE_FO, XML_MARGIN_RIGHT, XML_TYPE_MEASURE, CTF_MARGINRIGHT ),
+ // RES_UL_SPACE
+ MG_E( PROP_TopMargin, XML_NAMESPACE_FO, XML_MARGIN_TOP, XML_TYPE_MEASURE, CTF_MARGINTOP ),
+ MG_E( PROP_BottomMargin, XML_NAMESPACE_FO, XML_MARGIN_BOTTOM, XML_TYPE_MEASURE, CTF_MARGINBOTTOM ),
+ // RES_PAGEDESC
+ // not required
+ // RES_BREAK
+ // not required
+ // RES_CNTNT
+ // not required (accessed using API)
+ // RES_HEADER
+ // not required
+ // RES_FOOTER
+ // not required
+ // RES_PRINT
+ MG_E( PROP_Print, XML_NAMESPACE_STYLE, XML_PRINT_CONTENT, XML_TYPE_BOOL, 0 ),
+ // RES_OPAQUE
+ MG_ED( PROP_Opaque, XML_NAMESPACE_STYLE, XML_RUN_THROUGH, XML_TYPE_TEXT_OPAQUE, 0 ),
+ // RES_PROTECT
+ MG_E( PROP_ContentProtected, XML_NAMESPACE_STYLE, XML_PROTECT, XML_TYPE_TEXT_PROTECT_CONTENT|MID_FLAG_MERGE_ATTRIBUTE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ MG_E( PROP_SizeProtected, XML_NAMESPACE_STYLE, XML_PROTECT, XML_TYPE_TEXT_PROTECT_SIZE|MID_FLAG_MERGE_ATTRIBUTE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ MG_E( PROP_PositionProtected, XML_NAMESPACE_STYLE, XML_PROTECT, XML_TYPE_TEXT_PROTECT_POSITION|MID_FLAG_MERGE_ATTRIBUTE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ // RES_SURROUND
+ MG_ED( PROP_TextWrap, XML_NAMESPACE_STYLE, XML_WRAP, XML_TYPE_TEXT_WRAP, CTF_WRAP ),
+ MG_ED( PROP_SurroundAnchorOnly, XML_NAMESPACE_STYLE, XML_NUMBER_WRAPPED_PARAGRAPHS, XML_TYPE_TEXT_PARAGRAPH_ONLY, CTF_WRAP_PARAGRAPH_ONLY ),
+ MG_E( PROP_SurroundContour, XML_NAMESPACE_STYLE, XML_WRAP_CONTOUR, XML_TYPE_BOOL, CTF_WRAP_CONTOUR ),
+ MG_E( PROP_ContourOutside, XML_NAMESPACE_STYLE, XML_WRAP_CONTOUR_MODE, XML_TYPE_TEXT_WRAP_OUTSIDE, CTF_WRAP_CONTOUR_MODE ),
+ // RES_VERT_ORIENT
+ MG_ED( PROP_VertOrient, XML_NAMESPACE_STYLE, XML_VERTICAL_POS, XML_TYPE_TEXT_VERTICAL_POS, CTF_VERTICALPOS ),
+ MG_ED( PROP_VertOrient, XML_NAMESPACE_STYLE, XML_VERTICAL_POS, XML_TYPE_TEXT_VERTICAL_POS_AT_CHAR, CTF_VERTICALPOS_ATCHAR ),
+ MG_ED( PROP_VertOrient, XML_NAMESPACE_STYLE, XML_VERTICAL_REL, XML_TYPE_TEXT_VERTICAL_REL_AS_CHAR|MID_FLAG_MULTI_PROPERTY, CTF_VERTICALREL_ASCHAR ),
+ MG_ED( PROP_VertOrientRelation, XML_NAMESPACE_STYLE, XML_VERTICAL_REL, XML_TYPE_TEXT_VERTICAL_REL, CTF_VERTICALREL ),
+ MG_ED( PROP_VertOrientRelation, XML_NAMESPACE_STYLE, XML_VERTICAL_REL, XML_TYPE_TEXT_VERTICAL_REL_PAGE|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_VERTICALREL_PAGE ),
+ MG_ED( PROP_VertOrientRelation, XML_NAMESPACE_STYLE, XML_VERTICAL_REL, XML_TYPE_TEXT_VERTICAL_REL_FRAME|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_VERTICALREL_FRAME ),
+ MAP_EXT_I( PROP_VertOrientRelation, XML_NAMESPACE_LO_EXT, XML_VERTICAL_REL, XML_TYPE_TEXT_VERTICAL_REL|XML_TYPE_PROP_GRAPHIC|MID_FLAG_DEFAULT_ITEM_EXPORT, CTF_VERTICALREL ),
+ MAP_EXT_I( PROP_VertOrientRelation, XML_NAMESPACE_LO_EXT, XML_VERTICAL_REL, XML_TYPE_TEXT_VERTICAL_REL_PAGE|MID_FLAG_SPECIAL_ITEM_IMPORT|XML_TYPE_PROP_GRAPHIC|MID_FLAG_DEFAULT_ITEM_EXPORT, CTF_VERTICALREL_PAGE ),
+ MAP_EXT_I( PROP_VertOrientRelation, XML_NAMESPACE_LO_EXT, XML_VERTICAL_REL, XML_TYPE_TEXT_VERTICAL_REL_FRAME|MID_FLAG_SPECIAL_ITEM_IMPORT|XML_TYPE_PROP_GRAPHIC|MID_FLAG_DEFAULT_ITEM_EXPORT, CTF_VERTICALREL_FRAME ),
+ // RES_HORI_ORIENT
+ MG_ED( PROP_HoriOrient, XML_NAMESPACE_STYLE, XML_HORIZONTAL_POS, XML_TYPE_TEXT_HORIZONTAL_POS|MID_FLAG_MULTI_PROPERTY, CTF_HORIZONTALPOS ),
+ MG_ED( PROP_PageToggle, XML_NAMESPACE_STYLE, XML_HORIZONTAL_POS, XML_TYPE_TEXT_HORIZONTAL_MIRROR, CTF_HORIZONTALMIRROR ),
+ MG_ED( PROP_HoriOrient, XML_NAMESPACE_STYLE, XML_HORIZONTAL_POS, XML_TYPE_TEXT_HORIZONTAL_POS_MIRRORED|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_HORIZONTALPOS_MIRRORED ),
+ MG_ED( PROP_HoriOrientRelation, XML_NAMESPACE_STYLE, XML_HORIZONTAL_REL, XML_TYPE_TEXT_HORIZONTAL_REL, CTF_HORIZONTALREL ),
+ MG_ED( PROP_HoriOrientRelation, XML_NAMESPACE_STYLE, XML_HORIZONTAL_REL, XML_TYPE_TEXT_HORIZONTAL_REL_FRAME|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_HORIZONTALREL_FRAME ),
+ // RES_ANCHOR
+ // see above
+ // RES_BACKGROUND
+ // DO NOT REORDER these!
+ MG_ED( PROP_BackColorRGB, XML_NAMESPACE_FO, XML_BACKGROUND_COLOR, XML_TYPE_COLORTRANSPARENT|MID_FLAG_MULTI_PROPERTY, 0 ),
+ MG_ED( PROP_BackTransparent, XML_NAMESPACE_FO, XML_BACKGROUND_COLOR, XML_TYPE_ISTRANSPARENT|MID_FLAG_MERGE_ATTRIBUTE|MID_FLAG_MULTI_PROPERTY, CTF_BACKGROUND_TRANSPARENT ),
+ MG_ED( PROP_BackColorTransparency, XML_NAMESPACE_STYLE, XML_BACKGROUND_TRANSPARENCY, XML_TYPE_PERCENT8, CTF_BACKGROUND_TRANSPARENCY ),
+
+ MG_E( PROP_BackGraphicTransparency, XML_NAMESPACE_STYLE, XML_BACKGROUND_IMAGE_TRANSPARENCY, MID_FLAG_SPECIAL_ITEM|XML_TYPE_PERCENT8, CTF_BACKGROUND_TRANSPARENCY ),
+ MG_E( PROP_BackGraphicLocation, XML_NAMESPACE_STYLE, XML_POSITION, MID_FLAG_SPECIAL_ITEM|XML_TYPE_BUILDIN_CMP_ONLY, CTF_BACKGROUND_POS ),
+ MG_E( PROP_BackGraphicFilter, XML_NAMESPACE_STYLE, XML_FILTER_NAME, MID_FLAG_SPECIAL_ITEM|XML_TYPE_STRING, CTF_BACKGROUND_FILTER ),
+ MG_E( PROP_BackGraphic, XML_NAMESPACE_STYLE, XML_BACKGROUND_IMAGE, MID_FLAG_ELEMENT_ITEM|XML_TYPE_GRAPHIC, CTF_BACKGROUND_URL ),
+
+ // fill attributes
+ GMAP( PROP_FillStyle, XML_NAMESPACE_DRAW, XML_FILL, XML_SW_TYPE_FILLSTYLE, 0 ),
+ GMAP( PROP_FillColor, XML_NAMESPACE_DRAW, XML_FILL_COLOR, XML_TYPE_COLOR, 0 ),
+ GMAP( PROP_FillColor2, XML_NAMESPACE_DRAW, XML_SECONDARY_FILL_COLOR, XML_TYPE_COLOR, 0 ),
+ GMAP( PROP_FillGradientName, XML_NAMESPACE_DRAW, XML_FILL_GRADIENT_NAME, XML_TYPE_STYLENAME|MID_FLAG_NO_PROPERTY_IMPORT, CTF_FILLGRADIENTNAME ),
+ GMAP( PROP_FillGradientStepCount, XML_NAMESPACE_DRAW, XML_GRADIENT_STEP_COUNT, XML_TYPE_NUMBER16, 0 ),
+ GMAP( PROP_FillHatchName, XML_NAMESPACE_DRAW, XML_FILL_HATCH_NAME, XML_TYPE_STYLENAME|MID_FLAG_NO_PROPERTY_IMPORT, CTF_FILLHATCHNAME ),
+ GMAP( PROP_FillBackground, XML_NAMESPACE_DRAW, XML_FILL_HATCH_SOLID, XML_TYPE_BOOL, 0 ),
+ GMAP( PROP_FillBitmapName, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_NAME, XML_TYPE_STYLENAME|MID_FLAG_NO_PROPERTY_IMPORT, CTF_FILLBITMAPNAME ),
+ GMAP( PROP_FillTransparence, XML_NAMESPACE_DRAW, XML_OPACITY, XML_TYPE_NEG_PERCENT16|MID_FLAG_MULTI_PROPERTY, 0 ), // exists in SW, too
+ GMAP( PROP_FillTransparenceGradientName, XML_NAMESPACE_DRAW, XML_OPACITY_NAME, XML_TYPE_STYLENAME|MID_FLAG_NO_PROPERTY_IMPORT, CTF_FILLTRANSNAME ),
+ GMAP( PROP_FillBitmapSizeX, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_WIDTH, XML_SW_TYPE_FILLBITMAPSIZE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ GMAP( PROP_FillBitmapLogicalSize, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_WIDTH, XML_SW_TYPE_LOGICAL_SIZE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ GMAP( PROP_FillBitmapSizeY, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_HEIGHT, XML_SW_TYPE_FILLBITMAPSIZE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ GMAP( PROP_FillBitmapLogicalSize, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_HEIGHT, XML_SW_TYPE_LOGICAL_SIZE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ GMAP( PROP_FillBitmapMode, XML_NAMESPACE_STYLE, XML_REPEAT, XML_SW_TYPE_BITMAP_MODE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ GMAP( PROP_FillBitmapPositionOffsetX, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_REF_POINT_X, XML_TYPE_PERCENT, 0 ),
+ GMAP( PROP_FillBitmapPositionOffsetY, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_REF_POINT_Y, XML_TYPE_PERCENT, 0 ),
+ GMAP( PROP_FillBitmapRectanglePoint, XML_NAMESPACE_DRAW, XML_FILL_IMAGE_REF_POINT, XML_SW_TYPE_BITMAP_REFPOINT, 0 ),
+ GMAP( PROP_FillBitmapOffsetX, XML_NAMESPACE_DRAW, XML_TILE_REPEAT_OFFSET, XML_SW_TYPE_BITMAPREPOFFSETX|MID_FLAG_MULTI_PROPERTY, CTF_REPEAT_OFFSET_X ),
+ GMAP( PROP_FillBitmapOffsetY, XML_NAMESPACE_DRAW, XML_TILE_REPEAT_OFFSET, XML_SW_TYPE_BITMAPREPOFFSETY|MID_FLAG_MULTI_PROPERTY, CTF_REPEAT_OFFSET_Y ),
+
+ // RES_BOX
+ MG_ED( PROP_LeftBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH, XML_TYPE_BORDER_WIDTH, CTF_ALLBORDERWIDTH ),
+ MG_ED( PROP_LeftBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_LEFT, XML_TYPE_BORDER_WIDTH, CTF_LEFTBORDERWIDTH ),
+ MG_ED( PROP_RightBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_RIGHT, XML_TYPE_BORDER_WIDTH, CTF_RIGHTBORDERWIDTH ),
+ MG_ED( PROP_TopBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_TOP, XML_TYPE_BORDER_WIDTH, CTF_TOPBORDERWIDTH ),
+ MG_ED( PROP_BottomBorder, XML_NAMESPACE_STYLE, XML_BORDER_LINE_WIDTH_BOTTOM, XML_TYPE_BORDER_WIDTH, CTF_BOTTOMBORDERWIDTH ),
+
+ MG_ED( PROP_LeftBorderDistance, XML_NAMESPACE_FO, XML_PADDING, XML_TYPE_MEASURE, CTF_ALLBORDERDISTANCE ), // need special import filtering
+ MG_ED( PROP_LeftBorderDistance, XML_NAMESPACE_FO, XML_PADDING_LEFT, XML_TYPE_MEASURE, CTF_LEFTBORDERDISTANCE ),
+ MG_ED( PROP_RightBorderDistance, XML_NAMESPACE_FO, XML_PADDING_RIGHT, XML_TYPE_MEASURE, CTF_RIGHTBORDERDISTANCE ),
+ MG_ED( PROP_TopBorderDistance, XML_NAMESPACE_FO, XML_PADDING_TOP, XML_TYPE_MEASURE, CTF_TOPBORDERDISTANCE ),
+ MG_ED( PROP_BottomBorderDistance, XML_NAMESPACE_FO, XML_PADDING_BOTTOM, XML_TYPE_MEASURE, CTF_BOTTOMBORDERDISTANCE ),
+
+ // There is an additional property for controls!
+ MG_ED( PROP_LeftBorder, XML_NAMESPACE_FO, XML_BORDER, XML_TYPE_BORDER|MID_FLAG_MULTI_PROPERTY, CTF_ALLBORDER ),
+ MG_ED( PROP_LeftBorder, XML_NAMESPACE_FO, XML_BORDER_LEFT, XML_TYPE_BORDER, CTF_LEFTBORDER ),
+ MG_ED( PROP_RightBorder, XML_NAMESPACE_FO, XML_BORDER_RIGHT, XML_TYPE_BORDER, CTF_RIGHTBORDER ),
+ MG_ED( PROP_TopBorder, XML_NAMESPACE_FO, XML_BORDER_TOP, XML_TYPE_BORDER, CTF_TOPBORDER ),
+ MG_ED( PROP_BottomBorder, XML_NAMESPACE_FO, XML_BORDER_BOTTOM, XML_TYPE_BORDER, CTF_BOTTOMBORDER ),
+ // RES_SHADOW
+ MG_E( PROP_ShadowFormat, XML_NAMESPACE_STYLE, XML_SHADOW, XML_TYPE_TEXT_SHADOW, 0 ),
+ MG_E( PROP_ShadowTransparence, XML_NAMESPACE_DRAW, XML_SHADOW_OPACITY, XML_TYPE_NEG_PERCENT, 0 ),
+ // RES_FRMMACRO
+ // TODO
+ // RES_COL
+ MG_E( PROP_TextColumns, XML_NAMESPACE_STYLE, XML_COLUMNS, MID_FLAG_ELEMENT_ITEM|XML_TYPE_TEXT_COLUMNS, CTF_TEXTCOLUMNS ),
+ // RES_KEEP
+ // not required
+ // RES_URL
+ // not required (exported as draw:a element)
+ // RES_EDIT_IN_READONLY
+ MG_ED( PROP_EditInReadonly, XML_NAMESPACE_STYLE, XML_EDITABLE, XML_TYPE_BOOL, 0 ),
+ // RES_LAYOUT_SPLIT
+ // not required
+ // RES_CHAIN
+ // not required (exported at text:text-box element)
+ // RES_LINENUMBER
+ // not required
+ // RES_FTN_AT_TXTEND
+ // not required
+ // RES_END_AT_TXTEND
+ // not required
+ // RES_COLUMNBALANCE
+ // TODO
+ // RES_UNKNOWNATR_CONTAINER
+// M_E_SE( TEXT, xmlns, RES_UNKNOWNATR_CONTAINER, 0 ),
+ // RES_GRFATR_MIRRORGRF (vertical MUST be processed after horizontal!)
+ MG_E( PROP_HoriMirroredOnEvenPages, XML_NAMESPACE_STYLE, XML_MIRROR, XML_TYPE_TEXT_MIRROR_HORIZONTAL_LEFT|MID_FLAG_MERGE_ATTRIBUTE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ MG_E( PROP_HoriMirroredOnOddPages, XML_NAMESPACE_STYLE, XML_MIRROR, XML_TYPE_TEXT_MIRROR_HORIZONTAL_RIGHT|MID_FLAG_MERGE_ATTRIBUTE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ MG_E( PROP_VertMirrored, XML_NAMESPACE_STYLE, XML_MIRROR, XML_TYPE_TEXT_MIRROR_VERTICAL|MID_FLAG_MERGE_ATTRIBUTE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ // RES_GRFATR_CROPGRF
+ MG_EV( PROP_GraphicCrop, XML_NAMESPACE_FO, XML_CLIP, XML_TYPE_TEXT_CLIP, CTF_TEXT_CLIP, SvtSaveOptions::ODFSVER_012 ),
+ MG_E( PROP_GraphicCrop, XML_NAMESPACE_FO, XML_CLIP, XML_TYPE_TEXT_CLIP11, CTF_TEXT_CLIP11 ),
+ // RES_GRFATR_ROTATION
+ // not required (exported as svg:transform attribute)
+ // RES_GRFATR_LUMINANCE
+ MG_E( PROP_AdjustLuminance, XML_NAMESPACE_DRAW, XML_LUMINANCE, XML_TYPE_PERCENT16, 0 ), // signed?
+ // RES_GRFATR_CONTRAST
+ MG_E( PROP_AdjustContrast, XML_NAMESPACE_DRAW, XML_CONTRAST, XML_TYPE_PERCENT16, 0 ), // signed?
+ // RES_GRFATR_CHANNELR
+ MG_E( PROP_AdjustRed, XML_NAMESPACE_DRAW, XML_RED, XML_TYPE_PERCENT16, 0 ), // signed?
+ // RES_GRFATR_CHANNELG
+ MG_E( PROP_AdjustGreen, XML_NAMESPACE_DRAW, XML_GREEN, XML_TYPE_PERCENT16, 0 ), // signed?
+ // RES_GRFATR_CHANNELB
+ MG_E( PROP_AdjustBlue, XML_NAMESPACE_DRAW, XML_BLUE, XML_TYPE_PERCENT16, 0 ), // signed?
+ // RES_GRFATR_GAMMA
+ MG_E( PROP_Gamma, XML_NAMESPACE_DRAW, XML_GAMMA, XML_TYPE_DOUBLE_PERCENT, 0 ), // signed?
+ // RES_GRFATR_INVERT
+ MG_E( PROP_GraphicIsInverted, XML_NAMESPACE_DRAW, XML_COLOR_INVERSION, XML_TYPE_BOOL, 0 ),
+ // RES_GRFATR_TRANSPARENCY
+ MG_E( PROP_Transparency, XML_NAMESPACE_DRAW, XML_IMAGE_OPACITY, XML_TYPE_NEG_PERCENT16|MID_FLAG_MULTI_PROPERTY, 0 ), // #i25616#
+ // RES_GRFATR_DRAWMODE
+ MG_E( PROP_GraphicColorMode, XML_NAMESPACE_DRAW, XML_COLOR_MODE, XML_TYPE_COLOR_MODE, 0 ),
+ MG_E( PROP_WritingMode, XML_NAMESPACE_STYLE, XML_WRITING_MODE, XML_TYPE_TEXT_WRITING_MODE_WITH_DEFAULT, 0 ),
+ MAP_EXT_I( PROP_WritingMode, XML_NAMESPACE_LO_EXT, XML_WRITING_MODE, XML_TYPE_TEXT_WRITING_MODE_WITH_DEFAULT|XML_TYPE_PROP_GRAPHIC, 0),
+ // RES_FOLLOW_TEXT_FLOW - DVO #i18732#
+ MG_E( PROP_IsFollowingTextFlow, XML_NAMESPACE_DRAW, XML_FLOW_WITH_TEXT, XML_TYPE_BOOL|MID_FLAG_SPECIAL_ITEM_EXPORT, CTF_OLD_FLOW_WITH_TEXT ),
+ MG_E( PROP_IsFollowingTextFlow, XML_NAMESPACE_STYLE, XML_FLOW_WITH_TEXT, XML_TYPE_BOOL, 0 ),
+ // #i28701# - RES_WRAP_INFLUENCE_ON_OBJPOS
+ MG_E( PROP_WrapInfluenceOnPosition, XML_NAMESPACE_DRAW, XML_WRAP_INFLUENCE_ON_POSITION, XML_TYPE_WRAP_INFLUENCE_ON_POSITION, 0 ),
+ MAP_EXT( PROP_AllowOverlap, XML_NAMESPACE_LO_EXT, XML_ALLOW_OVERLAP, XML_TYPE_BOOL|XML_TYPE_PROP_GRAPHIC, 0 ),
+ MAP_EXT( PROP_WrapTextAtFlyStart, XML_NAMESPACE_LO_EXT, XML_WRAP_TEXT_AT_FRAME_START, XML_TYPE_BOOL|XML_TYPE_PROP_GRAPHIC, 0 ),
+
+ // special entries for floating frames
+ MG_E( PROP_, XML_NAMESPACE_DRAW, XML_FRAME_DISPLAY_SCROLLBAR, XML_TYPE_BOOL|MID_FLAG_NO_PROPERTY|MID_FLAG_MULTI_PROPERTY, CTF_FRAME_DISPLAY_SCROLLBAR ),
+ MG_E( PROP_, XML_NAMESPACE_DRAW, XML_FRAME_DISPLAY_BORDER, XML_TYPE_BOOL|MID_FLAG_NO_PROPERTY|MID_FLAG_MULTI_PROPERTY, CTF_FRAME_DISPLAY_BORDER ),
+ MG_E( PROP_, XML_NAMESPACE_DRAW, XML_FRAME_MARGIN_HORIZONTAL, XML_TYPE_MEASURE_PX|MID_FLAG_NO_PROPERTY|MID_FLAG_MULTI_PROPERTY, CTF_FRAME_MARGIN_HORI ),
+ MG_E( PROP_, XML_NAMESPACE_DRAW, XML_FRAME_MARGIN_VERTICAL, XML_TYPE_MEASURE_PX|MID_FLAG_NO_PROPERTY|MID_FLAG_MULTI_PROPERTY, CTF_FRAME_MARGIN_VERT ),
+ MG_E( PROP_, XML_NAMESPACE_DRAW, XML_VISIBLE_AREA_LEFT, XML_TYPE_MEASURE|MID_FLAG_NO_PROPERTY|MID_FLAG_MULTI_PROPERTY, CTF_OLE_VIS_AREA_LEFT ),
+ MG_E( PROP_, XML_NAMESPACE_DRAW, XML_VISIBLE_AREA_TOP, XML_TYPE_MEASURE|MID_FLAG_NO_PROPERTY|MID_FLAG_MULTI_PROPERTY, CTF_OLE_VIS_AREA_TOP ),
+ MG_E( PROP_, XML_NAMESPACE_DRAW, XML_VISIBLE_AREA_WIDTH, XML_TYPE_MEASURE|MID_FLAG_NO_PROPERTY|MID_FLAG_MULTI_PROPERTY, CTF_OLE_VIS_AREA_WIDTH ),
+ MG_E( PROP_, XML_NAMESPACE_DRAW, XML_VISIBLE_AREA_HEIGHT, XML_TYPE_MEASURE|MID_FLAG_NO_PROPERTY|MID_FLAG_MULTI_PROPERTY, CTF_OLE_VIS_AREA_HEIGHT ),
+ MG_E( PROP_, XML_NAMESPACE_DRAW, XML_DRAW_ASPECT, XML_TYPE_TEXT_DRAW_ASPECT|MID_FLAG_NO_PROPERTY|MID_FLAG_MULTI_PROPERTY, CTF_OLE_DRAW_ASPECT ),
+
+ MG_E( PROP_UserDefinedAttributes, XML_NAMESPACE_TEXT, XML_XMLNS, XML_TYPE_ATTRIBUTE_CONTAINER | MID_FLAG_SPECIAL_ITEM, 0 ),
+ MAP_EXT( PROP_RelativeWidthRelation, XML_NAMESPACE_LO_EXT, XML_REL_WIDTH_REL, XML_TYPE_TEXT_HORIZONTAL_REL|XML_TYPE_PROP_GRAPHIC, CTF_RELWIDTHREL),
+ MAP_EXT( PROP_RelativeHeightRelation, XML_NAMESPACE_LO_EXT, XML_REL_HEIGHT_REL, XML_TYPE_TEXT_VERTICAL_REL|XML_TYPE_PROP_GRAPHIC, CTF_RELHEIGHTREL),
+ MG_E(PROP_TextVerticalAdjust, XML_NAMESPACE_DRAW, XML_TEXTAREA_VERTICAL_ALIGN, XML_TYPE_VERTICAL_ALIGN, 0),
+ MAP_EXT(PROP_Decorative, XML_NAMESPACE_LO_EXT, XML_DECORATIVE, XML_TYPE_BOOL|XML_TYPE_PROP_GRAPHIC, 0),
+
+ M_END()
+};
+
+XMLPropertyMapEntry constexpr aXMLShapePropMap[] =
+{
+ // RES_LR_SPACE
+ MG_E( PROP_LeftMargin, XML_NAMESPACE_FO, XML_MARGIN_LEFT, XML_TYPE_MEASURE, 0),
+ MG_E( PROP_RightMargin, XML_NAMESPACE_FO, XML_MARGIN_RIGHT, XML_TYPE_MEASURE, 0 ),
+ // RES_UL_SPACE
+ MG_E( PROP_TopMargin, XML_NAMESPACE_FO, XML_MARGIN_TOP, XML_TYPE_MEASURE, 0 ),
+ MG_E( PROP_BottomMargin, XML_NAMESPACE_FO, XML_MARGIN_BOTTOM, XML_TYPE_MEASURE, 0 ),
+ // RES_OPAQUE
+ MG_ED( PROP_Opaque, XML_NAMESPACE_STYLE, XML_RUN_THROUGH, XML_TYPE_TEXT_OPAQUE, 0 ),
+ // RES_SURROUND
+ MG_E( PROP_TextWrap, XML_NAMESPACE_STYLE, XML_WRAP, XML_TYPE_TEXT_WRAP, CTF_WRAP ),
+ MG_E( PROP_SurroundAnchorOnly, XML_NAMESPACE_STYLE, XML_NUMBER_WRAPPED_PARAGRAPHS, XML_TYPE_TEXT_PARAGRAPH_ONLY, CTF_WRAP_PARAGRAPH_ONLY ),
+ MG_E( PROP_SurroundContour, XML_NAMESPACE_STYLE, XML_WRAP_CONTOUR, XML_TYPE_BOOL, CTF_WRAP_CONTOUR ),
+ MG_E( PROP_ContourOutside, XML_NAMESPACE_STYLE, XML_WRAP_CONTOUR_MODE, XML_TYPE_TEXT_WRAP_OUTSIDE, CTF_WRAP_CONTOUR_MODE ),
+ // Use own CTF ids for positioning attributes (#i28749#)
+ // RES_VERT_ORIENT
+ MG_E( PROP_VertOrient, XML_NAMESPACE_STYLE, XML_VERTICAL_POS, XML_TYPE_TEXT_VERTICAL_POS, CTF_SHAPE_VERTICALPOS ),
+ // Add property for at-character anchored shapes (#i26791#)
+ MG_E( PROP_VertOrient, XML_NAMESPACE_STYLE, XML_VERTICAL_POS, XML_TYPE_TEXT_VERTICAL_POS_AT_CHAR, CTF_SHAPE_VERTICALPOS_ATCHAR ),
+ MG_E( PROP_VertOrient, XML_NAMESPACE_STYLE, XML_VERTICAL_REL, XML_TYPE_TEXT_VERTICAL_REL_AS_CHAR|MID_FLAG_MULTI_PROPERTY, CTF_VERTICALREL_ASCHAR ),
+ MG_E( PROP_VertOrientRelation, XML_NAMESPACE_STYLE, XML_VERTICAL_REL, XML_TYPE_TEXT_VERTICAL_REL, CTF_SHAPE_VERTICALREL ),
+ MG_E( PROP_VertOrientRelation, XML_NAMESPACE_STYLE, XML_VERTICAL_REL, XML_TYPE_TEXT_VERTICAL_REL_PAGE|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_SHAPE_VERTICALREL_PAGE ),
+ MG_E( PROP_VertOrientRelation, XML_NAMESPACE_STYLE, XML_VERTICAL_REL, XML_TYPE_TEXT_VERTICAL_REL_FRAME|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_SHAPE_VERTICALREL_FRAME ),
+ MAP_EXT_I( PROP_VertOrientRelation, XML_NAMESPACE_LO_EXT, XML_VERTICAL_REL, XML_TYPE_TEXT_VERTICAL_REL|XML_TYPE_PROP_GRAPHIC, CTF_VERTICALREL ),
+ MAP_EXT_I( PROP_VertOrientRelation, XML_NAMESPACE_LO_EXT, XML_VERTICAL_REL, XML_TYPE_TEXT_VERTICAL_REL_PAGE|MID_FLAG_SPECIAL_ITEM_IMPORT|XML_TYPE_PROP_GRAPHIC, CTF_VERTICALREL_PAGE ),
+ MAP_EXT_I( PROP_VertOrientRelation, XML_NAMESPACE_LO_EXT, XML_VERTICAL_REL, XML_TYPE_TEXT_VERTICAL_REL_FRAME|MID_FLAG_SPECIAL_ITEM_IMPORT|XML_TYPE_PROP_GRAPHIC, CTF_VERTICALREL_FRAME ),
+ // RES_HORI_ORIENT
+ MG_E( PROP_HoriOrient, XML_NAMESPACE_STYLE, XML_HORIZONTAL_POS, XML_TYPE_TEXT_HORIZONTAL_POS|MID_FLAG_MULTI_PROPERTY, CTF_SHAPE_HORIZONTALPOS ),
+ MG_E( PROP_PageToggle, XML_NAMESPACE_STYLE, XML_HORIZONTAL_POS, XML_TYPE_TEXT_HORIZONTAL_MIRROR, CTF_SHAPE_HORIZONTALMIRROR ),
+ MG_E( PROP_HoriOrient, XML_NAMESPACE_STYLE, XML_HORIZONTAL_POS, XML_TYPE_TEXT_HORIZONTAL_POS_MIRRORED|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_SHAPE_HORIZONTALPOS_MIRRORED ),
+ MG_E( PROP_HoriOrientRelation, XML_NAMESPACE_STYLE, XML_HORIZONTAL_REL, XML_TYPE_TEXT_HORIZONTAL_REL, CTF_SHAPE_HORIZONTALREL ),
+ MG_E( PROP_HoriOrientRelation, XML_NAMESPACE_STYLE, XML_HORIZONTAL_REL, XML_TYPE_TEXT_HORIZONTAL_REL_FRAME|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_SHAPE_HORIZONTALREL_FRAME ),
+ // RES_WRAP_INFLUENCE_ON_OBJPOS (#i28701#)
+ MG_ED( PROP_WrapInfluenceOnPosition, XML_NAMESPACE_DRAW, XML_WRAP_INFLUENCE_ON_POSITION, XML_TYPE_WRAP_INFLUENCE_ON_POSITION, 0 ),
+ MAP_EXT( PROP_AllowOverlap, XML_NAMESPACE_LO_EXT, XML_ALLOW_OVERLAP, XML_TYPE_BOOL|XML_TYPE_PROP_GRAPHIC, 0 ),
+ // UserDefinedAttributes is already contained in the map this one is
+ // chained to.
+
+ // RES_FOLLOW_TEXT_FLOW (#i26791#)
+ MG_ED( PROP_IsFollowingTextFlow, XML_NAMESPACE_STYLE, XML_FLOW_WITH_TEXT, XML_TYPE_BOOL, 0 ),
+
+ // RES_FRM_SIZE
+ MAP_EXT( PROP_RelativeWidthRelation, XML_NAMESPACE_LO_EXT, XML_REL_WIDTH_REL, XML_TYPE_TEXT_HORIZONTAL_REL|XML_TYPE_PROP_GRAPHIC, CTF_RELWIDTHREL ),
+ MAP_EXT( PROP_RelativeHeightRelation, XML_NAMESPACE_LO_EXT, XML_REL_HEIGHT_REL, XML_TYPE_TEXT_VERTICAL_REL|XML_TYPE_PROP_GRAPHIC, CTF_RELHEIGHTREL ),
+
+ M_END()
+};
+
+XMLPropertyMapEntry constexpr aXMLSectionPropMap[] =
+{
+ // RES_COL
+ MS_E( PROP_TextColumns, XML_NAMESPACE_STYLE, XML_COLUMNS, MID_FLAG_ELEMENT_ITEM|XML_TYPE_TEXT_COLUMNS, CTF_TEXTCOLUMNS ),
+
+ // RES_BACKGROUND
+ // DO NOT REORDER these!
+ MS_E( PROP_BackColor, XML_NAMESPACE_FO, XML_BACKGROUND_COLOR, XML_TYPE_COLORTRANSPARENT|MID_FLAG_MULTI_PROPERTY, 0 ),
+ MS_E( PROP_BackTransparent, XML_NAMESPACE_FO, XML_BACKGROUND_COLOR, XML_TYPE_ISTRANSPARENT|MID_FLAG_MERGE_ATTRIBUTE, 0 ),
+ MS_E( PROP_BackGraphicLocation, XML_NAMESPACE_STYLE, XML_POSITION, MID_FLAG_SPECIAL_ITEM|XML_TYPE_BUILDIN_CMP_ONLY, CTF_BACKGROUND_POS ),
+ MS_E( PROP_BackGraphicFilter, XML_NAMESPACE_STYLE, XML_FILTER_NAME, MID_FLAG_SPECIAL_ITEM|XML_TYPE_STRING, CTF_BACKGROUND_FILTER ),
+ MS_E( PROP_BackGraphic, XML_NAMESPACE_STYLE, XML_BACKGROUND_IMAGE, MID_FLAG_ELEMENT_ITEM|XML_TYPE_GRAPHIC, CTF_BACKGROUND_URL ),
+
+ // move protect-flag into section element
+// M_E( "IsProtected", STYLE, PROTECT, XML_TYPE_BOOL, 0 ),
+
+ MS_E( PROP_DontBalanceTextColumns, XML_NAMESPACE_TEXT, XML_DONT_BALANCE_TEXT_COLUMNS, XML_TYPE_BOOL, 0 ),
+
+ MS_E( PROP_WritingMode, XML_NAMESPACE_STYLE, XML_WRITING_MODE, XML_TYPE_TEXT_WRITING_MODE_WITH_DEFAULT, 0 ),
+
+ MS_E( PROP_SectionLeftMargin, XML_NAMESPACE_FO, XML_MARGIN_LEFT, XML_TYPE_MEASURE, 0 ),
+ MS_E( PROP_SectionRightMargin, XML_NAMESPACE_FO, XML_MARGIN_RIGHT, XML_TYPE_MEASURE, 0 ),
+
+ // section footnote settings
+ MS_E( PROP_FootnoteIsOwnNumbering, XML_NAMESPACE_TEXT, XML__EMPTY, MID_FLAG_SPECIAL_ITEM|XML_TYPE_BOOL, CTF_SECTION_FOOTNOTE_NUM_OWN ),
+ MS_E( PROP_FootnoteIsRestartNumbering, XML_NAMESPACE_TEXT, XML__EMPTY, MID_FLAG_SPECIAL_ITEM|XML_TYPE_BOOL, CTF_SECTION_FOOTNOTE_NUM_RESTART ),
+ MS_E( PROP_FootnoteRestartNumberingAt, XML_NAMESPACE_TEXT, XML__EMPTY, MID_FLAG_SPECIAL_ITEM|XML_TYPE_NUMBER16, CTF_SECTION_FOOTNOTE_NUM_RESTART_AT ),
+ MS_E( PROP_FootnoteNumberingType, XML_NAMESPACE_TEXT, XML__EMPTY, MID_FLAG_SPECIAL_ITEM|XML_TYPE_NUMBER16, CTF_SECTION_FOOTNOTE_NUM_TYPE ),
+ MS_E( PROP_FootnoteNumberingPrefix, XML_NAMESPACE_TEXT, XML__EMPTY, MID_FLAG_SPECIAL_ITEM|XML_TYPE_STRING, CTF_SECTION_FOOTNOTE_NUM_PREFIX ),
+ MS_E( PROP_FootnoteNumberingSuffix, XML_NAMESPACE_TEXT, XML__EMPTY, MID_FLAG_SPECIAL_ITEM|XML_TYPE_STRING, CTF_SECTION_FOOTNOTE_NUM_SUFFIX ),
+ MS_E( PROP_FootnoteIsCollectAtTextEnd, XML_NAMESPACE_TEXT, XML_NOTES_CONFIGURATION, MID_FLAG_ELEMENT_ITEM|XML_TYPE_BOOL, CTF_SECTION_FOOTNOTE_END ),
+
+ // section footnote settings
+ MS_E( PROP_EndnoteIsOwnNumbering, XML_NAMESPACE_TEXT, XML__EMPTY, MID_FLAG_SPECIAL_ITEM|XML_TYPE_BOOL, CTF_SECTION_ENDNOTE_NUM_OWN ),
+ MS_E( PROP_EndnoteIsRestartNumbering, XML_NAMESPACE_TEXT, XML__EMPTY, MID_FLAG_SPECIAL_ITEM|XML_TYPE_BOOL, CTF_SECTION_ENDNOTE_NUM_RESTART ),
+ MS_E( PROP_EndnoteRestartNumberingAt, XML_NAMESPACE_TEXT, XML__EMPTY, MID_FLAG_SPECIAL_ITEM|XML_TYPE_NUMBER16, CTF_SECTION_ENDNOTE_NUM_RESTART_AT ),
+ MS_E( PROP_EndnoteNumberingType, XML_NAMESPACE_TEXT, XML__EMPTY, MID_FLAG_SPECIAL_ITEM|XML_TYPE_NUMBER16, CTF_SECTION_ENDNOTE_NUM_TYPE ),
+ MS_E( PROP_EndnoteNumberingPrefix, XML_NAMESPACE_TEXT, XML__EMPTY, MID_FLAG_SPECIAL_ITEM|XML_TYPE_STRING, CTF_SECTION_ENDNOTE_NUM_PREFIX ),
+ MS_E( PROP_EndnoteNumberingSuffix, XML_NAMESPACE_TEXT, XML__EMPTY, MID_FLAG_SPECIAL_ITEM|XML_TYPE_STRING, CTF_SECTION_ENDNOTE_NUM_SUFFIX ),
+ MS_E( PROP_EndnoteIsCollectAtTextEnd, XML_NAMESPACE_TEXT, XML_NOTES_CONFIGURATION, MID_FLAG_ELEMENT_ITEM|XML_TYPE_BOOL, CTF_SECTION_ENDNOTE_END ),
+ MS_E( PROP_UserDefinedAttributes, XML_NAMESPACE_TEXT, XML_XMLNS, XML_TYPE_ATTRIBUTE_CONTAINER | MID_FLAG_SPECIAL_ITEM, 0 ),
+ // RES_EDIT_IN_READONLY
+ MS_E( PROP_EditInReadonly, XML_NAMESPACE_STYLE, XML_EDITABLE, XML_TYPE_BOOL, 0 ),
+ M_END()
+};
+
+XMLPropertyMapEntry constexpr aXMLRubyPropMap[] =
+{
+ MR_E( PROP_RubyAdjust, XML_NAMESPACE_STYLE, XML_RUBY_ALIGN, XML_TYPE_TEXT_RUBY_ADJUST, 0 ),
+ MR_E( PROP_RubyIsAbove, XML_NAMESPACE_STYLE, XML_RUBY_POSITION, XML_TYPE_TEXT_RUBY_IS_ABOVE, 0 ),
+ MR_EV( PROP_RubyPosition, XML_NAMESPACE_LO_EXT, XML_RUBY_POSITION, XML_TYPE_TEXT_RUBY_POSITION, 0, SvtSaveOptions::ODFSVER_FUTURE_EXTENDED),
+ M_END()
+};
+
+
+XMLPropertyMapEntry constexpr aXMLTableDefaultsMap[] =
+{
+ // RES_COLLAPSING_BORDERS: only occurs in tables, but we need to
+ // read/write the default for this item
+ M_ED_( PROP_CollapsingBorders, XML_NAMESPACE_TABLE, XML_BORDER_MODEL, XML_TYPE_PROP_TABLE | XML_TYPE_BORDER_MODEL | MID_FLAG_NO_PROPERTY_IMPORT, CTF_BORDER_MODEL ),
+
+ M_END()
+};
+
+XMLPropertyMapEntry constexpr aXMLTableRowDefaultsMap[] =
+{
+ // RES_ROW_SPLIT: only occurs in table rows, but we need to
+ // read/write the default for this item
+ M_ED_( PROP_IsSplitAllowed, XML_NAMESPACE_FO, XML_KEEP_TOGETHER, XML_TYPE_PROP_TABLE_ROW | XML_TYPE_TEXT_NKEEP | MID_FLAG_NO_PROPERTY_IMPORT, CTF_KEEP_TOGETHER ),
+
+ M_END()
+};
+
+XMLPropertyMapEntry constexpr aXMLCellPropMap[] =
+{
+ MC_E( PROP_BackColor, XML_NAMESPACE_FO, XML_BACKGROUND_COLOR, XML_TYPE_COLORTRANSPARENT|MID_FLAG_MULTI_PROPERTY, 0 ),
+ MC_E( PROP_LeftBorder, XML_NAMESPACE_FO, XML_BORDER_LEFT, XML_TYPE_BORDER, 0 ),
+ MC_E( PROP_RightBorder, XML_NAMESPACE_FO, XML_BORDER_RIGHT, XML_TYPE_BORDER, 0 ),
+ MC_E( PROP_TopBorder, XML_NAMESPACE_FO, XML_BORDER_TOP, XML_TYPE_BORDER, 0 ),
+ MC_E( PROP_BottomBorder, XML_NAMESPACE_FO, XML_BORDER_BOTTOM, XML_TYPE_BORDER, 0 ),
+ MC_E( PROP_BorderDistance, XML_NAMESPACE_FO, XML_PADDING, XML_TYPE_MEASURE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ MC_E( PROP_LeftBorderDistance, XML_NAMESPACE_FO, XML_PADDING_LEFT, XML_TYPE_MEASURE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ MC_E( PROP_RightBorderDistance, XML_NAMESPACE_FO, XML_PADDING_RIGHT, XML_TYPE_MEASURE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ MC_E( PROP_TopBorderDistance, XML_NAMESPACE_FO, XML_PADDING_TOP, XML_TYPE_MEASURE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ MC_E( PROP_BottomBorderDistance, XML_NAMESPACE_FO, XML_PADDING_BOTTOM, XML_TYPE_MEASURE|MID_FLAG_MULTI_PROPERTY, 0 ),
+ MC_E( PROP_VertOrient, XML_NAMESPACE_STYLE, XML_VERTICAL_ALIGN, XML_TYPE_TEXT_VERTICAL_POS, 0 ),
+ MC_E( PROP_WritingMode, XML_NAMESPACE_STYLE, XML_WRITING_MODE, XML_TYPE_TEXT_WRITING_MODE_WITH_DEFAULT, 0 ),
+ MC_E( PROP_NumberFormat, XML_NAMESPACE_STYLE, XML_DATA_STYLE_NAME, XML_TYPE_NUMBER|MID_FLAG_SPECIAL_ITEM_EXPORT, 0 ),
+ // paragraph properties
+ MP_E( PROP_ParaAdjust, XML_NAMESPACE_FO, XML_TEXT_ALIGN, XML_TYPE_TEXT_ADJUST, 0 ),
+ // text properties
+ MT_ED( PROP_CharColor, XML_NAMESPACE_FO, XML_COLOR, XML_TYPE_COLORAUTO|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_ED( PROP_CharColor, XML_NAMESPACE_STYLE, XML_USE_WINDOW_FONT_COLOR, XML_TYPE_ISAUTOCOLOR|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MAP_EXT( PROP_CharComplexColor, XML_NAMESPACE_LO_EXT, XML_CHAR_COMPLEX_COLOR, XML_TYPE_COMPLEX_COLOR|XML_TYPE_PROP_TEXT|MID_FLAG_ELEMENT_ITEM, CTF_COMPLEX_COLOR),
+ MT_E( PROP_CharShadowed, XML_NAMESPACE_FO, XML_TEXT_SHADOW, XML_TYPE_TEXT_SHADOWED, 0 ),
+ MT_E( PROP_CharContoured, XML_NAMESPACE_STYLE, XML_TEXT_OUTLINE, XML_TYPE_BOOL, 0 ),
+ MT_E( PROP_CharStrikeout, XML_NAMESPACE_STYLE, XML_TEXT_LINE_THROUGH_STYLE, XML_TYPE_TEXT_CROSSEDOUT_STYLE|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_E( PROP_CharStrikeout, XML_NAMESPACE_STYLE, XML_TEXT_LINE_THROUGH_TYPE, XML_TYPE_TEXT_CROSSEDOUT_TYPE|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_E( PROP_CharStrikeout, XML_NAMESPACE_STYLE, XML_TEXT_LINE_THROUGH_WIDTH, XML_TYPE_TEXT_CROSSEDOUT_WIDTH|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_E( PROP_CharStrikeout, XML_NAMESPACE_STYLE, XML_TEXT_LINE_THROUGH_TEXT, XML_TYPE_TEXT_CROSSEDOUT_TEXT|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_E( PROP_CharUnderline, XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_STYLE, XML_TYPE_TEXT_UNDERLINE_STYLE|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_E( PROP_CharUnderline, XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_TYPE, XML_TYPE_TEXT_UNDERLINE_TYPE|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_E( PROP_CharUnderline, XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_WIDTH, XML_TYPE_TEXT_UNDERLINE_WIDTH|MID_FLAG_MERGE_PROPERTY, 0 ),
+ MT_E( PROP_CharUnderlineColor, XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_COLOR, XML_TYPE_TEXT_UNDERLINE_COLOR|MID_FLAG_MULTI_PROPERTY, 0 ),
+ MT_E( PROP_CharUnderlineHasColor, XML_NAMESPACE_STYLE, XML_TEXT_UNDERLINE_COLOR, XML_TYPE_TEXT_UNDERLINE_HASCOLOR|MID_FLAG_MERGE_ATTRIBUTE, 0 ),
+ // STANDARD FONT
+ MT_ED( PROP_CharHeight, XML_NAMESPACE_FO, XML_FONT_SIZE, XML_TYPE_CHAR_HEIGHT|MID_FLAG_MULTI_PROPERTY, 0 ),
+ MT_E( PROP_CharWeight, XML_NAMESPACE_FO, XML_FONT_WEIGHT, XML_TYPE_TEXT_WEIGHT, 0 ),
+ MT_E( PROP_CharPosture, XML_NAMESPACE_FO, XML_FONT_STYLE, XML_TYPE_TEXT_POSTURE, 0 ),
+ // RES_CHRATR_FONT
+ MT_ED( PROP_CharFontName, XML_NAMESPACE_STYLE, XML_FONT_NAME, XML_TYPE_STRING|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_FONTNAME ),
+ MT_ED( PROP_CharFontName, XML_NAMESPACE_FO, XML_FONT_FAMILY, XML_TYPE_TEXT_FONTFAMILYNAME|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_FONTFAMILYNAME ),
+ MT_ED( PROP_CharFontStyleName, XML_NAMESPACE_STYLE, XML_FONT_STYLE_NAME, XML_TYPE_STRING, CTF_FONTSTYLENAME ),
+ MT_ED( PROP_CharFontFamily, XML_NAMESPACE_STYLE, XML_FONT_FAMILY_GENERIC, XML_TYPE_TEXT_FONTFAMILY, CTF_FONTFAMILY ),
+ MT_ED( PROP_CharFontPitch, XML_NAMESPACE_STYLE, XML_FONT_PITCH, XML_TYPE_TEXT_FONTPITCH, CTF_FONTPITCH ),
+ MT_ED( PROP_CharFontCharSet, XML_NAMESPACE_STYLE, XML_FONT_CHARSET, XML_TYPE_TEXT_FONTENCODING, CTF_FONTCHARSET ),
+ // CJK FONT
+ MT_ED( PROP_CharHeightAsian, XML_NAMESPACE_STYLE, XML_FONT_SIZE_ASIAN, XML_TYPE_CHAR_HEIGHT|MID_FLAG_MULTI_PROPERTY, 0 ),
+ MT_E( PROP_CharWeightAsian, XML_NAMESPACE_STYLE, XML_FONT_WEIGHT_ASIAN, XML_TYPE_TEXT_WEIGHT, 0 ),
+ MT_E( PROP_CharPostureAsian, XML_NAMESPACE_STYLE, XML_FONT_STYLE_ASIAN, XML_TYPE_TEXT_POSTURE, 0 ),
+ // RES_CHRATR_CJK_FONT
+ MT_ED( PROP_CharFontNameAsian, XML_NAMESPACE_STYLE, XML_FONT_NAME_ASIAN, XML_TYPE_STRING|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_FONTNAME_CJK ),
+ MT_ED( PROP_CharFontNameAsian, XML_NAMESPACE_STYLE, XML_FONT_FAMILY_ASIAN, XML_TYPE_TEXT_FONTFAMILYNAME|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_FONTFAMILYNAME_CJK ),
+ MT_ED( PROP_CharFontStyleNameAsian, XML_NAMESPACE_STYLE, XML_FONT_STYLE_NAME_ASIAN, XML_TYPE_STRING, CTF_FONTSTYLENAME_CJK ),
+ MT_ED( PROP_CharFontFamilyAsian, XML_NAMESPACE_STYLE, XML_FONT_FAMILY_GENERIC_ASIAN, XML_TYPE_TEXT_FONTFAMILY, CTF_FONTFAMILY_CJK ),
+ MT_ED( PROP_CharFontPitchAsian, XML_NAMESPACE_STYLE, XML_FONT_PITCH_ASIAN, XML_TYPE_TEXT_FONTPITCH, CTF_FONTPITCH_CJK ),
+ MT_ED( PROP_CharFontCharSetAsian, XML_NAMESPACE_STYLE, XML_FONT_CHARSET_ASIAN, XML_TYPE_TEXT_FONTENCODING, CTF_FONTCHARSET_CJK ),
+ // CTL FONT
+ MT_ED( PROP_CharHeightComplex, XML_NAMESPACE_STYLE, XML_FONT_SIZE_COMPLEX, XML_TYPE_CHAR_HEIGHT|MID_FLAG_MULTI_PROPERTY, 0),
+ MT_E( PROP_CharWeightComplex, XML_NAMESPACE_STYLE, XML_FONT_WEIGHT_COMPLEX, XML_TYPE_TEXT_WEIGHT, 0),
+ MT_E( PROP_CharPostureComplex, XML_NAMESPACE_STYLE, XML_FONT_STYLE_COMPLEX, XML_TYPE_TEXT_POSTURE, 0),
+ // RES_CHRATR_CTL_FONT
+ MT_ED( PROP_CharFontNameComplex, XML_NAMESPACE_STYLE, XML_FONT_NAME_COMPLEX, XML_TYPE_STRING|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_FONTNAME_CTL),
+ MT_ED( PROP_CharFontNameComplex, XML_NAMESPACE_STYLE, XML_FONT_FAMILY_COMPLEX, XML_TYPE_TEXT_FONTFAMILYNAME|MID_FLAG_SPECIAL_ITEM_IMPORT, CTF_FONTFAMILYNAME_CTL),
+ MT_ED( PROP_CharFontStyleNameComplex, XML_NAMESPACE_STYLE, XML_FONT_STYLE_NAME_COMPLEX, XML_TYPE_STRING, CTF_FONTSTYLENAME_CTL),
+ MT_ED( PROP_CharFontFamilyComplex, XML_NAMESPACE_STYLE, XML_FONT_FAMILY_GENERIC_COMPLEX, XML_TYPE_TEXT_FONTFAMILY, CTF_FONTFAMILY_CTL),
+ MT_ED( PROP_CharFontPitchComplex, XML_NAMESPACE_STYLE, XML_FONT_PITCH_COMPLEX, XML_TYPE_TEXT_FONTPITCH, CTF_FONTPITCH_CTL),
+ MT_ED( PROP_CharFontCharSetComplex, XML_NAMESPACE_STYLE, XML_FONT_CHARSET_COMPLEX, XML_TYPE_TEXT_FONTENCODING, CTF_FONTCHARSET_CTL),
+
+ M_END()
+};
+
+static XMLPropertyMapEntry const *lcl_txtprmap_getMap( TextPropMap nType )
+{
+ XMLPropertyMapEntry const *pMap = nullptr;
+ switch( nType )
+ {
+ case TextPropMap::TEXT:
+ pMap = aXMLTextPropMap;
+ break;
+ case TextPropMap::SHAPE_PARA:
+ // #i125045# use [21] instead of [1] for text props for Shapes, indices
+ // [1..20] contain the DrawingLayer FillStyle attributes corresponding to
+ // [XATTR_FILL_FIRST .. XATTR_FILL_LAST] and would be double since Shapes
+ // already contain these (usually in aXMLSDProperties)
+ pMap = &(aXMLParaPropMap[21]);
+ assert( pMap->meXMLName == XML_MARGIN && " shape para map changed" );
+ break;
+ case TextPropMap::PARA:
+ pMap = aXMLParaPropMap;
+ break;
+ case TextPropMap::FRAME:
+ pMap = aXMLFramePropMap;
+ break;
+ case TextPropMap::AUTO_FRAME:
+ pMap = &(aXMLFramePropMap[13]);
+ assert( pMap->meXMLName == XML_MARGIN && " frame map changed" );
+ break;
+ case TextPropMap::SHAPE:
+ pMap = aXMLShapePropMap;
+ break;
+ case TextPropMap::SECTION:
+ pMap = aXMLSectionPropMap;
+ break;
+ case TextPropMap::RUBY:
+ pMap = aXMLRubyPropMap;
+ break;
+ case TextPropMap::TEXT_ADDITIONAL_DEFAULTS:
+ pMap = aXMLAdditionalTextDefaultsMap;
+ break;
+ case TextPropMap::TABLE_DEFAULTS:
+ pMap = aXMLTableDefaultsMap;
+ break;
+ case TextPropMap::TABLE_ROW_DEFAULTS:
+ pMap = aXMLTableRowDefaultsMap;
+ break;
+ case TextPropMap::CELL:
+ pMap = aXMLCellPropMap;
+ break;
+ }
+ SAL_WARN_IF( !pMap, "xmloff", "illegal map type" );
+ return pMap;
+}
+
+const XMLPropertyMapEntry* XMLTextPropertySetMapper::getPropertyMapForType( TextPropMap _nType )
+{
+ return lcl_txtprmap_getMap( _nType );
+}
+
+XMLTextPropertySetMapper::XMLTextPropertySetMapper( TextPropMap nType, bool bForExport ) :
+ XMLPropertySetMapper( lcl_txtprmap_getMap( nType ),
+ new XMLTextPropertyHandlerFactory, bForExport )
+{
+}
+
+XMLTextPropertySetMapper::~XMLTextPropertySetMapper()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/txtsecte.cxx b/xmloff/source/text/txtsecte.cxx
new file mode 100644
index 0000000000..14589b961d
--- /dev/null
+++ b/xmloff/source/text/txtsecte.cxx
@@ -0,0 +1,203 @@
+/* -*- 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 <xmloff/txtparae.hxx>
+
+#include <vector>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/text/XTextSection.hpp>
+#include "XMLTextNumRuleInfo.hxx"
+#include "XMLSectionExport.hxx"
+#include "XMLRedlineExport.hxx"
+#include <MultiPropertySetHelper.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::uno;
+
+using ::com::sun::star::beans::XPropertySet;
+
+void XMLTextParagraphExport::exportListAndSectionChange(
+ Reference<XTextSection> & rPrevSection,
+ const Reference<XTextContent> & rNextSectionContent,
+ const XMLTextNumRuleInfo& rPrevRule,
+ const XMLTextNumRuleInfo& rNextRule,
+ bool bAutoStyles)
+{
+ Reference<XTextSection> xNextSection;
+
+ // first: get current XTextSection
+ Reference<XPropertySet> xPropSet(rNextSectionContent, UNO_QUERY);
+ if (xPropSet.is())
+ {
+ if (xPropSet->getPropertySetInfo()->hasPropertyByName(gsTextSection))
+ {
+ xPropSet->getPropertyValue(gsTextSection) >>= xNextSection;
+ }
+ // else: no current section
+ }
+
+ exportListAndSectionChange(rPrevSection, xNextSection,
+ rPrevRule, rNextRule, bAutoStyles);
+}
+
+void XMLTextParagraphExport::exportListAndSectionChange(
+ Reference<XTextSection> & rPrevSection,
+ MultiPropertySetHelper& rPropSetHelper,
+ sal_Int16 nTextSectionId,
+ const Reference<XTextContent> & rNextSectionContent,
+ const XMLTextNumRuleInfo& rPrevRule,
+ const XMLTextNumRuleInfo& rNextRule,
+ bool bAutoStyles)
+{
+ Reference<XTextSection> xNextSection;
+
+ // first: get current XTextSection
+ Reference<XPropertySet> xPropSet(rNextSectionContent, UNO_QUERY);
+ if (xPropSet.is())
+ {
+ if( !rPropSetHelper.checkedProperties() )
+ rPropSetHelper.hasProperties( xPropSet->getPropertySetInfo() );
+ if( rPropSetHelper.hasProperty( nTextSectionId ))
+ {
+ xNextSection.set(rPropSetHelper.getValue( nTextSectionId , xPropSet,
+ true ), uno::UNO_QUERY);
+ }
+ // else: no current section
+ }
+
+ exportListAndSectionChange(rPrevSection, xNextSection,
+ rPrevRule, rNextRule, bAutoStyles);
+}
+
+void XMLTextParagraphExport::exportListAndSectionChange(
+ Reference<XTextSection> & rPrevSection,
+ const Reference<XTextSection> & rNextSection,
+ const XMLTextNumRuleInfo& rPrevRule,
+ const XMLTextNumRuleInfo& rNextRule,
+ bool bAutoStyles)
+{
+ // old != new? -> maybe we have to start or end a new section
+ if (rPrevSection != rNextSection)
+ {
+ // a new section started, or an old one gets closed!
+
+ // close old list
+ XMLTextNumRuleInfo aEmptyNumRuleInfo;
+ if ( !bAutoStyles )
+ exportListChange(rPrevRule, aEmptyNumRuleInfo);
+
+ // Build stacks of old and new sections
+ // Sections on top of mute sections should not be on the stack
+ std::vector< Reference<XTextSection> > aOldStack;
+ Reference<XTextSection> aCurrent(rPrevSection);
+ while(aCurrent.is())
+ {
+ // if we have a mute section, ignore all its children
+ // (all previous ones)
+ if (m_pSectionExport->IsMuteSection(aCurrent))
+ aOldStack.clear();
+
+ aOldStack.push_back(aCurrent);
+ aCurrent.set(aCurrent->getParentSection());
+ }
+
+ std::vector< Reference<XTextSection> > aNewStack;
+ aCurrent.set(rNextSection);
+ bool bMute = false;
+ while(aCurrent.is())
+ {
+ // if we have a mute section, ignore all its children
+ // (all previous ones)
+ if (m_pSectionExport->IsMuteSection(aCurrent))
+ {
+ aNewStack.clear();
+ bMute = true;
+ }
+
+ aNewStack.push_back(aCurrent);
+ aCurrent.set(aCurrent->getParentSection());
+ }
+
+ // compare the two stacks
+ std::vector<Reference<XTextSection> > ::reverse_iterator aOld =
+ aOldStack.rbegin();
+ std::vector<Reference<XTextSection> > ::reverse_iterator aNew =
+ aNewStack.rbegin();
+ // compare bottom sections and skip equal section
+ while ( (aOld != aOldStack.rend()) &&
+ (aNew != aNewStack.rend()) &&
+ (*aOld) == (*aNew) )
+ {
+ ++aOld;
+ ++aNew;
+ }
+
+ // close all elements of aOld ...
+ // (order: newest to oldest)
+ if (aOld != aOldStack.rend())
+ {
+ std::vector<Reference<XTextSection> > ::iterator aOldForward(
+ aOldStack.begin());
+ while ((aOldForward != aOldStack.end()) &&
+ (*aOldForward != *aOld))
+ {
+ if ( !bAutoStyles && (nullptr != m_pRedlineExport) )
+ m_pRedlineExport->ExportStartOrEndRedline(*aOldForward,
+ false);
+ m_pSectionExport->ExportSectionEnd(*aOldForward, bAutoStyles);
+ ++aOldForward;
+ }
+ if (aOldForward != aOldStack.end())
+ {
+ if ( !bAutoStyles && (nullptr != m_pRedlineExport) )
+ m_pRedlineExport->ExportStartOrEndRedline(*aOldForward,
+ false);
+ m_pSectionExport->ExportSectionEnd(*aOldForward, bAutoStyles);
+ }
+ }
+
+ // ...then open all of aNew
+ // (order: oldest to newest)
+ while (aNew != aNewStack.rend())
+ {
+ if ( !bAutoStyles && (nullptr != m_pRedlineExport) )
+ m_pRedlineExport->ExportStartOrEndRedline(*aNew, true);
+ m_pSectionExport->ExportSectionStart(*aNew, bAutoStyles);
+ ++aNew;
+ }
+
+ // start new list
+ if ( !bAutoStyles && !bMute )
+ exportListChange(aEmptyNumRuleInfo, rNextRule);
+ }
+ else
+ {
+ // list change, if sections have not changed
+ if ( !bAutoStyles )
+ exportListChange(rPrevRule, rNextRule);
+ }
+
+ // save old section (old numRule gets saved in calling method)
+ rPrevSection.set(rNextSection);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/txtstyle.cxx b/xmloff/source/text/txtstyle.cxx
new file mode 100644
index 0000000000..552e688338
--- /dev/null
+++ b/xmloff/source/text/txtstyle.cxx
@@ -0,0 +1,164 @@
+/* -*- 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 <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/style/ParagraphStyleCategory.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/style/XStyle.hpp>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/families.hxx>
+#include <xmloff/txtparae.hxx>
+#include <xmloff/xmlnume.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/ProgressBarHelper.hxx>
+#include "XMLSectionExport.hxx"
+#include "XMLLineNumberingExport.hxx"
+#include "txtexppr.hxx"
+#include <xmloff/txtprmap.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::style;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::beans;
+using namespace ::xmloff::token;
+
+void XMLTextParagraphExport::exportStyleAttributes(
+ const css::uno::Reference< css::style::XStyle > & rStyle )
+{
+ Reference< XPropertySet > xPropSet( rStyle, UNO_QUERY );
+ Reference< XPropertySetInfo > xPropSetInfo(
+ xPropSet->getPropertySetInfo());
+ if( xPropSetInfo->hasPropertyByName( gsCategory ) )
+ {
+ sal_Int16 nCategory = 0;
+ xPropSet->getPropertyValue( gsCategory ) >>= nCategory;
+ enum XMLTokenEnum eValue = XML_TOKEN_INVALID;
+ if( -1 != nCategory )
+ {
+ switch( nCategory )
+ {
+ case ParagraphStyleCategory::TEXT:
+ eValue = XML_TEXT;
+ break;
+ case ParagraphStyleCategory::CHAPTER:
+ eValue = XML_CHAPTER;
+ break;
+ case ParagraphStyleCategory::LIST:
+ eValue = XML_LIST;
+ break;
+ case ParagraphStyleCategory::INDEX:
+ eValue = XML_INDEX;
+ break;
+ case ParagraphStyleCategory::EXTRA:
+ eValue = XML_EXTRA;
+ break;
+ case ParagraphStyleCategory::HTML:
+ eValue = XML_HTML;
+ break;
+ }
+ }
+ if( eValue != XML_TOKEN_INVALID )
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_CLASS, eValue);
+ }
+ if( xPropSetInfo->hasPropertyByName( gsPageDescName ) )
+ {
+ Reference< XPropertyState > xPropState( xPropSet, uno::UNO_QUERY );
+ if( PropertyState_DIRECT_VALUE ==
+ xPropState->getPropertyState( gsPageDescName ) )
+ {
+ OUString sName;
+ xPropSet->getPropertyValue( gsPageDescName ) >>= sName;
+ // fix for #i5551# if( sName.getLength() > 0 )
+ GetExport().AddAttribute( XML_NAMESPACE_STYLE,
+ XML_MASTER_PAGE_NAME,
+ GetExport().EncodeStyleName( sName ) );
+ }
+ }
+ if( m_bProgress )
+ {
+ ProgressBarHelper *pProgress = GetExport().GetProgressBarHelper();
+ pProgress->SetValue( pProgress->GetValue()+2 );
+ }
+}
+
+void XMLTextParagraphExport::exportNumStyles( bool bUsed )
+{
+ SvxXMLNumRuleExport aNumRuleExport( GetExport() );
+ aNumRuleExport.exportStyles(bUsed, !IsBlockMode());
+}
+
+void XMLTextParagraphExport::exportTextStyles( bool bUsed, bool bProg )
+{
+ bool bOldProg = m_bProgress;
+ m_bProgress = bProg;
+
+ Reference < lang::XMultiServiceFactory > xFactory (GetExport().GetModel(), UNO_QUERY);
+ if (xFactory.is())
+ {
+ Reference < XPropertySet > xPropSet (xFactory->createInstance ( "com.sun.star.text.Defaults" ), UNO_QUERY);
+ if (xPropSet.is())
+ {
+ exportDefaultStyle( xPropSet, GetXMLToken(XML_PARAGRAPH), GetParaPropMapper());
+
+ exportDefaultStyle(
+ xPropSet,
+ GetXMLToken(XML_TABLE),
+ new XMLTextExportPropertySetMapper(
+ new XMLTextPropertySetMapper(
+ TextPropMap::TABLE_DEFAULTS, true ),
+ GetExport() ) );
+
+ exportDefaultStyle(
+ xPropSet,
+ GetXMLToken(XML_TABLE_ROW),
+ new XMLTextExportPropertySetMapper(
+ new XMLTextPropertySetMapper(
+ TextPropMap::TABLE_ROW_DEFAULTS, true ),
+ GetExport() ) );
+ }
+ }
+ exportStyleFamily( "ParagraphStyles", GetXMLToken(XML_PARAGRAPH), GetParaPropMapper(),
+ bUsed, XmlStyleFamily::TEXT_PARAGRAPH);
+ exportStyleFamily( "CharacterStyles", GetXMLToken(XML_TEXT), GetTextPropMapper(),
+ bUsed, XmlStyleFamily::TEXT_TEXT );
+ // get shape export to make sure the frame family is added correctly.
+ GetExport().GetShapeExport();
+ exportStyleFamily( "FrameStyles", XML_STYLE_FAMILY_SD_GRAPHICS_NAME, m_xFramePropMapper,
+ bUsed, XmlStyleFamily::TEXT_FRAME);
+ exportNumStyles( bUsed );
+ if( !IsBlockMode() )
+ {
+ exportTextFootnoteConfiguration();
+ XMLSectionExport::ExportBibliographyConfiguration(GetExport());
+ XMLLineNumberingExport aLineNumberingExport(GetExport());
+ aLineNumberingExport.Export();
+ }
+
+ m_bProgress = bOldProg;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/txtstyli.cxx b/xmloff/source/text/txtstyli.cxx
new file mode 100644
index 0000000000..bf4893479d
--- /dev/null
+++ b/xmloff/source/text/txtstyli.cxx
@@ -0,0 +1,633 @@
+/* -*- 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 "XMLTextPropertySetContext.hxx"
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/XMLEventsImportContext.hxx>
+#include <xmloff/families.hxx>
+#include <xmloff/txtprmap.hxx>
+#include <xmloff/txtstyli.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/maptype.hxx>
+#include <xmloff/xmlimppr.hxx>
+#include <xmloff/xmlement.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/document/XEventsSupplier.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/style/ParagraphStyleCategory.hpp>
+#include <com/sun/star/style/XStyle.hpp>
+
+#include <o3tl/any.hxx>
+
+#include <sax/tools/converter.hxx>
+
+#include <tools/debug.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <sal/log.hxx>
+
+#include <vector>
+
+#include <xmlsdtypes.hxx>
+#include <xmloff/xmlerror.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::xml::sax;
+using namespace ::com::sun::star::style;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+using namespace ::xmloff::token;
+
+const SvXMLEnumMapEntry<sal_uInt16> aCategoryMap[] =
+{
+ { XML_TEXT, ParagraphStyleCategory::TEXT },
+ { XML_CHAPTER, ParagraphStyleCategory::CHAPTER },
+ { XML_LIST, ParagraphStyleCategory::LIST },
+ { XML_INDEX, ParagraphStyleCategory::INDEX },
+ { XML_EXTRA, ParagraphStyleCategory::EXTRA },
+ { XML_HTML, ParagraphStyleCategory::HTML },
+ { XML_TOKEN_INVALID, 0 }
+};
+
+void XMLTextStyleContext::SetAttribute( sal_Int32 nElement,
+ const OUString& rValue )
+{
+ switch (nElement)
+ {
+ case XML_ELEMENT(STYLE, XML_AUTO_UPDATE):
+ {
+ if( IsXMLToken( rValue, XML_TRUE ) )
+ m_isAutoUpdate = true;
+ break;
+ }
+ case XML_ELEMENT(STYLE, XML_LIST_STYLE_NAME):
+ {
+ m_sListStyleName = rValue;
+ // Inherited paragraph style lost information about unset numbering (#i69523#)
+ m_bListStyleSet = true;
+ break;
+ }
+ case XML_ELEMENT(STYLE, XML_MASTER_PAGE_NAME):
+ {
+ m_sMasterPageName = rValue;
+ m_bHasMasterPageName = true;
+ break;
+ }
+ case XML_ELEMENT(STYLE, XML_DATA_STYLE_NAME):
+ m_sDataStyleName = rValue;
+ break;
+ case XML_ELEMENT(STYLE, XML_CLASS):
+ m_sCategoryVal = rValue;
+ break;
+ case XML_ELEMENT(STYLE, XML_DEFAULT_OUTLINE_LEVEL):
+ {
+ sal_Int32 nTmp;
+ if (::sax::Converter::convertNumber( nTmp, rValue ) &&
+ 0 <= nTmp && nTmp <= 10 )
+ {
+ m_nOutlineLevel = static_cast<sal_Int8>(nTmp);
+ }
+ break;
+ }
+ case XML_ELEMENT(STYLE, XML_LIST_LEVEL):
+ {
+ sal_Int32 nTmp;
+ // The spec is positiveInteger (1-based), but the implementation is 0-based.
+ if (sax::Converter::convertNumber(nTmp, rValue) && nTmp > 0 && nTmp <= 10)
+ {
+ m_aListLevel.emplace(--nTmp);
+ }
+ break;
+ }
+ default:
+ XMLPropStyleContext::SetAttribute( nElement, rValue );
+ }
+}
+
+XMLTextStyleContext::XMLTextStyleContext( SvXMLImport& rImport,
+ SvXMLStylesContext& rStyles, XmlStyleFamily nFamily,
+ bool bDefaultStyle )
+: XMLPropStyleContext( rImport, rStyles, nFamily, bDefaultStyle )
+, m_nOutlineLevel( -1 )
+, m_isAutoUpdate( false )
+, m_bHasMasterPageName( false )
+, m_bHasCombinedCharactersLetter( false )
+// Inherited paragraph style lost information about unset numbering (#i69523#)
+, m_bListStyleSet( false )
+{
+}
+
+XMLTextStyleContext::~XMLTextStyleContext()
+{}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTextStyleContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ if( IsTokenInNamespace(nElement, XML_NAMESPACE_STYLE) )
+ {
+ sal_Int32 nLocalName = nElement & TOKEN_MASK;
+ sal_uInt32 nFamily = 0;
+ if( nLocalName == XML_TEXT_PROPERTIES )
+ nFamily = XML_TYPE_PROP_TEXT;
+ else if( nLocalName == XML_PARAGRAPH_PROPERTIES )
+ nFamily = XML_TYPE_PROP_PARAGRAPH;
+ else if( nLocalName == XML_SECTION_PROPERTIES )
+ nFamily = XML_TYPE_PROP_SECTION;
+ else if( IsDefaultStyle() && nLocalName == XML_TABLE_PROPERTIES )
+ nFamily = XML_TYPE_PROP_TABLE;
+ else if( IsDefaultStyle() && nLocalName == XML_TABLE_ROW_PROPERTIES )
+ nFamily = XML_TYPE_PROP_TABLE_ROW;
+ if( nFamily )
+ {
+ rtl::Reference < SvXMLImportPropertyMapper > xImpPrMap =
+ GetStyles()->GetImportPropertyMapper( GetFamily() );
+ if( xImpPrMap.is() )
+ return new XMLTextPropertySetContext( GetImport(), nElement, xAttrList,
+ nFamily,
+ GetProperties(),
+ xImpPrMap,
+ m_sDropCapTextStyleName);
+ }
+ }
+ else if ( nElement == XML_ELEMENT(OFFICE, XML_EVENT_LISTENERS) )
+ {
+ // create and remember events import context
+ // (for delayed processing of events)
+ m_xEventContext.set(new XMLEventsImportContext( GetImport() ));
+ return m_xEventContext;
+ }
+
+ return XMLPropStyleContext::createFastChildContext( nElement, xAttrList );
+}
+
+void XMLTextStyleContext::CreateAndInsert( bool bOverwrite )
+{
+ XMLPropStyleContext::CreateAndInsert( bOverwrite );
+ Reference < XStyle > xStyle = GetStyle();
+ if( !xStyle.is() || !(bOverwrite || IsNew()) )
+ return;
+
+ Reference < XPropertySet > xPropSet( xStyle, UNO_QUERY );
+ Reference< XPropertySetInfo > xPropSetInfo =
+ xPropSet->getPropertySetInfo();
+
+ static constexpr OUString sIsAutoUpdate(u"IsAutoUpdate"_ustr);
+ if( xPropSetInfo->hasPropertyByName( sIsAutoUpdate ) )
+ {
+ xPropSet->setPropertyValue( sIsAutoUpdate, Any(m_isAutoUpdate) );
+ }
+
+ sal_uInt16 nCategory = ParagraphStyleCategory::TEXT;
+ if( XmlStyleFamily::TEXT_PARAGRAPH == GetFamily() &&
+ !m_sCategoryVal.isEmpty() && xStyle->isUserDefined() &&
+ xPropSetInfo->hasPropertyByName("Category") &&
+ SvXMLUnitConverter::convertEnum( nCategory, m_sCategoryVal, aCategoryMap))
+ {
+ xPropSet->setPropertyValue("Category", Any(static_cast<sal_Int16>(nCategory)));
+ }
+
+ // tell the style about it's events (if applicable)
+ if (m_xEventContext.is())
+ {
+ // pass events into event supplier
+ Reference<document::XEventsSupplier> xEventsSupplier(xStyle,UNO_QUERY);
+ m_xEventContext->SetEvents(xEventsSupplier);
+ m_xEventContext.clear();
+ }
+
+ // XML import: reconstruction of assignment of paragraph style to outline levels (#i69629#)
+ if (m_nOutlineLevel > 0)
+ {
+ GetImport().GetTextImport()->AddOutlineStyleCandidate(m_nOutlineLevel,
+ GetDisplayName() );
+ }
+}
+
+void XMLTextStyleContext::SetDefaults( )
+{
+ if( ( GetFamily() == XmlStyleFamily::TEXT_PARAGRAPH ) ||
+ ( GetFamily() == XmlStyleFamily::TABLE_TABLE ) ||
+ ( GetFamily() == XmlStyleFamily::TABLE_ROW ) )
+ {
+ Reference < XMultiServiceFactory > xFactory ( GetImport().GetModel(), UNO_QUERY);
+ if (xFactory.is())
+ {
+ Reference < XInterface > xInt = xFactory->createInstance( "com.sun.star.text.Defaults" );
+ Reference < XPropertySet > xProperties ( xInt, UNO_QUERY );
+ if ( xProperties.is() )
+ FillPropertySet ( xProperties );
+ }
+ }
+}
+
+void XMLTextStyleContext::Finish( bool bOverwrite )
+{
+ XMLPropStyleContext::Finish( bOverwrite );
+
+ Reference < XStyle > xStyle = GetStyle();
+ // Consider set empty list style (#i69523#)
+ if ( !( m_bListStyleSet ||
+ m_nOutlineLevel >= 0 ||
+ !m_sDropCapTextStyleName.isEmpty() ||
+ m_bHasMasterPageName ) ||
+ !xStyle.is() ||
+ !( bOverwrite || IsNew() ) )
+ return;
+
+ Reference < XPropertySet > xPropSet( xStyle, UNO_QUERY );
+ Reference< XPropertySetInfo > xPropSetInfo =
+ xPropSet->getPropertySetInfo();
+
+ static constexpr OUString sOutlineLevel(u"OutlineLevel"_ustr);
+ if( xPropSetInfo->hasPropertyByName( sOutlineLevel ))
+ {
+ if (m_nOutlineLevel >= 0)
+ {
+ xPropSet->setPropertyValue( sOutlineLevel, Any(m_nOutlineLevel) );
+ }
+ }
+
+ // Consider set empty list style (#i69523#)
+ static constexpr OUString sNumberingStyleName(u"NumberingStyleName"_ustr);
+ if (m_bListStyleSet &&
+ xPropSetInfo->hasPropertyByName( sNumberingStyleName ) )
+ {
+ /* Only for text document from version prior OOo 2.1 resp. SO 8 PU5:
+ - Do not apply list style, if paragraph style has a default outline
+ level > 0 and thus, will be assigned to the corresponding list
+ level of the outline style. (#i70223#)
+ */
+ bool bApplyListStyle( true );
+ if (m_nOutlineLevel > 0)
+ {
+ if ( GetImport().IsTextDocInOOoFileFormat() )
+ {
+ bApplyListStyle = false;
+ }
+ else
+ {
+ sal_Int32 nUPD( 0 );
+ sal_Int32 nBuild( 0 );
+ // Check explicitly on certain versions (#i86058#)
+ if ( GetImport().getBuildIds( nUPD, nBuild ) &&
+ ( ( nUPD == 641 ) || ( nUPD == 645 ) || // prior OOo 2.0
+ ( nUPD == 680 && nBuild <= 9073 ) ) ) // OOo 2.0 - OOo 2.0.4
+ {
+ bApplyListStyle = false;
+ }
+ }
+ }
+
+ if ( bApplyListStyle )
+ {
+ if (m_sListStyleName.isEmpty())
+ {
+ xPropSet->setPropertyValue(sNumberingStyleName, Any(m_sListStyleName)); /* empty string */
+ }
+ else
+ {
+ // change list style name to display name
+ OUString sDisplayListStyleName(
+ GetImport().GetStyleDisplayName(XmlStyleFamily::TEXT_LIST,
+ m_sListStyleName));
+ // The families container must exist
+ const Reference < XNameContainer >& rNumStyles =
+ GetImport().GetTextImport()->GetNumberingStyles();
+ // if( rNumStyles.is() && rNumStyles->hasByName( sDisplayListStyleName ) &&
+ // xPropSetInfo->hasPropertyByName( sNumberingStyleName ) )
+ if ( rNumStyles.is() &&
+ rNumStyles->hasByName( sDisplayListStyleName ) )
+ {
+ xPropSet->setPropertyValue( sNumberingStyleName, Any(sDisplayListStyleName) );
+ }
+ }
+
+ if (m_aListLevel.has_value())
+ {
+ xPropSet->setPropertyValue("NumberingLevel", uno::Any(*m_aListLevel));
+ }
+ }
+ }
+
+ if (!m_sDropCapTextStyleName.isEmpty())
+ {
+ // change list style name to display name
+ OUString sDisplayDropCapTextStyleName(
+ GetImport().GetStyleDisplayName( XmlStyleFamily::TEXT_TEXT,
+ m_sDropCapTextStyleName));
+ // The families container must exist
+ const Reference < XNameContainer >& rTextStyles =
+ GetImport().GetTextImport()->GetTextStyles();
+ if( rTextStyles.is() &&
+ rTextStyles->hasByName( sDisplayDropCapTextStyleName ) &&
+ xPropSetInfo->hasPropertyByName("DropCapCharStyleName"))
+ {
+ xPropSet->setPropertyValue("DropCapCharStyleName", Any(sDisplayDropCapTextStyleName));
+ }
+ }
+
+ if (!m_bHasMasterPageName)
+ return;
+
+ OUString sDisplayName(
+ GetImport().GetStyleDisplayName(
+ XmlStyleFamily::MASTER_PAGE, m_sMasterPageName));
+ // The families container must exist
+ const Reference < XNameContainer >& rPageStyles =
+ GetImport().GetTextImport()->GetPageStyles();
+
+ static constexpr OUString sPageDescName(u"PageDescName"_ustr);
+ if( ( sDisplayName.isEmpty() ||
+ (rPageStyles.is() &&
+ rPageStyles->hasByName( sDisplayName )) ) &&
+ xPropSetInfo->hasPropertyByName( sPageDescName ) )
+ {
+ xPropSet->setPropertyValue( sPageDescName, Any(sDisplayName) );
+ }
+}
+
+void XMLTextStyleContext::FillPropertySet(
+ const Reference<XPropertySet > & rPropSet )
+{
+ // imitate the FillPropertySet of the super class, so we get a chance to
+ // catch the combined characters attribute
+
+ // imitate XMLPropStyleContext::FillPropertySet(...)
+ SvXMLStylesContext* pSvXMLStylesContext = GetStyles();
+ rtl::Reference < SvXMLImportPropertyMapper > xImpPrMap = pSvXMLStylesContext->GetImportPropertyMapper(GetFamily());
+ DBG_ASSERT(xImpPrMap.is(),"Where is the import prop mapper?");
+
+ if(!xImpPrMap.is())
+ return;
+
+ // imitate SvXMLImportPropertyMapper::FillPropertySet(...)
+ // The reason for this is that we have no other way to
+ // efficiently intercept the value of combined characters. To
+ // get that value, we could iterate through the map once more,
+ // but instead we chose to insert the code into this
+ // iteration. I haven't been able to come up with a much more
+ // intelligent solution.
+ struct ContextID_Index_Pair aContextIDs[] =
+ {
+ { CTF_COMBINED_CHARACTERS_FIELD, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE },
+ { CTF_KEEP_TOGETHER, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE },
+ { CTF_BORDER_MODEL, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE },
+ { CTF_TEXT_DISPLAY, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE },
+ { CTF_FONTFAMILYNAME, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE },
+ { CTF_FONTFAMILYNAME_CJK, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE },
+ { CTF_FONTFAMILYNAME_CTL, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE },
+
+ //UUU need special handling for DrawingLayer FillStyle names
+ { CTF_FILLGRADIENTNAME, -1, drawing::FillStyle::FillStyle_GRADIENT },
+ { CTF_FILLTRANSNAME, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE },
+ { CTF_FILLHATCHNAME, -1, drawing::FillStyle::FillStyle_HATCH },
+ { CTF_FILLBITMAPNAME, -1, drawing::FillStyle::FillStyle_BITMAP },
+
+ { -1, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE }
+ };
+
+ // the style families associated with the same index modulo 4
+ static const XmlStyleFamily aFamilies[] =
+ {
+ XmlStyleFamily::SD_GRADIENT_ID,
+ XmlStyleFamily::SD_GRADIENT_ID,
+ XmlStyleFamily::SD_HATCH_ID,
+ XmlStyleFamily::SD_FILL_IMAGE_ID
+ };
+
+ // get property set info
+ Reference< XPropertySetInfo > xInfo;
+ rtl::Reference< XMLPropertySetMapper > rPropMapper;
+ bool bAutomatic = false;
+
+ if(pSvXMLStylesContext->IsAutomaticStyle() &&
+ (XmlStyleFamily::TEXT_TEXT == GetFamily() || XmlStyleFamily::TEXT_PARAGRAPH == GetFamily()))
+ {
+ bAutomatic = true;
+
+ if( GetAutoName().hasValue() )
+ {
+ OUString sAutoProp = ( GetFamily() == XmlStyleFamily::TEXT_TEXT ) ?
+ OUString( "CharAutoStyleName" ):
+ OUString( "ParaAutoStyleName" );
+
+ try
+ {
+ if(!xInfo.is())
+ {
+ xInfo = rPropSet->getPropertySetInfo();
+ }
+
+ if ( xInfo->hasPropertyByName( sAutoProp ) )
+ {
+ rPropSet->setPropertyValue( sAutoProp, GetAutoName() );
+ }
+ else
+ {
+ bAutomatic = false;
+ }
+ }
+ catch( const RuntimeException& ) { throw; }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("xmloff.text");
+ bAutomatic = false;
+ }
+ }
+ }
+
+ if( bAutomatic )
+ {
+ xImpPrMap->CheckSpecialContext( GetProperties(), rPropSet, aContextIDs );
+ }
+ else
+ {
+ xImpPrMap->FillPropertySet( GetProperties(), rPropSet, aContextIDs );
+ }
+
+ sal_Int32 nIndex = aContextIDs[0].nIndex;
+
+ // have we found a combined characters
+ if ( nIndex != -1 )
+ {
+ Any& rAny = GetProperties()[nIndex].maValue;
+ bool bVal = *o3tl::doAccess<bool>(rAny);
+ m_bHasCombinedCharactersLetter = bVal;
+ }
+
+ // keep-together: the application default is different from
+ // the file format default. Hence, if we always set this
+ // value; if we didn't find one, we'll set to false, the file
+ // format default.
+ // border-model: same
+ if(IsDefaultStyle() && XmlStyleFamily::TABLE_ROW == GetFamily())
+ {
+ OUString sIsSplitAllowed("IsSplitAllowed");
+ SAL_WARN_IF( !rPropSet->getPropertySetInfo()->hasPropertyByName( sIsSplitAllowed ), "xmloff", "property missing?" );
+ rPropSet->setPropertyValue(
+ sIsSplitAllowed,
+ (aContextIDs[1].nIndex == -1) ? Any( false ) : GetProperties()[aContextIDs[1].nIndex].maValue );
+ }
+
+ if(IsDefaultStyle() && XmlStyleFamily::TABLE_TABLE == GetFamily())
+ {
+ OUString sCollapsingBorders("CollapsingBorders");
+ SAL_WARN_IF( !rPropSet->getPropertySetInfo()->hasPropertyByName( sCollapsingBorders ), "xmloff", "property missing?" );
+ rPropSet->setPropertyValue(
+ sCollapsingBorders,
+ (aContextIDs[2].nIndex == -1)
+ ? Any( false )
+ : GetProperties()[aContextIDs[2].nIndex].maValue );
+ }
+
+
+ // iterate over aContextIDs entries, start with 3, prev ones are already used above
+ for(sal_uInt16 i(3); aContextIDs[i].nContextID != -1; i++)
+ {
+ nIndex = aContextIDs[i].nIndex;
+
+ if ( nIndex != -1 )
+ {
+ // Found!
+ struct XMLPropertyState& rState = GetProperties()[nIndex];
+
+ switch(aContextIDs[i].nContextID)
+ {
+ case CTF_FILLGRADIENTNAME:
+ case CTF_FILLTRANSNAME:
+ case CTF_FILLHATCHNAME:
+ case CTF_FILLBITMAPNAME:
+ {
+ // DrawingLayer FillStyle name needs to be mapped to DisplayName
+ OUString sStyleName;
+ rState.maValue >>= sStyleName;
+
+ // translate the used name from ODF intern to the name used in the Model
+ sStyleName = GetImport().GetStyleDisplayName(aFamilies[i - 7], sStyleName);
+
+ if(bAutomatic)
+ {
+ // in this case the rPropSet got not really filled since above the call to
+ // CheckSpecialContext was used and not FillPropertySet, thus the below call to
+ // setPropertyValue can fail/will not be useful (e.g. when the rPropSet
+ // is a SwXTextCursor).
+ // This happens for AutoStyles which are already filled in XMLPropStyleContext::CreateAndInsert,
+ // thus the whole mechanism based on _ContextID_Index_Pair will not work
+ // in that case. Thus the slots which need to be converted already get
+ // converted there (it's called first) and not here (see
+ // translateNameBasedDrawingLayerFillStyleDefinitionsToStyleDisplayNames)
+ // For convenience, still Write back the corrected value to the XMLPropertyState entry
+ rState.maValue <<= sStyleName;
+ break;
+ }
+
+ if (::xmloff::IsIgnoreFillStyleNamedItem(rPropSet, aContextIDs[i].nExpectedFillStyle))
+ {
+ SAL_INFO("xmloff.style", "XMLTextStyleContext: dropping fill named item: " << sStyleName);
+ break; // ignore it, it's not used
+ }
+
+ // Still needed if it's not an AutomaticStyle (!)
+ try
+ {
+ if(!rPropMapper.is())
+ {
+ rPropMapper = xImpPrMap->getPropertySetMapper();
+ }
+
+ // set property
+ const OUString& rPropertyName = rPropMapper->GetEntryAPIName(rState.mnIndex);
+
+ if(!xInfo.is())
+ {
+ xInfo = rPropSet->getPropertySetInfo();
+ }
+
+ if(xInfo->hasPropertyByName(rPropertyName))
+ {
+ rPropSet->setPropertyValue(rPropertyName,Any(sStyleName));
+ }
+ }
+ catch(css::lang::IllegalArgumentException& e)
+ {
+ Sequence<OUString> aSeq { sStyleName };
+ GetImport().SetError(XMLERROR_STYLE_PROP_VALUE | XMLERROR_FLAG_WARNING, aSeq, e.Message, nullptr);
+ }
+ break;
+ }
+ default:
+ {
+ // check for StarBats and StarMath fonts
+ Any rAny = rState.maValue;
+ sal_Int32 nMapperIndex = rState.mnIndex;
+
+ // Now check for font name in rState and set corrected value,
+ // if necessary.
+ OUString sFontName;
+ rAny >>= sFontName;
+
+ if ( !sFontName.isEmpty() )
+ {
+ if ( sFontName.equalsIgnoreAsciiCase( "StarBats" ) ||
+ sFontName.equalsIgnoreAsciiCase( "StarMath" ) )
+ {
+ // construct new value
+ sFontName = "StarSymbol";
+ Any aAny(rAny);
+ aAny <<= sFontName;
+
+ if(!rPropMapper.is())
+ {
+ rPropMapper = xImpPrMap->getPropertySetMapper();
+ }
+
+ // set property
+ OUString rPropertyName(rPropMapper->GetEntryAPIName(nMapperIndex));
+
+ if(!xInfo.is())
+ {
+ xInfo = rPropSet->getPropertySetInfo();
+ }
+
+ if(xInfo->hasPropertyByName(rPropertyName))
+ {
+ rPropSet->setPropertyValue(rPropertyName,aAny);
+ }
+ }
+ // else: "normal" style name -> no correction is necessary
+ }
+ // else: no style name found -> illegal value -> ignore
+ }
+ }
+ }
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/txtvfldi.cxx b/xmloff/source/text/txtvfldi.cxx
new file mode 100644
index 0000000000..7855a2c5be
--- /dev/null
+++ b/xmloff/source/text/txtvfldi.cxx
@@ -0,0 +1,1247 @@
+/* -*- 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 .
+ */
+
+
+/** @#file
+ *
+ * export of all variable related text fields (and database display field)
+ */
+#include <txtvfldi.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/txtimp.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/i18nmap.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmluconv.hxx>
+#include <xmloff/xmlement.hxx>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/text/SetVariableType.hpp>
+#include <com/sun/star/text/XDependentTextField.hpp>
+#include <com/sun/star/text/XTextFieldsSupplier.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/xml/sax/XAttributeList.hpp>
+#include <com/sun/star/style/NumberingType.hpp>
+#include <com/sun/star/container/XIndexReplace.hpp>
+
+#include <sax/tools/converter.hxx>
+
+#include <rtl/ustring.hxx>
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+
+#include <tools/debug.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+
+// service names
+constexpr char16_t sAPI_fieldmaster_prefix[] = u"com.sun.star.text.FieldMaster.";
+constexpr OUString sAPI_get_expression = u"GetExpression"_ustr;
+constexpr OUString sAPI_set_expression = u"SetExpression"_ustr;
+constexpr OUString sAPI_user = u"User"_ustr;
+constexpr OUString sAPI_database = u"com.sun.star.text.TextField.Database"_ustr;
+
+// property names
+constexpr OUString sAPI_content = u"Content"_ustr;
+constexpr OUString sAPI_sub_type = u"SubType"_ustr;
+constexpr OUString sAPI_number_format = u"NumberFormat"_ustr;
+constexpr OUString sAPI_is_visible = u"IsVisible"_ustr;
+constexpr OUString sAPI_current_presentation = u"CurrentPresentation"_ustr;
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::style;
+using namespace ::xmloff::token;
+
+
+// XMLVarFieldImportContext: superclass for all variable related fields
+
+
+XMLVarFieldImportContext::XMLVarFieldImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp,
+ const OUString& pServiceName,
+ bool bFormula, bool bFormulaDefault,
+ bool bDescription, bool bHelp, bool bHint, bool bVisible,
+ bool bIsDisplayFormula,
+ bool bType, bool bStyle, bool bValue,
+ bool bPresentation) :
+ XMLTextFieldImportContext(rImport, rHlp, pServiceName),
+ aValueHelper(rImport, rHlp, bType, bStyle, bValue, false),
+ bDisplayFormula(false),
+ bDisplayNone(false),
+ bFormulaOK(false),
+ bDescriptionOK(false),
+ bHelpOK(false),
+ bHintOK(false),
+ bDisplayOK(false),
+ bSetFormula(bFormula),
+ bSetFormulaDefault(bFormulaDefault),
+ bSetDescription(bDescription),
+ bSetHelp(bHelp),
+ bSetHint(bHint),
+ bSetVisible(bVisible),
+ bSetDisplayFormula(bIsDisplayFormula),
+ bSetPresentation(bPresentation)
+{
+}
+
+void XMLVarFieldImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ switch (nAttrToken)
+ {
+ case XML_ELEMENT(TEXT, XML_NAME):
+ sName = OUString::fromUtf8(sAttrValue);
+ bValid = true; // we assume: field with name is valid!
+ break;
+ case XML_ELEMENT(TEXT, XML_DESCRIPTION):
+ sDescription = OUString::fromUtf8(sAttrValue);
+ bDescriptionOK = true;
+ break;
+ case XML_ELEMENT(TEXT, XML_HELP):
+ sHelp = OUString::fromUtf8(sAttrValue);
+ bHelpOK = true;
+ break;
+ case XML_ELEMENT(TEXT, XML_HINT):
+ sHint = OUString::fromUtf8(sAttrValue);
+ bHintOK = true;
+ break;
+ case XML_ELEMENT(TEXT, XML_FORMULA):
+ {
+ OUString sTmp;
+ sal_uInt16 nPrefix = GetImport().GetNamespaceMap().
+ GetKeyByAttrValueQName(OUString::fromUtf8(sAttrValue), &sTmp);
+ if( XML_NAMESPACE_OOOW == nPrefix )
+ {
+ sFormula = sTmp;
+ bFormulaOK = true;
+ }
+ else
+ sFormula = OUString::fromUtf8(sAttrValue);
+ }
+ break;
+ case XML_ELEMENT(TEXT, XML_DISPLAY):
+ if (IsXMLToken(sAttrValue, XML_FORMULA))
+ {
+ bDisplayFormula = true;
+ bDisplayNone = false;
+ bDisplayOK = true;
+ }
+ else if (IsXMLToken(sAttrValue, XML_VALUE))
+ {
+ bDisplayFormula = false;
+ bDisplayNone = false;
+ bDisplayOK = true;
+ }
+ else if (IsXMLToken(sAttrValue, XML_NONE))
+ {
+ bDisplayFormula = false;
+ bDisplayNone = true;
+ bDisplayOK = true;
+ } // else: no change
+ DBG_ASSERT(!(bDisplayFormula && bDisplayNone),
+ "illegal display values");
+ break;
+ default:
+ // delegate all others to value helper
+ aValueHelper.ProcessAttribute(nAttrToken, sAttrValue);
+ break;
+ }
+}
+
+void XMLVarFieldImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ // bSetName: not implemented
+
+ if (bSetFormula)
+ {
+ if (!bFormulaOK && bSetFormulaDefault)
+ {
+ sFormula = GetContent();
+ bFormulaOK = true;
+ }
+
+ if (bFormulaOK)
+ {
+ xPropertySet->setPropertyValue(sAPI_content, Any(sFormula));
+ }
+ }
+
+ if (bSetDescription && bDescriptionOK)
+ {
+ xPropertySet->setPropertyValue("Hint", Any(sDescription));
+ }
+
+ if (bSetHelp && bHelpOK)
+ {
+ xPropertySet->setPropertyValue("Help", Any(sHelp));
+ }
+
+ if (bSetHint && bHintOK)
+ {
+ xPropertySet->setPropertyValue("Tooltip", Any(sHint));
+ }
+
+ if (bSetVisible && bDisplayOK)
+ {
+ bool bTmp = !bDisplayNone;
+ xPropertySet->setPropertyValue(sAPI_is_visible, Any(bTmp));
+ }
+
+ // workaround for #no-bug#: display formula by default
+ if (xPropertySet->getPropertySetInfo()->
+ hasPropertyByName("IsShowFormula") &&
+ !bSetDisplayFormula)
+ {
+ bDisplayFormula = false;
+ bSetDisplayFormula = true;
+ }
+
+
+ if (bSetDisplayFormula)
+ {
+ bool bTmp = bDisplayFormula && bDisplayOK;
+ xPropertySet->setPropertyValue("IsShowFormula", Any(bTmp));
+ }
+
+ // delegate to value helper
+ aValueHelper.SetDefault(GetContent());
+ aValueHelper.PrepareField(xPropertySet);
+
+ // finally, set the current presentation
+ if (bSetPresentation)
+ {
+ Any aAny;
+ aAny <<= GetContent();
+ xPropertySet->setPropertyValue(sAPI_current_presentation, aAny);
+ }
+}
+
+
+// variable set fields
+
+
+XMLSetVarFieldImportContext::XMLSetVarFieldImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp,
+ const OUString& pServiceName, VarType eVarType,
+ bool bFormula, bool bFormulaDefault,
+ bool bDescription, bool bHelp, bool bHint, bool bVisible, bool bIsDisplayFormula,
+ bool bType, bool bStyle, bool bValue, bool bPresentation) :
+ XMLVarFieldImportContext(rImport, rHlp, pServiceName,
+ bFormula, bFormulaDefault,
+ bDescription, bHelp, bHint, bVisible, bIsDisplayFormula,
+ bType, bStyle, bValue, bPresentation),
+ eFieldType(eVarType)
+{
+}
+
+void XMLSetVarFieldImportContext::endFastElement(sal_Int32 )
+{
+ // should we call PrepareField on the field, or rather on it's master?
+ // currently: call on field (just like superclass)
+ // possible alternatives: call on master
+ // call field or master depending on variable
+ // PrepareMaster() in addition to PrepareField()
+
+ DBG_ASSERT(!GetServiceName().isEmpty(), "no service name for element!");
+
+ if (bValid)
+ {
+ DBG_ASSERT(!GetName().isEmpty(), "variable name needed!");
+
+ // find field master
+ Reference<XPropertySet> xMaster;
+ if (FindFieldMaster(xMaster))
+ {
+ // create field/Service
+ Reference<XPropertySet> xPropSet;
+ if (CreateField(xPropSet, "com.sun.star.text.TextField." + GetServiceName()))
+ {
+ Reference<XDependentTextField> xDepTextField(xPropSet, UNO_QUERY);
+ if (xDepTextField.is())
+ {
+ // attach field to field master
+ xDepTextField->attachTextFieldMaster(xMaster);
+
+ // attach field to document
+ Reference<XTextContent> xTextContent(xPropSet, UNO_QUERY);
+ if (xTextContent.is())
+ {
+ try {
+ // insert, set field properties and exit!
+ GetImportHelper().InsertTextContent(xTextContent);
+ PrepareField(xPropSet);
+ } catch (lang::IllegalArgumentException & /*e*/)
+ {
+ // ignore e: #i54023#
+ };
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ // above: exit on success; so for all error cases we end up here!
+ // write element content
+ GetImportHelper().InsertString(GetContent());
+}
+
+bool XMLSetVarFieldImportContext::FindFieldMaster(
+ Reference<XPropertySet> & xMaster)
+{
+ // currently: delegate to XMLVariableDeclImportContext;
+ // should eventually go here
+ return XMLVariableDeclImportContext::FindFieldMaster(xMaster,
+ GetImport(),
+ GetImportHelper(),
+ GetName(),
+ eFieldType);
+}
+
+
+// sequence field
+
+
+XMLSequenceFieldImportContext::XMLSequenceFieldImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
+ XMLSetVarFieldImportContext(rImport, rHlp, sAPI_set_expression,
+ VarTypeSequence,
+ // formula
+ true, true,
+ false, false, false, false,
+ false,
+ false, false, false, true),
+
+ sNumFormat(OUString('1')),
+ sNumFormatSync(GetXMLToken(XML_FALSE)),
+ bRefNameOK(false)
+{
+}
+
+void XMLSequenceFieldImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken, std::string_view sAttrValue )
+{
+ switch (nAttrToken)
+ {
+ case XML_ELEMENT(STYLE, XML_NUM_FORMAT):
+ sNumFormat = OUString::fromUtf8(sAttrValue);
+ break;
+ case XML_ELEMENT(STYLE, XML_NUM_LETTER_SYNC):
+ sNumFormatSync = OUString::fromUtf8(sAttrValue);
+ break;
+ case XML_ELEMENT(TEXT, XML_REF_NAME):
+ sRefName = OUString::fromUtf8(sAttrValue);
+ bRefNameOK = true;
+ break;
+ default:
+ // delegate to super class (name, formula)
+ XMLSetVarFieldImportContext::ProcessAttribute(nAttrToken,
+ sAttrValue);
+ break;
+ } // switch
+}
+
+void XMLSequenceFieldImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ // delegate to super class (formula)
+ XMLSetVarFieldImportContext::PrepareField(xPropertySet);
+
+ // set format
+ sal_Int16 nNumType = NumberingType::ARABIC;
+ GetImport().GetMM100UnitConverter().convertNumFormat( nNumType, sNumFormat, sNumFormatSync );
+ xPropertySet->setPropertyValue(sAPI_number_format, Any(nNumType));
+
+ // handle reference name
+ if (bRefNameOK)
+ {
+ Any aAny = xPropertySet->getPropertyValue("SequenceValue");
+ sal_Int16 nValue = 0;
+ aAny >>= nValue;
+ GetImportHelper().InsertSequenceID(sRefName, GetName(), nValue);
+ }
+}
+
+
+// variable set field
+
+
+XMLVariableSetFieldImportContext::XMLVariableSetFieldImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
+ XMLSetVarFieldImportContext(rImport, rHlp, sAPI_set_expression,
+ VarTypeSimple,
+ // formula, value&type, style,
+ // display none
+ true, true,
+ false, false, false,
+ true, false,
+ true, true, true,
+ true)
+{
+}
+
+void XMLVariableSetFieldImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ // set type
+ Any aAny;
+ aAny <<= (IsStringValue()? SetVariableType::STRING : SetVariableType::VAR);
+ xPropertySet->setPropertyValue(sAPI_sub_type, aAny);
+
+ // the remainder is handled by super class
+ XMLSetVarFieldImportContext::PrepareField(xPropertySet);
+}
+
+
+// variable input field
+
+
+XMLVariableInputFieldImportContext::XMLVariableInputFieldImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
+ XMLSetVarFieldImportContext(rImport, rHlp, sAPI_set_expression,
+ VarTypeSimple,
+ // description, display none/formula,
+ // value&type, style, formula
+ true, true,
+ true, true, true,
+ true, false,
+ true, true, true,
+ true)
+{
+}
+
+void XMLVariableInputFieldImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ // set type (input field)
+ Any aAny;
+ xPropertySet->setPropertyValue("Input", Any(true));
+
+ // set type
+ aAny <<= (IsStringValue()? SetVariableType::STRING : SetVariableType::VAR);
+ xPropertySet->setPropertyValue(sAPI_sub_type, aAny);
+
+ // the remainder is handled by super class
+ XMLSetVarFieldImportContext::PrepareField(xPropertySet);
+}
+
+
+// user field
+
+
+XMLUserFieldImportContext::XMLUserFieldImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
+ XMLSetVarFieldImportContext(rImport, rHlp, sAPI_user,
+ VarTypeUserField,
+ // display none/formula, style
+ false, false,
+ false, false, false, true,
+ true,
+ false, true, false,
+ false)
+{
+}
+
+
+// user input field
+
+
+// bug: doesn't work (SO API lacking)
+XMLUserFieldInputImportContext::XMLUserFieldInputImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
+ XMLVarFieldImportContext(rImport, rHlp, "InputUser",
+ // description, style
+ false, false,
+ true, false, false,
+ false, false,
+ false /*???*/, true, false,
+ false)
+{
+}
+
+void XMLUserFieldInputImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ xPropertySet->setPropertyValue(sAPI_content, Any(GetName()));
+
+ // delegate to super class
+ XMLVarFieldImportContext::PrepareField(xPropertySet);
+}
+
+
+// variable get field
+
+
+XMLVariableGetFieldImportContext::XMLVariableGetFieldImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
+ XMLVarFieldImportContext(rImport, rHlp, sAPI_get_expression,
+ // style, display formula
+ false, false,
+ false, false, false,
+ false, true,
+ true, true, false,
+ true)
+{
+}
+
+void XMLVariableGetFieldImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ // set name
+ xPropertySet->setPropertyValue(sAPI_content, Any(GetName()));
+
+ // the remainder is handled by super class
+ XMLVarFieldImportContext::PrepareField(xPropertySet);
+}
+
+
+// expression field
+
+
+XMLExpressionFieldImportContext::XMLExpressionFieldImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
+ XMLVarFieldImportContext(rImport, rHlp, sAPI_get_expression,
+ // formula, type, style, display formula
+ true, true,
+ false, false, false,
+ false, true,
+ true, true, false,
+ true)
+{
+ bValid = true; // always valid
+}
+
+
+void XMLExpressionFieldImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ xPropertySet->setPropertyValue(sAPI_sub_type, Any(sal_Int16(SetVariableType::FORMULA)));
+
+ // delegate to super class
+ XMLVarFieldImportContext::PrepareField(xPropertySet);
+}
+
+
+// text input field
+
+
+XMLTextInputFieldImportContext::XMLTextInputFieldImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
+ XMLVarFieldImportContext(rImport, rHlp, "Input",
+ // description
+ false, false,
+ true, true, true,
+ false, false,
+ false, false, false,
+ false)
+{
+ bValid = true; // always valid
+}
+
+void XMLTextInputFieldImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ XMLVarFieldImportContext::PrepareField(xPropertySet);
+
+ xPropertySet->setPropertyValue(sAPI_content, Any(GetContent()));
+}
+
+
+// table formula field
+
+
+XMLTableFormulaImportContext::XMLTableFormulaImportContext(
+ SvXMLImport& rImport,
+ XMLTextImportHelper& rHlp) :
+ XMLTextFieldImportContext(rImport, rHlp, "TableFormula"),
+ aValueHelper(rImport, rHlp, false, true, false, true),
+ bIsShowFormula(false)
+{
+}
+
+void XMLTableFormulaImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken,
+ std::string_view sAttrValue )
+{
+ switch (nAttrToken)
+ {
+ case XML_ELEMENT(TEXT, XML_FORMULA):
+ aValueHelper.ProcessAttribute( nAttrToken, sAttrValue );
+ bValid = true; // we need a formula!
+ break;
+
+ case XML_ELEMENT(STYLE, XML_DATA_STYLE_NAME):
+ aValueHelper.ProcessAttribute( nAttrToken, sAttrValue );
+ break;
+ case XML_ELEMENT(TEXT, XML_DISPLAY):
+ if ( sAttrValue == "formula" )
+ bIsShowFormula = true;
+ break;
+ default:
+ // unknown attribute -> ignore
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+ break;
+ }
+}
+
+void XMLTableFormulaImportContext::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ // set format and formula
+ aValueHelper.PrepareField( xPropertySet );
+
+ Any aAny;
+
+ // set 'show formula' and presentation
+ xPropertySet->setPropertyValue( "IsShowFormula", Any(bIsShowFormula) );
+
+ aAny <<= GetContent();
+ xPropertySet->setPropertyValue( "CurrentPresentation", aAny );
+}
+
+
+// variable declarations
+
+// Should be adapted to XMLVarField-/XMLSetVarFieldImportContext scheme!
+
+
+// declaration container import (<variable/user-field/sequence-decls>)
+
+
+XMLVariableDeclsImportContext::XMLVariableDeclsImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp, enum VarType eVarType) :
+ SvXMLImportContext(rImport),
+ eVarDeclsContextType(eVarType),
+ rImportHelper(rHlp)
+{
+}
+
+css::uno::Reference< css::xml::sax::XFastContextHandler > XMLVariableDeclsImportContext::createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
+{
+ if( IsTokenInNamespace(nElement, XML_NAMESPACE_TEXT) )
+ {
+ enum XMLTokenEnum eElementName;
+ switch (eVarDeclsContextType)
+ {
+ case VarTypeSequence:
+ eElementName = XML_SEQUENCE_DECL;
+ break;
+ case VarTypeSimple:
+ eElementName = XML_VARIABLE_DECL;
+ break;
+ case VarTypeUserField:
+ eElementName = XML_USER_FIELD_DECL;
+ break;
+ default:
+ OSL_FAIL("unknown field type!");
+ eElementName = XML_SEQUENCE_DECL;
+ break;
+ }
+
+ if( nElement == XML_ELEMENT(TEXT, eElementName) )
+ {
+ return new XMLVariableDeclImportContext(
+ GetImport(), rImportHelper, nElement, xAttrList,
+ eVarDeclsContextType);
+ }
+ }
+
+ // if no context was created, use default context
+ return nullptr;
+}
+
+
+// declaration import (<variable/user-field/sequence-decl> elements)
+
+
+XMLVariableDeclImportContext::XMLVariableDeclImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp,
+ sal_Int32 nElement,
+ const Reference<xml::sax::XFastAttributeList> & xAttrList,
+ enum VarType eVarType) :
+ SvXMLImportContext(rImport)
+{
+ // bug?? which properties for userfield/userfieldmaster
+ XMLValueImportHelper aValueHelper(rImport, rHlp, true, false, true, false);
+ sal_Unicode cSeparationChar('.');
+
+ sal_Int8 nNumLevel(-1);
+ OUString sName;
+
+ if (nElement != XML_ELEMENT(TEXT, XML_SEQUENCE_DECL) &&
+ nElement != XML_ELEMENT(TEXT, XML_VARIABLE_DECL) &&
+ nElement != XML_ELEMENT(TEXT, XML_USER_FIELD_DECL) )
+ return;
+
+ // TODO: check validity (need name!)
+
+ // parse attributes
+ for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
+ {
+ switch (aIter.getToken())
+ {
+ case XML_ELEMENT(TEXT, XML_NAME):
+ sName = aIter.toString();
+ break;
+ case XML_ELEMENT(TEXT, XML_DISPLAY_OUTLINE_LEVEL):
+ {
+ sal_Int32 nLevel;
+ bool const bRet = ::sax::Converter::convertNumber(
+ nLevel, aIter.toView(), 0,
+ GetImport().GetTextImport()->GetChapterNumbering()->
+ getCount());
+ if (bRet)
+ {
+ nNumLevel = static_cast< sal_Int8 >( nLevel-1 ); // API numbers -1..9
+ }
+ break;
+ }
+ case XML_ELEMENT(TEXT, XML_SEPARATION_CHARACTER):
+ cSeparationChar =
+ static_cast<char>(aIter.toString().toChar());
+ break;
+
+ default:
+ // delegate to value helper
+ aValueHelper.ProcessAttribute(aIter.getToken(), aIter.toView());
+ break;
+ }
+ }
+
+ Reference<XPropertySet> xFieldMaster;
+ if (!FindFieldMaster(xFieldMaster, GetImport(), rHlp,
+ sName, eVarType))
+ return;
+
+ // now we have a field master: process attributes!
+ Any aAny;
+
+ switch (eVarType)
+ {
+ case VarTypeSequence:
+ xFieldMaster->setPropertyValue("ChapterNumberingLevel", Any(nNumLevel));
+
+ if (nNumLevel >= 0)
+ {
+ OUString sStr(&cSeparationChar, 1);
+ xFieldMaster->setPropertyValue(
+ "NumberingSeparator", Any(sStr));
+ }
+ break;
+ case VarTypeSimple:
+ {
+ // set string or non-string SubType (#93192#)
+ // The SubType was already set in the FindFieldMaster
+ // method, but it needs to be adjusted if it's a string.
+ aAny <<= aValueHelper.IsStringValue()
+ ? SetVariableType::STRING : SetVariableType::VAR;
+ xFieldMaster->setPropertyValue(sAPI_sub_type, aAny);
+ }
+ break;
+ case VarTypeUserField:
+ {
+ bool bTmp = !aValueHelper.IsStringValue();
+ xFieldMaster->setPropertyValue("IsExpression", Any(bTmp));
+ aValueHelper.PrepareField(xFieldMaster);
+ break;
+ }
+ default:
+ OSL_FAIL("unknown varfield type");
+ } // switch
+}
+
+
+bool XMLVariableDeclImportContext::FindFieldMaster(
+ Reference<XPropertySet> & xMaster, SvXMLImport& rImport,
+ XMLTextImportHelper& rImportHelper,
+ const OUString& sVarName, enum VarType eVarType)
+{
+ static sal_Int32 nCollisionCount = 0;
+
+ // rename field
+ // currently: no family in use! Use 0.
+ OUString sName = rImportHelper.GetRenameMap().Get(
+ sal::static_int_cast< sal_uInt16 >(eVarType), sVarName);
+
+ // get text fields supplier and field masters
+ Reference<XTextFieldsSupplier> xTextFieldsSupp(rImport.GetModel(),
+ UNO_QUERY);
+ Reference<container::XNameAccess> xFieldMasterNameAccess =
+ xTextFieldsSupp->getTextFieldMasters();
+
+ OUString sVarServiceName =
+ OUString::Concat(sAPI_fieldmaster_prefix) +
+ sAPI_set_expression +
+ "." +
+ sName;
+
+ OUString sUserServiceName =
+ OUString::Concat(sAPI_fieldmaster_prefix) +
+ sAPI_user +
+ "." +
+ sName;
+
+ if (xFieldMasterNameAccess->hasByName(sVarServiceName)) {
+ // variable field master already in document
+
+ Any aAny = xFieldMasterNameAccess->getByName(sVarServiceName);
+ aAny >>= xMaster;
+
+ aAny = xMaster->getPropertyValue(sAPI_sub_type);
+ sal_Int16 nType = 0;
+ aAny >>= nType;
+
+ enum VarType eFMVarType =
+ (SetVariableType::SEQUENCE == nType) ?
+ VarTypeSequence : VarTypeSimple;
+
+ if (eFMVarType != eVarType)
+ {
+ ++nCollisionCount;
+ OUString sNew(sName + "_renamed_" + OUString::number(nCollisionCount));
+
+ // FIXME! can't find if name is taken already!!!!
+
+ rImportHelper.GetRenameMap().Add(
+ sal::static_int_cast< sal_uInt16 >(eVarType), sName, sNew);
+
+ // call FindFieldMaster recursively to create new master
+ return FindFieldMaster(xMaster, rImport, rImportHelper,
+ sNew, eVarType);
+ }
+ } else if (xFieldMasterNameAccess->hasByName(sUserServiceName)) {
+ // user field: get field master
+ Any aAny = xFieldMasterNameAccess->getByName(sUserServiceName);
+ aAny >>= xMaster;
+
+ if (VarTypeUserField != eVarType) {
+ ++nCollisionCount;
+ // find new name that is not taken
+ OUString sNew(sName + "_renamed_" + OUString::number(nCollisionCount));
+
+ // FIXME! can't find if name is taken already!!!!
+
+ rImportHelper.GetRenameMap().Add(
+ sal::static_int_cast< sal_uInt16 >(eVarType), sName, sNew);
+
+ // call FindFieldMaster recursively to create new master
+ return FindFieldMaster(xMaster, rImport, rImportHelper,
+ sNew, eVarType);
+ }
+ } else {
+ // field name not used: create field master
+
+ // import -> model is MultiServiceFactory -> createInstance
+ Reference<lang::XMultiServiceFactory>
+ xFactory(rImport.GetModel(),UNO_QUERY);
+ if( xFactory.is() ) {
+
+ OUString sService = sAPI_fieldmaster_prefix
+ + ((eVarType==VarTypeUserField) ?
+ sAPI_user : sAPI_set_expression);
+ Reference<XInterface> xIfc =
+ xFactory->createInstance( sService );
+ if (xIfc.is()) {
+ Reference<XPropertySet> xTmp( xIfc, UNO_QUERY );
+ xMaster = xTmp;
+
+ // set name
+ xMaster->setPropertyValue("Name", Any(sName));
+
+ if (eVarType != VarTypeUserField) {
+ // set subtype for setexp field
+ Any aAny;
+ aAny <<= ((eVarType == VarTypeSimple) ?
+ SetVariableType::VAR :
+ SetVariableType::SEQUENCE);
+ xMaster->setPropertyValue(sAPI_sub_type, aAny);
+ } // else : user field: no subtype
+
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ DBG_ASSERT(xMaster.is(), "no field master found!?!");
+ return true;
+}
+
+
+// Database Display field import
+
+
+XMLDatabaseDisplayImportContext::XMLDatabaseDisplayImportContext(
+ SvXMLImport& rImport, XMLTextImportHelper& rHlp) :
+ XMLDatabaseFieldImportContext(rImport, rHlp, sAPI_database, false),
+ aValueHelper(rImport, rHlp, false, true, false, false),
+ bColumnOK(false),
+ bDisplay( true ),
+ bDisplayOK( false )
+{
+}
+
+void XMLDatabaseDisplayImportContext::ProcessAttribute(
+ sal_Int32 nAttrToken, std::string_view sAttrValue )
+{
+ switch (nAttrToken)
+ {
+ case XML_ELEMENT(TEXT, XML_COLUMN_NAME):
+ sColumnName = OUString::fromUtf8(sAttrValue);
+ bColumnOK = true;
+ break;
+ case XML_ELEMENT(TEXT, XML_DISPLAY):
+ {
+ bool bNone = IsXMLToken( sAttrValue, XML_NONE );
+ bool bValue = IsXMLToken( sAttrValue, XML_VALUE );
+ bDisplay = bValue;
+ bDisplayOK = bNone || bValue;
+ }
+ break;
+ case XML_ELEMENT(TEXT, XML_DATABASE_NAME):
+ case XML_ELEMENT(TEXT, XML_TABLE_NAME):
+ case XML_ELEMENT(TEXT, XML_TABLE_TYPE):
+ // handled by super class
+ XMLDatabaseFieldImportContext::ProcessAttribute(nAttrToken,
+ sAttrValue);
+ break;
+ default:
+ // remainder handled by value helper
+ aValueHelper.ProcessAttribute(nAttrToken, sAttrValue);
+ break;
+ }
+
+ bValid = m_bTableOK && m_bDatabaseOK && bColumnOK;
+}
+
+void XMLDatabaseDisplayImportContext::endFastElement(sal_Int32 )
+{
+ // we have an EndElement of our own, because database fields need
+ // to be attached to a field master before they can be inserted into
+ // the document. Database stuff (database, table, column) all goes
+ // to the field master, value & style go to the field.
+
+ if (bValid)
+ {
+
+ // so here goes: we start with the master
+ Reference<XPropertySet> xMaster;
+
+ // create and prepare field master first
+ if (CreateField(xMaster,
+ "com.sun.star.text.FieldMaster.Database"))
+ {
+ Any aAny;
+ xMaster->setPropertyValue("DataColumnName", Any(sColumnName));
+
+ // fieldmaster takes database, table and column name
+ XMLDatabaseFieldImportContext::PrepareField(xMaster);
+
+ // create field
+ Reference<XPropertySet> xField;
+ if (CreateField(xField,
+ sAPI_database))
+ {
+ // attach field master
+ Reference<XDependentTextField> xDepField(xField, UNO_QUERY);
+ if (xDepField.is())
+ {
+ // attach field to field master
+ xDepField->attachTextFieldMaster(xMaster);
+
+ // attach field to document
+ Reference<XTextContent> xTextContent(xField, UNO_QUERY);
+ if (xTextContent.is())
+ {
+ // insert, set field properties and exit!
+ try
+ {
+ GetImportHelper().InsertTextContent(xTextContent);
+
+ // prepare field: format from database?
+ bool bTmp = !aValueHelper.IsFormatOK();
+ xField->setPropertyValue("DataBaseFormat", Any(bTmp));
+
+ // value, value-type and format done by value helper
+ aValueHelper.PrepareField(xField);
+
+ // visibility
+ if( bDisplayOK )
+ {
+ xField->setPropertyValue(sAPI_is_visible, Any(bDisplay));
+ }
+
+ // set presentation
+ aAny <<= GetContent();
+ xField->setPropertyValue(sAPI_current_presentation, aAny);
+
+ // success!
+ return;
+ }
+ catch (const lang::IllegalArgumentException&)
+ {
+ TOOLS_WARN_EXCEPTION("xmloff.text", "Failed to insert text content");
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // above: exit on success; so for all error cases we end up here!
+ // write element content
+ GetImportHelper().InsertString(GetContent());
+}
+
+
+// value import helper
+
+namespace {
+
+enum ValueType
+{
+ XML_VALUE_TYPE_STRING,
+ XML_VALUE_TYPE_FLOAT,
+ XML_VALUE_TYPE_CURRENCY,
+ XML_VALUE_TYPE_PERCENTAGE,
+ XML_VALUE_TYPE_DATE,
+ XML_VALUE_TYPE_TIME,
+ XML_VALUE_TYPE_BOOLEAN
+};
+
+}
+
+SvXMLEnumMapEntry<ValueType> const aValueTypeMap[] =
+{
+ { XML_FLOAT, XML_VALUE_TYPE_FLOAT },
+ { XML_CURRENCY, XML_VALUE_TYPE_CURRENCY },
+ { XML_PERCENTAGE, XML_VALUE_TYPE_PERCENTAGE },
+ { XML_DATE, XML_VALUE_TYPE_DATE },
+ { XML_TIME, XML_VALUE_TYPE_TIME },
+ { XML_BOOLEAN, XML_VALUE_TYPE_BOOLEAN },
+ { XML_STRING, XML_VALUE_TYPE_STRING },
+ { XML_TOKEN_INVALID, ValueType(0) }
+};
+
+XMLValueImportHelper::XMLValueImportHelper(
+ SvXMLImport& rImprt,
+ XMLTextImportHelper& rHlp,
+ bool bType, bool bStyle, bool bValue, bool bFormula) :
+
+ rImport(rImprt),
+ rHelper(rHlp),
+
+ fValue(0.0),
+ nFormatKey(0),
+ bIsDefaultLanguage(true),
+
+ bStringType(false),
+ bFormatOK(false),
+ bStringValueOK(false),
+ bFormulaOK(false),
+
+ bSetType(bType),
+ bSetValue(bValue),
+ bSetStyle(bStyle),
+ bSetFormula(bFormula)
+{
+}
+
+void XMLValueImportHelper::ProcessAttribute(
+ sal_Int32 nAttrToken, std::string_view sAttrValue )
+{
+ switch (nAttrToken)
+ {
+ case XML_ELEMENT(TEXT, XML_VALUE_TYPE): // #i32362#: src680m48++ saves text:value-type
+ case XML_ELEMENT(OFFICE, XML_VALUE_TYPE):
+ {
+ // convert enum
+ ValueType eValueType = XML_VALUE_TYPE_STRING;
+ bool bRet = SvXMLUnitConverter::convertEnum(
+ eValueType, sAttrValue, aValueTypeMap);
+
+ if (bRet) {
+ switch (eValueType)
+ {
+ case XML_VALUE_TYPE_STRING:
+ bStringType = true;
+ break;
+ case XML_VALUE_TYPE_FLOAT:
+ case XML_VALUE_TYPE_CURRENCY:
+ case XML_VALUE_TYPE_PERCENTAGE:
+ case XML_VALUE_TYPE_DATE:
+ case XML_VALUE_TYPE_TIME:
+ case XML_VALUE_TYPE_BOOLEAN:
+ bStringType = false;
+ break;
+
+ default:
+ OSL_FAIL("unknown value type");
+ }
+ }
+ break;
+ }
+
+ case XML_ELEMENT(TEXT, XML_VALUE):
+ case XML_ELEMENT(OFFICE, XML_VALUE):
+ {
+ double fTmp;
+ bool const bRet = ::sax::Converter::convertDouble(fTmp,sAttrValue);
+ if (bRet) {
+ fValue = fTmp;
+ }
+ break;
+ }
+
+ case XML_ELEMENT(TEXT, XML_TIME_VALUE):
+ case XML_ELEMENT(OFFICE, XML_TIME_VALUE):
+ {
+ double fTmp;
+ bool const bRet =
+ ::sax::Converter::convertDuration(fTmp, sAttrValue);
+ if (bRet) {
+ fValue = fTmp;
+ }
+ break;
+ }
+
+ case XML_ELEMENT(TEXT, XML_DATE_VALUE):
+ case XML_ELEMENT(OFFICE, XML_DATE_VALUE):
+ {
+ double fTmp;
+ bool bRet = rImport.GetMM100UnitConverter().
+ convertDateTime(fTmp,sAttrValue);
+ if (bRet) {
+ fValue = fTmp;
+ }
+ break;
+ }
+
+ case XML_ELEMENT(OFFICE, XML_BOOLEAN_VALUE):
+ {
+ bool bTmp(false);
+ bool bRet = ::sax::Converter::convertBool(bTmp, sAttrValue);
+ if (bRet) {
+ fValue = (bTmp ? 1.0 : 0.0);
+ }
+ else
+ {
+ double fTmp;
+ bRet = ::sax::Converter::convertDouble(fTmp, sAttrValue);
+ if (bRet) {
+ fValue = fTmp;
+ }
+ }
+ break;
+ }
+
+ case XML_ELEMENT(TEXT, XML_STRING_VALUE):
+ case XML_ELEMENT(OFFICE, XML_STRING_VALUE):
+ sValue = OUString::fromUtf8(sAttrValue);
+ bStringValueOK = true;
+ break;
+
+ case XML_ELEMENT(TEXT, XML_FORMULA):
+ {
+ OUString sTmp;
+ sal_uInt16 nPrefix = rImport.GetNamespaceMap().
+ GetKeyByAttrValueQName(OUString::fromUtf8(sAttrValue), &sTmp);
+ if( XML_NAMESPACE_OOOW == nPrefix )
+ {
+ sFormula = sTmp;
+ bFormulaOK = true;
+ }
+ else
+ sFormula = OUString::fromUtf8(sAttrValue);
+ }
+ break;
+
+ case XML_ELEMENT(STYLE, XML_DATA_STYLE_NAME):
+ {
+ sal_Int32 nKey = rHelper.GetDataStyleKey(
+ OUString::fromUtf8(sAttrValue), &bIsDefaultLanguage);
+ if (-1 != nKey)
+ {
+ nFormatKey = nKey;
+ bFormatOK = true;
+ }
+ break;
+ }
+ default:
+ XMLOFF_WARN_UNKNOWN_ATTR("xmloff", nAttrToken, sAttrValue);
+ } // switch
+}
+
+void XMLValueImportHelper::PrepareField(
+ const Reference<XPropertySet> & xPropertySet)
+{
+ Any aAny;
+
+ if (bSetType)
+ {
+ // ??? how to set type?
+ }
+
+ if (bSetFormula)
+ {
+ aAny <<= !bFormulaOK ? sDefault : sFormula;
+ xPropertySet->setPropertyValue(sAPI_content, aAny);
+ }
+
+ // format/style
+ if (bSetStyle && bFormatOK)
+ {
+ xPropertySet->setPropertyValue(sAPI_number_format, Any(nFormatKey));
+
+ if( xPropertySet->getPropertySetInfo()->
+ hasPropertyByName( "IsFixedLanguage" ) )
+ {
+ bool bIsFixedLanguage = ! bIsDefaultLanguage;
+ xPropertySet->setPropertyValue( "IsFixedLanguage", Any(bIsFixedLanguage) );
+ }
+ }
+
+ // value: string or float
+ if (bSetValue)
+ {
+ if (bStringType)
+ {
+ aAny <<= !bStringValueOK ? sDefault : sValue;
+ xPropertySet->setPropertyValue(sAPI_content, aAny);
+ }
+ else
+ {
+ xPropertySet->setPropertyValue("Value", Any(fValue));
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/xmlcontentcontrolcontext.cxx b/xmloff/source/text/xmlcontentcontrolcontext.cxx
new file mode 100644
index 0000000000..2a7ef5b2ee
--- /dev/null
+++ b/xmloff/source/text/xmlcontentcontrolcontext.cxx
@@ -0,0 +1,369 @@
+/* -*- 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 "xmlcontentcontrolcontext.hxx"
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include <sax/tools/converter.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/sequence.hxx>
+
+#include "XMLTextMarkImportContext.hxx"
+#include "txtparai.hxx"
+
+using namespace com::sun::star;
+using namespace xmloff::token;
+
+XMLContentControlContext::XMLContentControlContext(SvXMLImport& rImport, sal_Int32 /*nElement*/,
+ XMLHints_Impl& rHints, bool& rIgnoreLeadingSpace)
+ : SvXMLImportContext(rImport)
+ , m_rHints(rHints)
+ , m_rIgnoreLeadingSpace(rIgnoreLeadingSpace)
+ , m_xStart(GetImport().GetTextImport()->GetCursorAsRange()->getStart())
+{
+}
+
+void XMLContentControlContext::startFastElement(
+ sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
+{
+ for (auto& rIter : sax_fastparser::castToFastAttributeList(xAttrList))
+ {
+ bool bTmp = false;
+ sal_Int32 nTmp = 0;
+
+ switch (rIter.getToken())
+ {
+ case XML_ELEMENT(LO_EXT, XML_SHOWING_PLACE_HOLDER):
+ {
+ if (sax::Converter::convertBool(bTmp, rIter.toView()))
+ {
+ m_bShowingPlaceHolder = bTmp;
+ }
+ break;
+ }
+ case XML_ELEMENT(LO_EXT, XML_CHECKBOX):
+ {
+ if (sax::Converter::convertBool(bTmp, rIter.toView()))
+ {
+ m_bCheckbox = bTmp;
+ }
+ break;
+ }
+ case XML_ELEMENT(LO_EXT, XML_CHECKED):
+ {
+ if (sax::Converter::convertBool(bTmp, rIter.toView()))
+ {
+ m_bChecked = bTmp;
+ }
+ break;
+ }
+ case XML_ELEMENT(LO_EXT, XML_CHECKED_STATE):
+ {
+ m_aCheckedState = rIter.toString();
+ break;
+ }
+ case XML_ELEMENT(LO_EXT, XML_UNCHECKED_STATE):
+ {
+ m_aUncheckedState = rIter.toString();
+ break;
+ }
+ case XML_ELEMENT(LO_EXT, XML_PICTURE):
+ {
+ if (sax::Converter::convertBool(bTmp, rIter.toView()))
+ {
+ m_bPicture = bTmp;
+ }
+ break;
+ }
+ case XML_ELEMENT(LO_EXT, XML_DATE):
+ {
+ if (sax::Converter::convertBool(bTmp, rIter.toView()))
+ {
+ m_bDate = bTmp;
+ }
+ break;
+ }
+ case XML_ELEMENT(LO_EXT, XML_DATE_FORMAT):
+ {
+ m_aDateFormat = rIter.toString();
+ break;
+ }
+ case XML_ELEMENT(LO_EXT, XML_DATE_RFC_LANGUAGE_TAG):
+ {
+ m_aDateLanguage = rIter.toString();
+ break;
+ }
+ case XML_ELEMENT(LO_EXT, XML_CURRENT_DATE):
+ {
+ m_aCurrentDate = rIter.toString();
+ break;
+ }
+ case XML_ELEMENT(LO_EXT, XML_PLAIN_TEXT):
+ {
+ if (sax::Converter::convertBool(bTmp, rIter.toView()))
+ {
+ m_bPlainText = bTmp;
+ }
+ break;
+ }
+ case XML_ELEMENT(LO_EXT, XML_COMBOBOX):
+ {
+ if (sax::Converter::convertBool(bTmp, rIter.toView()))
+ {
+ m_bComboBox = bTmp;
+ }
+ break;
+ }
+ case XML_ELEMENT(LO_EXT, XML_DROPDOWN):
+ {
+ if (sax::Converter::convertBool(bTmp, rIter.toView()))
+ {
+ m_bDropDown = bTmp;
+ }
+ break;
+ }
+ case XML_ELEMENT(LO_EXT, XML_ALIAS):
+ {
+ m_aAlias = rIter.toString();
+ break;
+ }
+ case XML_ELEMENT(LO_EXT, XML_TAG):
+ {
+ m_aTag = rIter.toString();
+ break;
+ }
+ case XML_ELEMENT(LO_EXT, XML_ID):
+ {
+ if (sax::Converter::convertNumber(nTmp, rIter.toView()))
+ {
+ m_nId = nTmp;
+ }
+ break;
+ }
+ case XML_ELEMENT(LO_EXT, XML_TAB_INDEX):
+ {
+ if (sax::Converter::convertNumber(nTmp, rIter.toView()))
+ {
+ m_nTabIndex = nTmp;
+ }
+ break;
+ }
+ case XML_ELEMENT(LO_EXT, XML_LOCK):
+ {
+ m_aLock = rIter.toString();
+ break;
+ }
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", rIter);
+ }
+ }
+}
+
+void XMLContentControlContext::endFastElement(sal_Int32)
+{
+ if (!m_xStart.is())
+ {
+ SAL_WARN("xmloff.text", "XMLContentControlContext::endFastElement: no m_xStart");
+ return;
+ }
+
+ uno::Reference<text::XTextRange> xEndRange
+ = GetImport().GetTextImport()->GetCursorAsRange()->getStart();
+
+ // Create range for insertion.
+ uno::Reference<text::XTextCursor> xInsertionCursor
+ = GetImport().GetTextImport()->GetText()->createTextCursorByRange(xEndRange);
+ xInsertionCursor->gotoRange(m_xStart, /*bExpand=*/true);
+
+ uno::Reference<text::XTextContent> xContentControl
+ = XMLTextMarkImportContext::CreateAndInsertMark(
+ GetImport(), "com.sun.star.text.ContentControl", OUString(), xInsertionCursor);
+ if (!xContentControl.is())
+ {
+ SAL_WARN("xmloff.text", "cannot insert content control");
+ return;
+ }
+
+ uno::Reference<beans::XPropertySet> xPropertySet(xContentControl, uno::UNO_QUERY);
+ if (!xPropertySet.is())
+ {
+ return;
+ }
+
+ if (m_bShowingPlaceHolder)
+ {
+ xPropertySet->setPropertyValue("ShowingPlaceHolder", uno::Any(m_bShowingPlaceHolder));
+ }
+
+ if (m_bCheckbox)
+ {
+ xPropertySet->setPropertyValue("Checkbox", uno::Any(m_bCheckbox));
+ }
+ if (m_bChecked)
+ {
+ xPropertySet->setPropertyValue("Checked", uno::Any(m_bChecked));
+ }
+ if (!m_aCheckedState.isEmpty())
+ {
+ xPropertySet->setPropertyValue("CheckedState", uno::Any(m_aCheckedState));
+ }
+ if (!m_aUncheckedState.isEmpty())
+ {
+ xPropertySet->setPropertyValue("UncheckedState", uno::Any(m_aUncheckedState));
+ }
+ if (!m_aListItems.empty())
+ {
+ xPropertySet->setPropertyValue("ListItems",
+ uno::Any(comphelper::containerToSequence(m_aListItems)));
+ }
+
+ if (m_bPicture)
+ {
+ xPropertySet->setPropertyValue("Picture", uno::Any(m_bPicture));
+ }
+
+ if (m_bDate)
+ {
+ xPropertySet->setPropertyValue("Date", uno::Any(m_bDate));
+ }
+ if (!m_aDateFormat.isEmpty())
+ {
+ xPropertySet->setPropertyValue("DateFormat", uno::Any(m_aDateFormat));
+ }
+ if (!m_aDateLanguage.isEmpty())
+ {
+ xPropertySet->setPropertyValue("DateLanguage", uno::Any(m_aDateLanguage));
+ }
+ if (!m_aCurrentDate.isEmpty())
+ {
+ xPropertySet->setPropertyValue("CurrentDate", uno::Any(m_aCurrentDate));
+ }
+
+ if (m_bPlainText)
+ {
+ xPropertySet->setPropertyValue("PlainText", uno::Any(m_bPlainText));
+ }
+
+ if (m_bComboBox)
+ {
+ xPropertySet->setPropertyValue("ComboBox", uno::Any(m_bComboBox));
+ }
+
+ if (m_bDropDown)
+ {
+ xPropertySet->setPropertyValue("DropDown", uno::Any(m_bDropDown));
+ }
+
+ if (!m_aAlias.isEmpty())
+ {
+ xPropertySet->setPropertyValue("Alias", uno::Any(m_aAlias));
+ }
+
+ if (!m_aTag.isEmpty())
+ {
+ xPropertySet->setPropertyValue("Tag", uno::Any(m_aTag));
+ }
+
+ if (m_nId)
+ {
+ xPropertySet->setPropertyValue("Id", uno::Any(m_nId));
+ }
+
+ if (m_nTabIndex)
+ {
+ xPropertySet->setPropertyValue("TabIndex", uno::Any(m_nTabIndex));
+ }
+
+ if (!m_aLock.isEmpty())
+ {
+ xPropertySet->setPropertyValue("Lock", uno::Any(m_aLock));
+ }
+}
+
+css::uno::Reference<css::xml::sax::XFastContextHandler>
+XMLContentControlContext::createFastChildContext(
+ sal_Int32 nElement, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
+{
+ switch (nElement)
+ {
+ case XML_ELEMENT(LO_EXT, XML_LIST_ITEM):
+ return new XMLListItemContext(GetImport(), *this);
+ break;
+ default:
+ break;
+ }
+
+ return XMLImpSpanContext_Impl::CreateSpanContext(GetImport(), nElement, xAttrList, m_rHints,
+ m_rIgnoreLeadingSpace);
+}
+
+void XMLContentControlContext::characters(const OUString& rChars)
+{
+ GetImport().GetTextImport()->InsertString(rChars, m_rIgnoreLeadingSpace);
+}
+
+void XMLContentControlContext::AppendListItem(const css::beans::PropertyValues& rListItem)
+{
+ m_aListItems.push_back(rListItem);
+}
+
+XMLListItemContext::XMLListItemContext(SvXMLImport& rImport,
+ XMLContentControlContext& rContentControl)
+ : SvXMLImportContext(rImport)
+ , m_rContentControl(rContentControl)
+{
+}
+
+void XMLListItemContext::startFastElement(
+ sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
+{
+ OUString aDisplayText;
+ OUString aValue;
+
+ for (auto& rIter : sax_fastparser::castToFastAttributeList(xAttrList))
+ {
+ switch (rIter.getToken())
+ {
+ case XML_ELEMENT(LO_EXT, XML_DISPLAY_TEXT):
+ {
+ aDisplayText = rIter.toString();
+ break;
+ }
+ case XML_ELEMENT(LO_EXT, XML_VALUE):
+ {
+ aValue = rIter.toString();
+ break;
+ }
+ default:
+ XMLOFF_WARN_UNKNOWN("xmloff", rIter);
+ }
+ }
+
+ uno::Sequence<beans::PropertyValue> aListItem = {
+ comphelper::makePropertyValue("DisplayText", uno::Any(aDisplayText)),
+ comphelper::makePropertyValue("Value", uno::Any(aValue)),
+ };
+ m_rContentControl.AppendListItem(aListItem);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/xmlcontentcontrolcontext.hxx b/xmloff/source/text/xmlcontentcontrolcontext.hxx
new file mode 100644
index 0000000000..13c1e50f23
--- /dev/null
+++ b/xmloff/source/text/xmlcontentcontrolcontext.hxx
@@ -0,0 +1,92 @@
+/* -*- 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 .
+ */
+#pragma once
+
+#include <xmloff/xmlictxt.hxx>
+
+#include <vector>
+
+#include <com/sun/star/text/XTextContent.hpp>
+#include <com/sun/star/beans/PropertyValues.hpp>
+
+class XMLHints_Impl;
+
+/// Imports <loext:content-control>.
+class XMLContentControlContext : public SvXMLImportContext
+{
+ XMLHints_Impl& m_rHints;
+
+ bool& m_rIgnoreLeadingSpace;
+
+ css::uno::Reference<css::text::XTextRange> m_xStart;
+
+ bool m_bShowingPlaceHolder = false;
+
+ bool m_bCheckbox = false;
+ bool m_bChecked = false;
+ OUString m_aCheckedState;
+ OUString m_aUncheckedState;
+ std::vector<css::beans::PropertyValues> m_aListItems;
+ bool m_bPicture = false;
+ bool m_bDate = false;
+ OUString m_aDateFormat;
+ OUString m_aDateLanguage;
+ OUString m_aCurrentDate;
+ bool m_bPlainText = false;
+ bool m_bComboBox = false;
+ bool m_bDropDown = false;
+ OUString m_aAlias;
+ OUString m_aTag;
+ sal_Int32 m_nId = 0;
+ sal_uInt32 m_nTabIndex = 0;
+ OUString m_aLock;
+
+public:
+ XMLContentControlContext(SvXMLImport& rImport, sal_Int32 nElement, XMLHints_Impl& rHints,
+ bool& rIgnoreLeadingSpace);
+
+ void SAL_CALL startFastElement(
+ sal_Int32 nElement,
+ const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList) override;
+
+ void SAL_CALL endFastElement(sal_Int32 nElement) override;
+
+ css::uno::Reference<css::xml::sax::XFastContextHandler> SAL_CALL createFastChildContext(
+ sal_Int32 nElement,
+ const css::uno::Reference<css::xml::sax::XFastAttributeList>& rAttrList) override;
+
+ void SAL_CALL characters(const OUString& rChars) override;
+
+ void AppendListItem(const css::beans::PropertyValues& rListItem);
+};
+
+/// Imports <loext:list-item> inside <loext:content-control>.
+class XMLListItemContext : public SvXMLImportContext
+{
+ XMLContentControlContext& m_rContentControl;
+
+public:
+ XMLListItemContext(SvXMLImport& rImport, XMLContentControlContext& rContentControl);
+
+ void SAL_CALL startFastElement(
+ sal_Int32 nElement,
+ const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/xmllinebreakcontext.cxx b/xmloff/source/text/xmllinebreakcontext.cxx
new file mode 100644
index 0000000000..67b56c2d32
--- /dev/null
+++ b/xmloff/source/text/xmllinebreakcontext.cxx
@@ -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/.
+ */
+
+#include "xmllinebreakcontext.hxx"
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/text/XTextContent.hpp>
+
+#include <xmloff/xmlement.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmluconv.hxx>
+
+using namespace com::sun::star;
+using namespace xmloff::token;
+
+namespace
+{
+const SvXMLEnumMapEntry<sal_Int16> pXML_LineBreakClear_Enum[] = {
+ { XML_NONE, 0 }, { XML_LEFT, 1 }, { XML_RIGHT, 2 }, { XML_ALL, 3 }, { XML_TOKEN_INVALID, 0 }
+};
+}
+
+SvXMLLineBreakContext::SvXMLLineBreakContext(SvXMLImport& rImport, XMLTextImportHelper& rHelper)
+ : SvXMLImportContext(rImport)
+ , m_rHelper(rHelper)
+{
+}
+
+void SvXMLLineBreakContext::startFastElement(
+ sal_Int32 /*nElement*/, const uno::Reference<xml::sax::XFastAttributeList>& xAttrList)
+{
+ const uno::Reference<frame::XModel>& xModel = GetImport().GetModel();
+ uno::Reference<lang::XMultiServiceFactory> xFactory(xModel, uno::UNO_QUERY);
+ if (!xFactory.is())
+ return;
+
+ uno::Reference<text::XTextContent> xLineBreak(
+ xFactory->createInstance("com.sun.star.text.LineBreak"), uno::UNO_QUERY);
+
+ sal_Int16 eClear = 0;
+ OUString aClear = xAttrList->getValue(XML_ELEMENT(LO_EXT, XML_CLEAR));
+ if (SvXMLUnitConverter::convertEnum(eClear, aClear, pXML_LineBreakClear_Enum))
+ {
+ uno::Reference<beans::XPropertySet> xLineBreakProps(xLineBreak, uno::UNO_QUERY);
+ xLineBreakProps->setPropertyValue("Clear", uno::Any(eClear));
+ }
+
+ m_rHelper.InsertTextContent(xLineBreak);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/text/xmllinebreakcontext.hxx b/xmloff/source/text/xmllinebreakcontext.hxx
new file mode 100644
index 0000000000..ef1f744bb4
--- /dev/null
+++ b/xmloff/source/text/xmllinebreakcontext.hxx
@@ -0,0 +1,31 @@
+/* -*- 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 <xmloff/dllapi.h>
+#include <xmloff/xmlictxt.hxx>
+
+class XMLTextImportHelper;
+
+/// Handles <text:line-break loext:clear="..."> when the attribute is present.
+class XMLOFF_DLLPUBLIC SvXMLLineBreakContext : public SvXMLImportContext
+{
+ XMLTextImportHelper& m_rHelper;
+
+public:
+ SvXMLLineBreakContext(SvXMLImport& rImport, XMLTextImportHelper& rHelper);
+
+protected:
+ void SAL_CALL startFastElement(
+ sal_Int32 nElement,
+ const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */