summaryrefslogtreecommitdiff
path: root/writerfilter
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2022-03-08 08:42:44 +0100
committerMiklos Vajna <vmiklos@collabora.com>2022-03-08 12:25:55 +0100
commitf86d1482bef285f90079b5130e410646db96cf58 (patch)
treeca1d8c70df1e1fdc62df3ffb72cf345366cb129d /writerfilter
parent3455ef6eff0edb15b59d4e8818a1ce8f54b4454b (diff)
sw clearing breaks: add DOCX import
Map <w:br w:clear="..."> to the com.sun.star.text.LineBreak UNO service, but keep the default clear=none case unchanged. Change-Id: I145e891c1df0bbd0fdac2c62463dc801bca827fb Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131167 Reviewed-by: Miklos Vajna <vmiklos@collabora.com> Tested-by: Jenkins
Diffstat (limited to 'writerfilter')
-rw-r--r--writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx34
-rw-r--r--writerfilter/qa/cppunittests/dmapper/data/clearing-break.docxbin0 -> 15739 bytes
-rw-r--r--writerfilter/source/dmapper/DomainMapper.cxx18
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.cxx38
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.hxx8
-rw-r--r--writerfilter/source/ooxml/Handler.cxx9
-rw-r--r--writerfilter/source/ooxml/Handler.hxx3
-rw-r--r--writerfilter/source/ooxml/OOXMLFastContextHandler.cxx2
-rw-r--r--writerfilter/source/ooxml/OOXMLParserState.cxx2
9 files changed, 106 insertions, 8 deletions
diff --git a/writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx b/writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx
index a161c3514a17..16039f98370a 100644
--- a/writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx
@@ -284,6 +284,40 @@ CPPUNIT_TEST_FIXTURE(Test, testPasteOle)
uno::Reference<text::XTextRange> xPara(xParaEnum->nextElement(), uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(OUString("hello"), xPara->getString());
}
+
+CPPUNIT_TEST_FIXTURE(Test, testClearingBreak)
+{
+ // Given a document with a clearing break:
+ OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "clearing-break.docx";
+
+ // When loading that file:
+ getComponent() = loadFromDesktop(aURL);
+
+ // Then make sure that the clear property of the break is not ignored:
+ uno::Reference<text::XTextDocument> xTextDocument(getComponent(), uno::UNO_QUERY);
+ uno::Reference<text::XText> xText = xTextDocument->getText();
+ uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xText, uno::UNO_QUERY);
+ uno::Reference<container::XEnumeration> xParagraphs = xParaEnumAccess->createEnumeration();
+ uno::Reference<container::XEnumerationAccess> xParagraph(xParagraphs->nextElement(),
+ uno::UNO_QUERY);
+ uno::Reference<container::XEnumeration> xPortions = xParagraph->createEnumeration();
+ xPortions->nextElement();
+ xPortions->nextElement();
+ // Without the accompanying fix in place, this test would have failed with:
+ // An uncaught exception of type com.sun.star.container.NoSuchElementException
+ // i.e. the first para was just a fly + text portion, the clearing break was lost.
+ uno::Reference<beans::XPropertySet> xPortion(xPortions->nextElement(), uno::UNO_QUERY);
+ OUString aPortionType;
+ xPortion->getPropertyValue("TextPortionType") >>= aPortionType;
+ CPPUNIT_ASSERT_EQUAL(OUString("LineBreak"), aPortionType);
+ uno::Reference<text::XTextContent> xLineBreak;
+ xPortion->getPropertyValue("LineBreak") >>= xLineBreak;
+ sal_Int16 eClear{};
+ uno::Reference<beans::XPropertySet> xLineBreakProps(xLineBreak, uno::UNO_QUERY);
+ xLineBreakProps->getPropertyValue("Clear") >>= eClear;
+ // SwLineBreakClear::ALL
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(3), eClear);
+}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/qa/cppunittests/dmapper/data/clearing-break.docx b/writerfilter/qa/cppunittests/dmapper/data/clearing-break.docx
new file mode 100644
index 000000000000..453a4c2b83d1
--- /dev/null
+++ b/writerfilter/qa/cppunittests/dmapper/data/clearing-break.docx
Binary files differ
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index eed7ab8d45b0..f261538a0f19 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -749,9 +749,12 @@ void DomainMapper::lcl_attribute(Id nName, Value & val)
case NS_ooxml::LN_CT_SmartTagRun_element:
m_pImpl->getSmartTagHandler().setElement(val.getString());
break;
- case NS_ooxml::LN_CT_Br_type :
- //TODO: attributes for break (0x12) are not supported
- break;
+ case NS_ooxml::LN_CT_Br_type:
+ // Handled in the OOXMLBreakHandler dtor.
+ break;
+ case NS_ooxml::LN_CT_Br_clear:
+ m_pImpl->HandleLineBreakClear(val.getInt());
+ break;
case NS_ooxml::LN_CT_Fonts_hint :
/* assigns script type to ambiguous characters, values can be:
NS_ooxml::LN_Value_ST_Hint_default
@@ -3471,7 +3474,14 @@ void DomainMapper::lcl_text(const sal_uInt8 * data_, size_t len)
if (pContext == nullptr)
pContext = new PropertyMap();
- m_pImpl->appendTextPortion( sText, pContext );
+ if (sText == "\n")
+ {
+ m_pImpl->HandleLineBreak(pContext);
+ }
+ else
+ {
+ m_pImpl->appendTextPortion(sText, pContext);
+ }
}
}
catch( const uno::RuntimeException& )
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 882bd28086a6..bbbe68a01700 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -4004,6 +4004,44 @@ void DomainMapper_Impl::HandlePTab(sal_Int32 nAlignment)
xTextAppend->insertControlCharacter(xCursor, text::ControlCharacter::LINE_BREAK, true);
}
+void DomainMapper_Impl::HandleLineBreakClear(sal_Int32 nClear)
+{
+ switch (nClear)
+ {
+ case NS_ooxml::LN_Value_ST_BrClear_left:
+ // SwLineBreakClear::LEFT
+ m_oLineBreakClear = 1;
+ break;
+ case NS_ooxml::LN_Value_ST_BrClear_right:
+ // SwLineBreakClear::RIGHT
+ m_oLineBreakClear = 2;
+ break;
+ case NS_ooxml::LN_Value_ST_BrClear_all:
+ // SwLineBreakClear::ALL
+ m_oLineBreakClear = 3;
+ break;
+ }
+}
+
+void DomainMapper_Impl::HandleLineBreak(const PropertyMapPtr& pPropertyMap)
+{
+ if (!m_oLineBreakClear.has_value())
+ {
+ appendTextPortion("\n", pPropertyMap);
+ return;
+ }
+
+ if (GetTextFactory().is())
+ {
+ uno::Reference<text::XTextContent> xLineBreak(
+ GetTextFactory()->createInstance("com.sun.star.text.LineBreak"), uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xLineBreakProps(xLineBreak, uno::UNO_QUERY);
+ xLineBreakProps->setPropertyValue("Clear", uno::makeAny(*m_oLineBreakClear));
+ appendTextContent(xLineBreak, pPropertyMap->GetPropertyValues());
+ }
+ m_oLineBreakClear.reset();
+}
+
static sal_Int16 lcl_ParseNumberingType( const OUString& rCommand )
{
sal_Int16 nRet = style::NumberingType::PAGE_DESCRIPTOR;
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index bbd5d566367e..869d0cdf1ece 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -633,6 +633,8 @@ private:
bool m_bIsNewDoc;
bool m_bIsAltChunk = false;
bool m_bIsReadGlossaries;
+ std::optional<sal_Int16> m_oLineBreakClear;
+
public:
DomainMapper_Impl(
DomainMapper& rDMapper,
@@ -1169,6 +1171,12 @@ public:
/// Handles <w:ptab>.
void HandlePTab(sal_Int32 nAlignment);
+ /// Handles <w:br w:clear="...">.
+ void HandleLineBreakClear(sal_Int32 nClear);
+
+ /// Handles <w:br>.
+ void HandleLineBreak(const PropertyMapPtr& pPropertyMap);
+
void commentProps(const OUString& sId, const CommentProperties& rProps);
private:
diff --git a/writerfilter/source/ooxml/Handler.cxx b/writerfilter/source/ooxml/Handler.cxx
index d58453c8ee32..7cbd9b6bfdc3 100644
--- a/writerfilter/source/ooxml/Handler.cxx
+++ b/writerfilter/source/ooxml/Handler.cxx
@@ -236,14 +236,21 @@ void OOXMLHeaderHandler::sprm(Sprm & /*sprm*/)
/*
class OOXMLBreakHandler
*/
-OOXMLBreakHandler::OOXMLBreakHandler(Stream &rStream)
+OOXMLBreakHandler::OOXMLBreakHandler(OOXMLFastContextHandler* pContext, Stream &rStream)
: mnType(0),
+ mpFastContext(pContext),
mrStream(rStream)
{
}
OOXMLBreakHandler::~OOXMLBreakHandler()
{
+ if (mpFastContext)
+ {
+ mrStream.props(mpFastContext->getPropertySet().get());
+ mpFastContext->clearProps();
+ }
+
sal_uInt8 tmpBreak[1];
switch (mnType)
{
diff --git a/writerfilter/source/ooxml/Handler.hxx b/writerfilter/source/ooxml/Handler.hxx
index 42ea025538f0..df6673d44318 100644
--- a/writerfilter/source/ooxml/Handler.hxx
+++ b/writerfilter/source/ooxml/Handler.hxx
@@ -111,10 +111,11 @@ public:
class OOXMLBreakHandler : public Properties
{
sal_Int32 mnType;
+ OOXMLFastContextHandler* mpFastContext;
Stream& mrStream;
public:
- explicit OOXMLBreakHandler(Stream& rStream);
+ explicit OOXMLBreakHandler(OOXMLFastContextHandler* pContext, Stream& rStream);
virtual ~OOXMLBreakHandler() override;
virtual void attribute(Id name, Value& val) override;
virtual void sprm(Sprm& sprm) override;
diff --git a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
index aa9de6408202..e6aa15298c05 100644
--- a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
+++ b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
@@ -1117,7 +1117,7 @@ void OOXMLFastContextHandlerProperties::handleBreak()
{
if(isForwardEvents())
{
- OOXMLBreakHandler aBreakHandler(*mpStream);
+ OOXMLBreakHandler aBreakHandler(this, *mpStream);
getPropertySet()->resolve(aBreakHandler);
}
}
diff --git a/writerfilter/source/ooxml/OOXMLParserState.cxx b/writerfilter/source/ooxml/OOXMLParserState.cxx
index 3d35cbb9deac..a11afde8fb37 100644
--- a/writerfilter/source/ooxml/OOXMLParserState.cxx
+++ b/writerfilter/source/ooxml/OOXMLParserState.cxx
@@ -212,7 +212,7 @@ void OOXMLParserState::resolvePostponedBreak(Stream & rStream)
{
for (const auto & rBreak: mvPostponedBreaks)
{
- OOXMLBreakHandler aBreakHandler(rStream);
+ OOXMLBreakHandler aBreakHandler(nullptr, rStream);
rBreak->resolve(aBreakHandler);
}
mvPostponedBreaks.clear();