summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2021-04-16 14:30:28 +0300
committerMike Kaganski <mike.kaganski@collabora.com>2021-04-16 18:41:47 +0200
commitd8c0b63355af6caf3f0145dd1c10a93d63134a88 (patch)
tree7a4b312e9eb198400eef9ba045c364f97b6887d1
parenttdf#122222: add DOCX export of resolved comments as "done" (diff)
downloadcore-d8c0b63355af6caf3f0145dd1c10a93d63134a88.tar.gz
core-d8c0b63355af6caf3f0145dd1c10a93d63134a88.zip
tdf#122222: add DOCX import of resolved comments as "done"
Change-Id: Id596d18965de2d8c98853c281188fe8d749055f4 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114204 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport16.cxx56
-rw-r--r--writerfilter/CustomTarget_source.mk1
-rw-r--r--writerfilter/inc/dmapper/CommentProperties.hxx21
-rw-r--r--writerfilter/inc/dmapper/resourcemodel.hxx4
-rw-r--r--writerfilter/inc/ooxml/OOXMLDocument.hxx2
-rw-r--r--writerfilter/source/dmapper/DomainMapper.cxx12
-rw-r--r--writerfilter/source/dmapper/DomainMapper.hxx2
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.cxx21
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.hxx7
-rw-r--r--writerfilter/source/dmapper/PropertyMap.hxx4
-rw-r--r--writerfilter/source/ooxml/OOXMLDocumentImpl.cxx11
-rw-r--r--writerfilter/source/ooxml/OOXMLDocumentImpl.hxx4
-rw-r--r--writerfilter/source/ooxml/OOXMLFactory.hxx3
-rw-r--r--writerfilter/source/ooxml/OOXMLFastContextHandler.cxx37
-rw-r--r--writerfilter/source/ooxml/OOXMLFastContextHandler.hxx16
-rw-r--r--writerfilter/source/ooxml/OOXMLStreamImpl.cxx5
-rw-r--r--writerfilter/source/ooxml/model.xml64
17 files changed, 257 insertions, 13 deletions
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx
index 1c4bb106a0ec..722eb4f96606 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx
@@ -18,6 +18,7 @@
#include <com/sun/star/drawing/FillStyle.hpp>
#include <com/sun/star/text/XEndnotesSupplier.hpp>
#include <com/sun/star/text/XFootnotesSupplier.hpp>
+#include <com/sun/star/text/XTextFieldsSupplier.hpp>
#include <com/sun/star/text/XTextViewCursorSupplier.hpp>
#include <com/sun/star/text/XTextTable.hpp>
#include <com/sun/star/text/XTextTablesSupplier.hpp>
@@ -312,18 +313,8 @@ DECLARE_OOXMLEXPORT_TEST(testTdf140137, "tdf140137.docx")
// Don't throw exception during load
}
-DECLARE_OOXMLEXPORT_TEST(testCommentDone, "CommentDone.docx")
+DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testCommentDone, "CommentDone.docx")
{
- if (!mbExported)
- {
- // This manually toggles (enables) the resolved state of the first comment now, while
- // import is not yet implemented (TODO)
- uno::Sequence<beans::PropertyValue> aPropertyValues = comphelper::InitPropertySequence(
- { { "Id", uno::makeAny(OUString("1")) } });
- dispatchCommand(mxComponent, ".uno:ResolveComment", aPropertyValues);
- return;
- }
-
xmlDocUniquePtr pXmlComm = parseExport("word/comments.xml");
assertXPath(pXmlComm, "/w:comments/w:comment[1]/w:p", 2);
OUString idLastPara = getXPath(pXmlComm, "/w:comments/w:comment[1]/w:p[2]", "paraId");
@@ -335,6 +326,49 @@ DECLARE_OOXMLEXPORT_TEST(testCommentDone, "CommentDone.docx")
assertXPath(pXmlCommExt, "/w15:commentsEx/w15:commentEx", "done", "1");
}
+DECLARE_OOXMLEXPORT_TEST(testCommentDoneModel, "CommentDone.docx")
+{
+ css::uno::Reference<css::text::XTextFieldsSupplier> xTextFieldsSupplier(
+ mxComponent, css::uno::UNO_QUERY_THROW);
+ auto xFields(xTextFieldsSupplier->getTextFields()->createEnumeration());
+
+ // First comment: initially resolved, toggled to unresolved on import, unresolved on roundtrip
+ CPPUNIT_ASSERT(xFields->hasMoreElements());
+ css::uno::Any aComment = xFields->nextElement();
+ css::uno::Reference<css::beans::XPropertySet> xComment(aComment, css::uno::UNO_QUERY_THROW);
+
+ if (!mbExported)
+ {
+ // Check that it's resolved when initially read
+ CPPUNIT_ASSERT_EQUAL(true, xComment->getPropertyValue("Resolved").get<bool>());
+ // Set to unresolved
+ xComment->setPropertyValue("Resolved", css::uno::Any(false));
+ }
+ else
+ {
+ // After the roundtrip, it keeps the "unresolved" state set above
+ CPPUNIT_ASSERT_EQUAL(false, xComment->getPropertyValue("Resolved").get<bool>());
+ }
+
+ // Second comment: initially unresolved, toggled to resolved on import, resolved on roundtrip
+ CPPUNIT_ASSERT(xFields->hasMoreElements());
+ aComment = xFields->nextElement();
+ xComment.set(aComment, css::uno::UNO_QUERY_THROW);
+
+ if (!mbExported)
+ {
+ // Check that it's unresolved when initially read
+ CPPUNIT_ASSERT_EQUAL(false, xComment->getPropertyValue("Resolved").get<bool>());
+ // Set to resolved
+ xComment->setPropertyValue("Resolved", css::uno::Any(true));
+ }
+ else
+ {
+ // After the roundtrip, it keeps the "resolved" state set above
+ CPPUNIT_ASSERT_EQUAL(true, xComment->getPropertyValue("Resolved").get<bool>());
+ }
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/CustomTarget_source.mk b/writerfilter/CustomTarget_source.mk
index 8d7b3d22b690..d0085654a146 100644
--- a/writerfilter/CustomTarget_source.mk
+++ b/writerfilter/CustomTarget_source.mk
@@ -41,6 +41,7 @@ writerfilter_OOXMLNAMESPACES= \
vml-wordprocessingDrawing \
wp14 \
w14 \
+ w15 \
a14 \
wml
diff --git a/writerfilter/inc/dmapper/CommentProperties.hxx b/writerfilter/inc/dmapper/CommentProperties.hxx
new file mode 100644
index 000000000000..1cba6930d4c6
--- /dev/null
+++ b/writerfilter/inc/dmapper/CommentProperties.hxx
@@ -0,0 +1,21 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.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
+
+namespace writerfilter
+{
+struct CommentProperties
+{
+ bool bDone;
+ // TODO: a reference to a parent comment (paraIdParent: [MS-DOCX] sect. 2.5.3.1 CT_CommentEx)
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/writerfilter/inc/dmapper/resourcemodel.hxx b/writerfilter/inc/dmapper/resourcemodel.hxx
index fce90839d520..1a525b12296f 100644
--- a/writerfilter/inc/dmapper/resourcemodel.hxx
+++ b/writerfilter/inc/dmapper/resourcemodel.hxx
@@ -54,6 +54,8 @@ typedef sal_uInt32 Id;
namespace writerfilter
{
+struct CommentProperties;
+
/**
Reference to a resource that generates events and sends them to a
handler.
@@ -297,6 +299,8 @@ public:
/// Receives end mark for glossary document entry.
virtual void endGlossaryEntry() = 0;
+ virtual void commentProps(const OUString& /*sId*/, const CommentProperties& /*rProps*/) {}
+
protected:
~Stream() override {}
};
diff --git a/writerfilter/inc/ooxml/OOXMLDocument.hxx b/writerfilter/inc/ooxml/OOXMLDocument.hxx
index 1110fa84b1e0..de0a8a7134de 100644
--- a/writerfilter/inc/ooxml/OOXMLDocument.hxx
+++ b/writerfilter/inc/ooxml/OOXMLDocument.hxx
@@ -72,7 +72,7 @@ class OOXMLStream : public virtual SvRefBase
{
public:
enum StreamType_t { UNKNOWN, DOCUMENT, STYLES, WEBSETTINGS, FONTTABLE, NUMBERING,
- FOOTNOTES, ENDNOTES, COMMENTS, THEME, CUSTOMXML, CUSTOMXMLPROPS, GLOSSARY, CHARTS, EMBEDDINGS, SETTINGS, VBAPROJECT, FOOTER, HEADER, VBADATA };
+ FOOTNOTES, ENDNOTES, COMMENTS, COMMENTS_EXTENDED, THEME, CUSTOMXML, CUSTOMXMLPROPS, GLOSSARY, CHARTS, EMBEDDINGS, SETTINGS, VBAPROJECT, FOOTER, HEADER, VBADATA };
typedef tools::SvRef<OOXMLStream> Pointer_t;
/**
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index 2561120adb2d..9d163f2e671e 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -1219,6 +1219,13 @@ void DomainMapper::lcl_attribute(Id nName, Value & val)
m_pImpl->HandleAltChunk(sStringValue);
}
break;
+ case NS_ooxml::LN_AG_Parids_paraId:
+ if (ParagraphPropertyMap* pParaContext
+ = dynamic_cast<ParagraphPropertyMap*>(m_pImpl->GetTopContext().get()))
+ {
+ pParaContext->SetParaId(sStringValue);
+ }
+ break;
default:
SAL_WARN("writerfilter", "DomainMapper::lcl_attribute: unhandled token: " << nName);
}
@@ -4103,6 +4110,11 @@ void DomainMapper::finishParagraph(const bool bRemove, const bool bNoNumbering)
m_pImpl->finishParagraph(m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH), bRemove, bNoNumbering);
}
+void DomainMapper::commentProps(const OUString& sId, const CommentProperties& rProps)
+{
+ m_pImpl->commentProps(sId, rProps);
+}
+
} //namespace writerfilter
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/source/dmapper/DomainMapper.hxx b/writerfilter/source/dmapper/DomainMapper.hxx
index 4e47dd70a441..94b91460a6f9 100644
--- a/writerfilter/source/dmapper/DomainMapper.hxx
+++ b/writerfilter/source/dmapper/DomainMapper.hxx
@@ -131,6 +131,8 @@ public:
void HandleRedline( Sprm& rSprm );
+ virtual void commentProps(const OUString& sId, const CommentProperties& rProps) override;
+
private:
// Stream
virtual void lcl_startSectionGroup() override;
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 914836944486..b0ef95e0a785 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -2120,6 +2120,17 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap, con
m_previousRedline.clear();
m_bParaChanged = false;
+ if (m_bIsInComments && pParaContext)
+ {
+ if (const OUString sParaId = pParaContext->GetParaId(); !sParaId.isEmpty())
+ {
+ if (const auto& item = m_aCommentProps.find(sParaId); item != m_aCommentProps.end())
+ {
+ m_bAnnotationResolved = item->second.bDone;
+ }
+ }
+ }
+
if (m_bIsFirstParaInShape)
m_bIsFirstParaInShape = false;
@@ -3037,6 +3048,9 @@ void DomainMapper_Impl::PopAnnotation()
try
{
+ if (m_bAnnotationResolved)
+ m_xAnnotationField->setPropertyValue("Resolved", css::uno::Any(true));
+
// See if the annotation will be a single position or a range.
if (m_nAnnotationId == -1 || !m_aAnnotationPositions[m_nAnnotationId].m_xStart.is() || !m_aAnnotationPositions[m_nAnnotationId].m_xEnd.is())
{
@@ -3085,6 +3099,7 @@ void DomainMapper_Impl::PopAnnotation()
m_xAnnotationField.clear();
m_nAnnotationId = -1;
+ m_bAnnotationResolved = false;
}
void DomainMapper_Impl::PushPendingShape( const uno::Reference< drawing::XShape > & xShape )
@@ -7700,6 +7715,12 @@ void DomainMapper_Impl::substream(Id rName,
assert(m_aPropertyStacks[i].size() == propSize[i]);
}
}
+
+void DomainMapper_Impl::commentProps(const OUString& sId, const CommentProperties& rProps)
+{
+ m_aCommentProps[sId] = rProps;
+}
+
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index c4d9b5014c04..c12d75e201fa 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -33,6 +33,8 @@
#include <vector>
#include <optional>
+#include <dmapper/CommentProperties.hxx>
+
#include "DomainMapper.hxx"
#include "DomainMapperTableManager.hxx"
#include "DomainMapperTableHandler.hxx"
@@ -590,6 +592,7 @@ private:
//annotation import
css::uno::Reference< css::beans::XPropertySet > m_xAnnotationField;
sal_Int32 m_nAnnotationId;
+ bool m_bAnnotationResolved = false;
std::unordered_map< sal_Int32, AnnotationPosition > m_aAnnotationPositions;
void GetCurrentLocale(css::lang::Locale& rLocale);
@@ -1128,6 +1131,8 @@ public:
/// Handles <w:altChunk>.
void HandleAltChunk(const OUString& rStreamName);
+ void commentProps(const OUString& sId, const CommentProperties& rProps);
+
private:
void PushPageHeaderFooter(bool bHeader, SectionPropertyMap::PageType eType);
// Start a new index section; if needed, finish current paragraph
@@ -1146,6 +1151,8 @@ private:
bool m_bParaWithInlineObject;
/// SAXException was seen so document will be abandoned
bool m_bSaxError;
+
+ std::unordered_map<OUString, CommentProperties> m_aCommentProps;
};
} //namespace writerfilter::dmapper
diff --git a/writerfilter/source/dmapper/PropertyMap.hxx b/writerfilter/source/dmapper/PropertyMap.hxx
index d5282991f1b5..d4f981c5db91 100644
--- a/writerfilter/source/dmapper/PropertyMap.hxx
+++ b/writerfilter/source/dmapper/PropertyMap.hxx
@@ -429,6 +429,7 @@ private:
sal_Int32 m_yAlign; // from ST_YAlign bottom, center, inline, inside, outside, top
sal_Int8 m_nDropCapLength; // number of characters
OUString m_sParaStyleName;
+ OUString m_sParaId; // [MS-DOCX] sect. 2.2.4 "p and tr Extensions"
css::uno::Reference< css::text::XTextRange > m_xStartingRange; // start of a frame
css::uno::Reference< css::text::XTextRange > m_xEndingRange; // end of the frame
@@ -507,6 +508,9 @@ public:
const OUString& GetParaStyleName() const { return m_sParaStyleName; }
void SetParaStyleName( const OUString& rSet ) { m_sParaStyleName = rSet; }
+ const OUString& GetParaId() const { return m_sParaId; }
+ void SetParaId(const OUString& rSet) { m_sParaId = rSet; }
+
void ResetFrameProperties();
};
diff --git a/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx b/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx
index 8d959dc0119f..0331d3539508 100644
--- a/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx
+++ b/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx
@@ -310,9 +310,20 @@ void OOXMLDocumentImpl::resolveEndnote(Stream & rStream,
resolveFastSubStreamWithId(rStream, mpXNoteStream, nId);
}
+void OOXMLDocumentImpl::resolveCommentsExtendedStream(Stream& rStream)
+{
+ resolveFastSubStream(rStream, OOXMLStream::COMMENTS_EXTENDED);
+}
+
void OOXMLDocumentImpl::resolveComment(Stream & rStream,
const sal_Int32 nId)
{
+ if (!mbCommentsExtendedResolved)
+ {
+ resolveCommentsExtendedStream(rStream);
+ mbCommentsExtendedResolved = true;
+ }
+
writerfilter::Reference<Stream>::Pointer_t pStream =
getXNoteStream(OOXMLStream::COMMENTS, nId);
diff --git a/writerfilter/source/ooxml/OOXMLDocumentImpl.hxx b/writerfilter/source/ooxml/OOXMLDocumentImpl.hxx
index 93259997515b..ed9db125cbe8 100644
--- a/writerfilter/source/ooxml/OOXMLDocumentImpl.hxx
+++ b/writerfilter/source/ooxml/OOXMLDocumentImpl.hxx
@@ -67,6 +67,8 @@ class OOXMLDocumentImpl : public OOXMLDocument
/// Graphic mapper
css::uno::Reference<css::graphic::XGraphicMapper> mxGraphicMapper;
+ bool mbCommentsExtendedResolved = false;
+
private:
void resolveFastSubStream(Stream & rStream,
OOXMLStream::StreamType_t nType);
@@ -88,6 +90,8 @@ private:
void resolveCustomXmlStream(Stream & rStream);
void resolveGlossaryStream(Stream & rStream);
void resolveEmbeddingsStream(const OOXMLStream::Pointer_t& pStream);
+ void resolveCommentsExtendedStream(Stream & rStream);
+
public:
OOXMLDocumentImpl(OOXMLStream::Pointer_t const & pStream, const css::uno::Reference<css::task::XStatusIndicator>& xStatusIndicator, bool bSkipImages, const css::uno::Sequence<css::beans::PropertyValue>& rDescriptor);
virtual ~OOXMLDocumentImpl() override;
diff --git a/writerfilter/source/ooxml/OOXMLFactory.hxx b/writerfilter/source/ooxml/OOXMLFactory.hxx
index 79c375f2863e..4f3c82f1b070 100644
--- a/writerfilter/source/ooxml/OOXMLFactory.hxx
+++ b/writerfilter/source/ooxml/OOXMLFactory.hxx
@@ -48,7 +48,8 @@ enum class ResourceType {
TwipsMeasure_asSigned,
TwipsMeasure_asZero,
HpsMeasure,
- MeasurementOrPercent
+ MeasurementOrPercent,
+ CommentEx,
};
struct AttributeInfo
diff --git a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
index 2c48f121b066..efd097405c90 100644
--- a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
+++ b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
@@ -34,6 +34,7 @@
#include "OOXMLFastContextHandler.hxx"
#include "OOXMLFactory.hxx"
#include "Handler.hxx"
+#include <dmapper/CommentProperties.hxx>
#include <dmapper/PropertyIds.hxx>
#include <comphelper/propertysequence.hxx>
#include <comphelper/sequenceashashmap.hxx>
@@ -421,6 +422,20 @@ void OOXMLFastContextHandler::startParagraphGroup()
{
mpStream->startParagraphGroup();
mpParserState->setInParagraphGroup(true);
+
+ if (const auto& pPropSet = getPropertySet())
+ {
+ OOXMLPropertySetEntryToString aHandler(NS_ooxml::LN_AG_Parids_paraId);
+ pPropSet->resolve(aHandler);
+ if (const OUString& sText = aHandler.getString(); !sText.isEmpty())
+ {
+ OOXMLStringValue::Pointer_t pVal = new OOXMLStringValue(sText);
+ OOXMLPropertySet::Pointer_t pPropertySet(new OOXMLPropertySet);
+ pPropertySet->add(NS_ooxml::LN_AG_Parids_paraId, pVal, OOXMLProperty::ATTRIBUTE);
+ mpStream->props(pPropertySet.get());
+ }
+ }
+
}
}
@@ -2215,6 +2230,28 @@ void OOXMLFastContextHandlerMath::process()
mpStream->props( pProps.get() );
}
+OOXMLFastContextHandlerCommentEx::OOXMLFastContextHandlerCommentEx(
+ OOXMLFastContextHandler* pContext)
+ : OOXMLFastContextHandler(pContext)
+{
+}
+
+void OOXMLFastContextHandlerCommentEx::lcl_endFastElement(Token_t /*Element*/)
+{
+ mpStream->commentProps(m_sParaId, { m_bDone });
+}
+
+void OOXMLFastContextHandlerCommentEx::att_paraId(const OOXMLValue::Pointer_t& pValue)
+{
+ m_sParaId = pValue->getString();
+}
+
+void OOXMLFastContextHandlerCommentEx::att_done(const OOXMLValue::Pointer_t& pValue)
+{
+ if (pValue->getInt())
+ m_bDone = true;
+}
+
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/source/ooxml/OOXMLFastContextHandler.hxx b/writerfilter/source/ooxml/OOXMLFastContextHandler.hxx
index aa67decdb55b..6aa2bd2ed6c2 100644
--- a/writerfilter/source/ooxml/OOXMLFastContextHandler.hxx
+++ b/writerfilter/source/ooxml/OOXMLFastContextHandler.hxx
@@ -599,6 +599,22 @@ protected:
virtual void process() override;
};
+class OOXMLFastContextHandlerCommentEx : public OOXMLFastContextHandler
+{
+public:
+ explicit OOXMLFastContextHandlerCommentEx(OOXMLFastContextHandler* pContext);
+
+ virtual std::string getType() const override { return "CommentEx"; }
+ virtual void lcl_endFastElement(Token_t Element) override;
+
+ void att_paraId(const OOXMLValue::Pointer_t& pValue);
+ void att_done(const OOXMLValue::Pointer_t& pValue);
+
+private:
+ OUString m_sParaId;
+ bool m_bDone = false;
+};
+
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/source/ooxml/OOXMLStreamImpl.cxx b/writerfilter/source/ooxml/OOXMLStreamImpl.cxx
index 1d54ffde00d1..67fa826957e9 100644
--- a/writerfilter/source/ooxml/OOXMLStreamImpl.cxx
+++ b/writerfilter/source/ooxml/OOXMLStreamImpl.cxx
@@ -145,6 +145,7 @@ bool OOXMLStreamImpl::lcl_getTarget(const uno::Reference<embed::XRelationshipAcc
static const OUStringLiteral sFooterType = u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer";
static const OUStringLiteral sHeaderType = u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/header";
static const OUStringLiteral sOleObjectType = u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject";
+ static const OUStringLiteral sCommentsExtendedType = u"http://schemas.microsoft.com/office/2011/relationships/commentsExtended";
// OOXML strict
static const OUStringLiteral sDocumentTypeStrict = u"http://purl.oclc.org/ooxml/officeDocument/relationships/officeDocument";
static const OUStringLiteral sStylesTypeStrict = u"http://purl.oclc.org/ooxml/officeDocument/relationships/styles";
@@ -248,6 +249,10 @@ bool OOXMLStreamImpl::lcl_getTarget(const uno::Reference<embed::XRelationshipAcc
sStreamType = sHeaderType;
sStreamTypeStrict = sHeaderTypeStrict;
break;
+ case COMMENTS_EXTENDED:
+ sStreamType = sCommentsExtendedType;
+ sStreamTypeStrict = sCommentsExtendedType;
+ break;
default:
break;
}
diff --git a/writerfilter/source/ooxml/model.xml b/writerfilter/source/ooxml/model.xml
index 3f45394d5d88..77dce046fb3d 100644
--- a/writerfilter/source/ooxml/model.xml
+++ b/writerfilter/source/ooxml/model.xml
@@ -26,6 +26,7 @@
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml"
+ xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing"
xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup"
@@ -5359,6 +5360,54 @@
<element name="cntxtAlts" tokenid="ooxml:cntxtAlts_cntxtAlts"/>
</resource>
</namespace>
+ <namespace name="w15">
+ <start name="commentsEx"/>
+ <grammar xmlns="http://relaxng.org/ns/structure/1.0" ns="http://schemas.microsoft.com/office/word/2012/wordml" attributeFormDefault="qualified">
+ <define name="commentsEx">
+ <element name="commentsEx">
+ <ref name="CT_CommentsEx"/>
+ </element>
+ </define>
+ <define name="CT_CommentsEx">
+ <element name="commentEx">
+ <ref name="CT_CommentEx"/>
+ </element>
+ </define>
+ <define name="CT_CommentEx">
+ <attribute name="paraId">
+ <ref name="ST_LongHexNumber"/>
+ </attribute>
+ <!-- Not yet used
+ <attribute name="paraIdParent">
+ <ref name="ST_LongHexNumber"/>
+ </attribute>
+ -->
+ <attribute name="done">
+ <ref name="ST_OnOff"/>
+ </attribute>
+ </define>
+ <define name="ST_LongHexNumber">
+ <data type="hexBinary"/>
+ </define>
+ <define name="ST_OnOff">
+ <choice>
+ <value>true</value>
+ <value>false</value>
+ <value>0</value>
+ <value>1</value>
+ </choice>
+ </define>
+ </grammar>
+ <resource name="CT_CommentsEx" resource="Stream">
+ <element name="commentEx" tokenid="ooxml:CT_CommentsEx_commentEx"/>
+ </resource>
+ <resource name="CT_CommentEx" resource="CommentEx">
+ <attribute name="paraId" tokenid="ooxml:CT_CommentEx_paraId" action="att_paraId"/>
+ <attribute name="done" tokenid="ooxml:CT_CommentEx_done" action="att_done"/>
+ </resource>
+ <resource name="ST_LongHexNumber" resource="String"/>
+ <resource name="ST_OnOff" resource="Boolean"/>
+ </namespace>
<namespace name="a14">
<grammar xmlns="http://relaxng.org/ns/structure/1.0" ns="http://schemas.microsoft.com/office/drawing/2010/main">
<!-- Simple types -->
@@ -14197,6 +14246,18 @@
</element>
</choice>
</define>
+ <!-- [MS-DOCX] sect. 2.2.4 "p and tr Extensions" -->
+ <!-- Should rather be in w14 namespace, but I don't see how to reference things from there -->
+ <define name="AG_Parids">
+ <attribute name="w14:paraId">
+ <data type="string"/>
+ </attribute>
+ <!-- Not yet used
+ <attribute name="textId">
+ <ref name="ST_LongHexNumber"/>
+ </attribute>
+ -->
+ </define>
<define name="CT_P">
<element name="pPr">
<ref name="CT_PPr"/>
@@ -14217,6 +14278,7 @@
<attribute name="rsidRDefault">
<data type="string"/>
</attribute>
+ <ref name="AG_Parids"/>
<!-- tdf#108714 : allow <w:br> at paragraph level (despite this is illegal according to ECMA-376-1:2016) - bug-to-bug compatibility with Word -->
<element name="br">
<ref name="CT_Br_OutOfOrder"/>
@@ -14522,6 +14584,7 @@
<attribute name="rsidTr">
<data type="string"/>
</attribute>
+ <ref name="AG_Parids"/>
</define>
<define name="ST_TblLayout">
<choice>
@@ -18296,6 +18359,7 @@
<element name="subDoc" tokenid="ooxml:EG_PContent_subDoc"/>
</resource>
<resource name="CT_P" resource="Stream">
+ <attribute name="w14:paraId" tokenid="ooxml:AG_Parids_paraId"/>
<action name="start" action="handleLastParagraphInSection"/>
<action name="start" action="startParagraphGroup"/>
<action name="start" action="setHandle"/>