sw/qa/extras/ww8export/data/clearing-break.doc |binary sw/qa/extras/ww8export/ww8export3.cxx | 26 ++++++++++++++++ sw/source/filter/ww8/ww8par.hxx | 4 ++ sw/source/filter/ww8/ww8par6.cxx | 40 +++++++++++++++++++++++++ 4 files changed, 70 insertions(+)
New commits: commit 31ac4edf2ec83c9f6ec475ad74e5fd94a0c8b1ca Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Thu Mar 17 10:15:11 2022 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Thu Mar 17 10:58:20 2022 +0100 sw clearing breaks: add DOC import Map sprmCLbcCRJ's LBCOperand to SwLineBreakClear. Change-Id: Ie6a114bcd90a9442295815da68f6b0a9616c3210 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131697 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins diff --git a/sw/qa/extras/ww8export/data/clearing-break.doc b/sw/qa/extras/ww8export/data/clearing-break.doc new file mode 100644 index 000000000000..87b51128db3f Binary files /dev/null and b/sw/qa/extras/ww8export/data/clearing-break.doc differ diff --git a/sw/qa/extras/ww8export/ww8export3.cxx b/sw/qa/extras/ww8export/ww8export3.cxx index feb759312d15..e0eb32ee9f1b 100644 --- a/sw/qa/extras/ww8export/ww8export3.cxx +++ b/sw/qa/extras/ww8export/ww8export3.cxx @@ -995,6 +995,32 @@ DECLARE_WW8EXPORT_TEST(testTdf79186_noLayoutInCell, "tdf79186_noLayoutInCell.odt CPPUNIT_ASSERT(!getProperty<bool>(getShape(1), "IsFollowingTextFlow")); } +CPPUNIT_TEST_FIXTURE(Test, testClearingBreak) +{ + // Given a document with a clearing break: + // When loading that file: + load(mpTestDocumentPath, "clearing-break.doc"); + + // Then make sure that the clear property of the break is not ignored: + uno::Reference<container::XEnumerationAccess> xParagraph(getParagraph(1), 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); +} CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/filter/ww8/ww8par.hxx b/sw/source/filter/ww8/ww8par.hxx index 204a4de3efac..46198b105021 100644 --- a/sw/source/filter/ww8/ww8par.hxx +++ b/sw/source/filter/ww8/ww8par.hxx @@ -108,6 +108,7 @@ class GDIMetaFile; struct ESelection; class SfxItemSet; class OutlinerParaObject; +enum class SwLineBreakClear; namespace com::sun::star{ namespace beans{ class XPropertySet;} @@ -1174,6 +1175,8 @@ private: */ std::deque<FootnoteDescriptor> m_aFootnoteStack; + std::optional<SwLineBreakClear> m_oLineBreakClear; + /* A queue of the ms sections in the document */ @@ -1775,6 +1778,7 @@ public: // really private, but can only be done public void Read_ParaAutoBefore(sal_uInt16 , const sal_uInt8 *pData, short nLen); void Read_ParaAutoAfter(sal_uInt16 , const sal_uInt8 *pData, short nLen); void Read_ParaContextualSpacing( sal_uInt16 nId, const sal_uInt8* pData, short nLen ); + void Read_LineBreakClear(sal_uInt16 nId, const sal_uInt8* pData, short nLen); void Read_LineSpace( sal_uInt16, const sal_uInt8*, short nLen ); void SetRelativeJustify( bool bRel ); diff --git a/sw/source/filter/ww8/ww8par6.cxx b/sw/source/filter/ww8/ww8par6.cxx index 7f47d529656d..2352dfd1c12e 100644 --- a/sw/source/filter/ww8/ww8par6.cxx +++ b/sw/source/filter/ww8/ww8par6.cxx @@ -99,6 +99,7 @@ #include "ww8graf.hxx" #include <fmtwrapinfluenceonobjpos.hxx> +#include <textlinebreak.hxx> using namespace sw::util; using namespace sw::types; @@ -4541,6 +4542,44 @@ void SwWW8ImplReader::Read_ParaContextualSpacing( sal_uInt16, const sal_uInt8* p NewAttr( aUL ); } +void SwWW8ImplReader::Read_LineBreakClear(sal_uInt16 /*nId*/, const sal_uInt8* pData, short nLen) +{ + if (nLen == -1 && m_oLineBreakClear.has_value()) + { + SwTextNode* pText = m_pPaM->GetNode().GetTextNode(); + sal_Int32 nPos = m_pPaM->GetPoint()->nContent.GetIndex(); + if (!pText || !nPos) + { + // There should have been a linebreak char. + return; + } + + // Replace the linebreak char with a clearing break. + --nPos; + m_pPaM->SetMark(); + --m_pPaM->GetMark()->nContent; + m_rDoc.getIDocumentContentOperations().DeleteRange(*m_pPaM); + m_pPaM->DeleteMark(); + SwFormatLineBreak aLineBreak(*m_oLineBreakClear); + m_oLineBreakClear.reset(); + pText->InsertItem(aLineBreak, nPos, nPos); + } + + if (nLen < 1) + { + return; + } + + sal_uInt8 nClear = pData[0]; + if (nClear > 3) + { + return; + } + + auto eClear = static_cast<SwLineBreakClear>(nClear); + m_oLineBreakClear = eClear; +} + void SwWW8ImplReader::Read_IdctHint( sal_uInt16, const sal_uInt8* pData, short nLen ) { // sprmcidcthint (opcode 0x286f) specifies a script bias for the text in the run. @@ -6104,6 +6143,7 @@ static const wwSprmDispatcher *GetWW8SprmDispatcher() {NS_sprm::PFDyaBeforeAuto::val, &SwWW8ImplReader::Read_ParaAutoBefore}, {NS_sprm::PFDyaAfterAuto::val, &SwWW8ImplReader::Read_ParaAutoAfter}, {NS_sprm::PFContextualSpacing::val, &SwWW8ImplReader::Read_ParaContextualSpacing}, + {NS_sprm::CLbcCRJ::val, &SwWW8ImplReader::Read_LineBreakClear}, }; static wwSprmDispatcher aSprmSrch(aSprms, SAL_N_ELEMENTS(aSprms));