diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2022-01-28 13:38:20 +0100 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2022-01-28 19:15:37 +0100 |
commit | 8bac48991857d222f0e8f0c07b8c4e06649e1632 (patch) | |
tree | afda78d51f88b78eb84b5b8989b3331ebfdad2ca /writerfilter | |
parent | 8c558549b7dc3348da207627663824043eed6204 (diff) |
DOCX import: handle a subset of <w:ptab w:alignment="left">
The case when we can map it to a line break. This way the page number is
visually inside the rectangle shape that is behind the field.
The test intentionally uses \n as-is for line-break, because
SwASCWriter::WriteStream() uses \n in the LINEEND_LF case even on
Windows (and not SAL_NEWLINE_STRING), while SAL_NEWLINE_STRING is used
for paragraph-break.
Change-Id: Ic85e57b2391bfac73507727b17240f4d85fc2698
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/129059
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
Diffstat (limited to 'writerfilter')
-rw-r--r-- | writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx | 26 | ||||
-rw-r--r-- | writerfilter/qa/cppunittests/dmapper/data/ptab.docx | bin | 0 -> 15861 bytes | |||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper.cxx | 2 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.cxx | 56 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.hxx | 3 |
5 files changed, 87 insertions, 0 deletions
diff --git a/writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx b/writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx index 3719a09e3323..c0468d9d55cc 100644 --- a/writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx @@ -19,6 +19,7 @@ #include <com/sun/star/text/XTextTablesSupplier.hpp> #include <com/sun/star/text/XTextTable.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/style/XStyleFamiliesSupplier.hpp> #include <vcl/scheduler.hxx> @@ -230,6 +231,31 @@ CPPUNIT_TEST_FIXTURE(Test, testChartZOrder) // of the shape. CPPUNIT_ASSERT(xChart->supportsService("com.sun.star.text.TextEmbeddedObject")); } + +CPPUNIT_TEST_FIXTURE(Test, testPTab) +{ + // Given a document that has a <w:ptab> to render a linebreak: + OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "ptab.docx"; + + // When opening that file: + getComponent() = loadFromDesktop(aURL); + + // Then make sure that the Writer doc model contains that linebreak: + uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(getComponent(), + uno::UNO_QUERY); + uno::Reference<container::XNameAccess> xStyleFamilies + = xStyleFamiliesSupplier->getStyleFamilies(); + uno::Reference<container::XNameAccess> xStyleFamily(xStyleFamilies->getByName("PageStyles"), + uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xStyle(xStyleFamily->getByName("Standard"), uno::UNO_QUERY); + auto xFooter = xStyle->getPropertyValue("FooterText").get<uno::Reference<text::XTextRange>>(); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: <space><newline>1\n + // - Actual: <space><tab>1\n + // i.e. the layout height of the footer text was incorrect, the page number field was not + // visually inside the background shape. + CPPUNIT_ASSERT_EQUAL(OUString(" \n1" SAL_NEWLINE_STRING), xFooter->getString()); +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerfilter/qa/cppunittests/dmapper/data/ptab.docx b/writerfilter/qa/cppunittests/dmapper/data/ptab.docx Binary files differnew file mode 100644 index 000000000000..d1ae18a27a55 --- /dev/null +++ b/writerfilter/qa/cppunittests/dmapper/data/ptab.docx diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx index e8b5a3f40e5b..6a18d8d12da0 100644 --- a/writerfilter/source/dmapper/DomainMapper.cxx +++ b/writerfilter/source/dmapper/DomainMapper.cxx @@ -1167,7 +1167,9 @@ void DomainMapper::lcl_attribute(Id nName, Value & val) break; case NS_ooxml::LN_CT_PTab_leader: case NS_ooxml::LN_CT_PTab_relativeTo: + break; case NS_ooxml::LN_CT_PTab_alignment: + m_pImpl->HandlePTab(nIntValue); break; case NS_ooxml::LN_CT_Cnf_lastRowLastColumn: m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "lastRowLastColumn", OUString::number(nIntValue)); diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index f0902918e0ff..952d225f52f7 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -3868,6 +3868,62 @@ void DomainMapper_Impl::HandleAltChunk(const OUString& rStreamName) } } +void DomainMapper_Impl::HandlePTab(sal_Int32 nAlignment) +{ + // We only handle the case when the line already has content, so the left-aligned ptab is + // equivalent to a line break. + if (nAlignment != NS_ooxml::LN_Value_ST_PTabAlignment_left) + { + return; + } + + if (m_aTextAppendStack.empty()) + { + return; + } + + uno::Reference<text::XTextAppend> xTextAppend = m_aTextAppendStack.top().xTextAppend; + if (!xTextAppend.is()) + { + return; + } + + uno::Reference<css::text::XTextRange> xInsertPosition + = m_aTextAppendStack.top().xInsertPosition; + if (!xInsertPosition.is()) + { + xInsertPosition = xTextAppend->getEnd(); + } + uno::Reference<text::XTextCursor> xCursor + = xTextAppend->createTextCursorByRange(xInsertPosition); + + // Assume that we just inserted a tab character. + xCursor->goLeft(1, true); + if (xCursor->getString() != "\t") + { + return; + } + + // Assume that there is some content before the tab character. + uno::Reference<text::XParagraphCursor> xParagraphCursor(xCursor, uno::UNO_QUERY); + if (!xParagraphCursor.is()) + { + return; + } + + xCursor->collapseToStart(); + xParagraphCursor->gotoStartOfParagraph(true); + if (xCursor->isCollapsed()) + { + return; + } + + // Then select the tab again and replace with a line break. + xCursor->collapseToEnd(); + xCursor->goRight(1, true); + xTextAppend->insertControlCharacter(xCursor, text::ControlCharacter::LINE_BREAK, true); +} + 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 7238d129f766..7ede5cb2f91d 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx @@ -1164,6 +1164,9 @@ public: /// Handles <w:altChunk>. void HandleAltChunk(const OUString& rStreamName); + /// Handles <w:ptab>. + void HandlePTab(sal_Int32 nAlignment); + void commentProps(const OUString& sId, const CommentProperties& rProps); private: |