sw/inc/unoprnms.hxx | 1 sw/inc/unotextcursor.hxx | 1 sw/qa/core/unocore/data/paragraph-marker-formatted-run.docx |binary sw/qa/core/unocore/data/paragraph-marker.docx |binary sw/qa/core/unocore/unocore.cxx | 38 +++++ sw/qa/extras/ooxmlexport/ooxmlexport2.cxx | 3 sw/source/core/inc/unoport.hxx | 7 sw/source/core/text/xmldump.cxx | 5 sw/source/core/unocore/unoobj.cxx | 88 +++++++++++- sw/source/core/unocore/unoport.cxx | 57 ++++++- sw/source/core/unocore/unoportenum.cxx | 5 xmloff/source/text/txtparai.cxx | 17 ++ 12 files changed, 207 insertions(+), 15 deletions(-)
New commits: commit 4634a27dd6f762168b3d7820326611b20b7d385c Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Tue Dec 20 12:14:16 2022 +0100 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Thu Dec 22 06:12:55 2022 +0000 sw: fix ODT import of paragraph marker formatting The DOCX bugdoc had a numbering portion which was not bold, even if all characters in the paragrpah was bold. This was rendered fine, but once it was saved to ODT + reloaded, the numbering portion became bold as well, which is buggy. What happens here is that there is one span that covers the entire paragraph (and is bold) and there is an empty span at paragraph end (which is not bold), so the ODT export is fine. But once we import it back, the first span gets "upgraded" to paragraph-level formatting (because SetAttrMode::NOFORMATATTR is not used when inserting the hints) and the second span is not mapped back to the original RES_PARATR_LIST_AUTOFMT in the text node. Fix the problem by 1) improving SwXTextCursor::setPropertyValue() to work with SetAttrMode::NOFORMATATTR when multiple spans are inserted and by 2) extending SwUnoCursorHelper::SetCursorPropertyValue() to create RES_PARATR_LIST_AUTOFMT for empty spans at paragraph end. This way the original doc model and the one created after ODT export + import is much closer to each other. This builds on top of 6249858a8972aef077e0249bd93cfe8f01bce4d6 (sw: ODT import/export of DOCX's paragraph marker formatting, 2022-12-19), previously the ODT export and import of paragraph marker formatting was completely missing. (cherry picked from commit 1feb1aa08421f9d0934ab65ce94cf6054818c0f3) Also includes commit de235fe13a2e5a4db043f44e6d5636e308f2b979 (sw layout xml dump: show numbering portion weight, 2022-12-19). Change-Id: I139e11217dcbc18744aeeb80638090781aa74933 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144676 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/sw/inc/unoprnms.hxx b/sw/inc/unoprnms.hxx index c3a7d97b32e8..c59fc4813721 100644 --- a/sw/inc/unoprnms.hxx +++ b/sw/inc/unoprnms.hxx @@ -506,6 +506,7 @@ #define UNO_NAME_IS_SKIP_HIDDEN_TEXT "IsSkipHiddenText" #define UNO_NAME_IS_SKIP_PROTECTED_TEXT "IsSkipProtectedText" #define UNO_NAME_RESET_PARAGRAPH_LIST_ATTRIBUTES "ResetParagraphListAttributes" +#define UNO_NAME_NO_FORMAT_ATTR "NoFormatAttr" #define UNO_NAME_DOCUMENT_INDEX_MARKS "DocumentIndexMarks" #define UNO_NAME_FOOTNOTE_IS_COLLECT_AT_TEXT_END "FootnoteIsCollectAtTextEnd" #define UNO_NAME_FOOTNOTE_IS_RESTART_NUMBERING "FootnoteIsRestartNumbering" diff --git a/sw/inc/unotextcursor.hxx b/sw/inc/unotextcursor.hxx index b055f2d64504..25c71effa57c 100644 --- a/sw/inc/unotextcursor.hxx +++ b/sw/inc/unotextcursor.hxx @@ -76,6 +76,7 @@ private: const CursorType m_eType; const css::uno::Reference< css::text::XText > m_xParentText; sw::UnoCursorPointer m_pUnoCursor; + SetAttrMode m_nAttrMode = SetAttrMode::DEFAULT; SwUnoCursor& GetCursorOrThrow() { if(!m_pUnoCursor) diff --git a/sw/qa/core/unocore/data/paragraph-marker-formatted-run.docx b/sw/qa/core/unocore/data/paragraph-marker-formatted-run.docx new file mode 100644 index 000000000000..c0635c157cc9 Binary files /dev/null and b/sw/qa/core/unocore/data/paragraph-marker-formatted-run.docx differ diff --git a/sw/qa/core/unocore/unocore.cxx b/sw/qa/core/unocore/unocore.cxx index 220e946fe206..cce4d837ca5a 100644 --- a/sw/qa/core/unocore/unocore.cxx +++ b/sw/qa/core/unocore/unocore.cxx @@ -698,6 +698,25 @@ CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, testParagraphMarkerODFExport) getXPath(pXmlDoc, "//Special[@nType='PortionType::Number']/SwFont", "color")); } +CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, testParagraphMarkerFormattedRun) +{ + // Given a document with a bold run and non-bold paragraph marker: + load(DATA_DIRECTORY, "paragraph-marker-formatted-run.docx"); + + // When saving that as ODT + reload: + reload("writer8", nullptr); + + // Then make sure that the numbering portion is still non-bold, matching Word: + xmlDocUniquePtr pXmlDoc = parseLayoutDump(); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: normal + // - Actual : bold + // i.e. the numbering portion was bold, while its weight should be normal. + CPPUNIT_ASSERT_EQUAL( + OUString("normal"), + getXPath(pXmlDoc, "//Special[@nType='PortionType::Number']/SwFont", "weight")); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/text/xmldump.cxx b/sw/source/core/text/xmldump.cxx index 966ee8ac1eee..9c8a5ba91c73 100644 --- a/sw/source/core/text/xmldump.cxx +++ b/sw/source/core/text/xmldump.cxx @@ -637,6 +637,11 @@ void SwFont::dumpAsXml(xmlTextWriterPtr writer) const (void)xmlTextWriterWriteFormatAttribute(writer, BAD_CAST("ptr"), "%p", this); // do not use Color::AsRGBHexString() as that omits the transparency (void)xmlTextWriterWriteFormatAttribute(writer, BAD_CAST("color"), "%08" SAL_PRIxUINT32, sal_uInt32(GetColor())); + { + std::stringstream ss; + ss << GetWeight(); + (void)xmlTextWriterWriteAttribute(writer, BAD_CAST("weight"), BAD_CAST(ss.str().c_str())); + } (void)xmlTextWriterEndElement(writer); } diff --git a/sw/source/core/unocore/unoobj.cxx b/sw/source/core/unocore/unoobj.cxx index a33a7d028688..f1c7e7528fd3 100644 --- a/sw/source/core/unocore/unoobj.cxx +++ b/sw/source/core/unocore/unoobj.cxx @@ -227,6 +227,57 @@ lcl_setAutoStyle(IStyleAccess & rStyleAccess, const uno::Any & rValue, rSet.Put(aFormat); }; +/// Tries to map rValue to RES_PARATR_LIST_AUTOFMT on the current paragraph, returns true on +/// success. +static bool lcl_setListAutoStyle(SwPaM& rPam, const uno::Any& rValue, SfxItemSet& rItemSet) +{ + // See if this is an empty range at the end of a paragraph. + if (rPam.Start()->nNode.GetIndex() != rPam.End()->nNode.GetIndex()) + { + return false; + } + + if (rPam.Start()->nContent.GetIndex() != rPam.End()->nContent.GetIndex()) + { + return false; + } + + SwTextNode* pTextNode = rPam.GetNode().GetTextNode(); + if (!pTextNode) + { + return false; + } + + if (rPam.Start()->nContent.GetIndex() != pTextNode->Len()) + { + return false; + } + + // Look up the style content based on the name. + OUString sStyle; + if (!(rValue >>= sStyle)) + { + return false; + } + + IStyleAccess& rStyleAccess = rPam.GetDoc().GetIStyleAccess(); + std::shared_ptr<SfxItemSet> pStyle + = rStyleAccess.getByName(sStyle, IStyleAccess::AUTO_STYLE_CHAR); + if (!pStyle) + { + return false; + } + + // Set the style on the text node. + SwFormatAutoFormat aItem(RES_PARATR_LIST_AUTOFMT); + aItem.SetStyleHandle(pStyle); + pTextNode->SetAttr(aItem); + // Clear the style from the hints array. Without clearing, it would contain some style which + // happened to be there previously. + rItemSet.ClearItem(RES_TXTATR_AUTOFMT); + return true; +} + void SwUnoCursorHelper::SetTextFormatColl(const uno::Any & rAny, SwPaM & rPaM) { @@ -445,6 +496,11 @@ SwUnoCursorHelper::SetCursorPropertyValue( lcl_setCharStyle(rPam.GetDoc(), rValue, rItemSet); break; case RES_TXTATR_AUTOFMT: + if (lcl_setListAutoStyle(rPam, rValue, rItemSet)) + { + break; + } + lcl_setAutoStyle(rPam.GetDoc().GetIStyleAccess(), rValue, rItemSet, false); break; @@ -1889,7 +1945,8 @@ SwUnoCursorHelper::GetPropertyStates( if(!pEntry) { if (pNames[i] == UNO_NAME_IS_SKIP_HIDDEN_TEXT || - pNames[i] == UNO_NAME_IS_SKIP_PROTECTED_TEXT) + pNames[i] == UNO_NAME_IS_SKIP_PROTECTED_TEXT || + pNames[i] == UNO_NAME_NO_FORMAT_ATTR) { pStates[i] = beans::PropertyState_DEFAULT_VALUE; continue; @@ -2082,6 +2139,7 @@ SwXTextCursor::getPropertySetInfo() { { u"" UNO_NAME_IS_SKIP_HIDDEN_TEXT, FN_SKIP_HIDDEN_TEXT, cppu::UnoType<bool>::get(), PROPERTY_NONE, 0}, { u"" UNO_NAME_IS_SKIP_PROTECTED_TEXT, FN_SKIP_PROTECTED_TEXT, cppu::UnoType<bool>::get(), PROPERTY_NONE, 0}, + { u"" UNO_NAME_NO_FORMAT_ATTR, 0, cppu::UnoType<bool>::get(), PROPERTY_NONE, 0}, { u"", 0, css::uno::Type(), 0, 0 } }; const uno::Reference< beans::XPropertySetInfo > xInfo = @@ -2130,10 +2188,26 @@ SwXTextCursor::setPropertyValue( pTextNode->ResetAttr(RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END); } } + else if (rPropertyName == UNO_NAME_NO_FORMAT_ATTR) + { + bool bSet(false); + if (!(rValue >>= bSet)) + { + throw lang::IllegalArgumentException(); + } + if (bSet) + { + m_nAttrMode = SetAttrMode::NOFORMATATTR; + } + else + { + m_nAttrMode = SetAttrMode::DEFAULT; + } + } else { SwUnoCursorHelper::SetPropertyValue(rUnoCursor, - m_rPropSet, rPropertyName, rValue); + m_rPropSet, rPropertyName, rValue, m_nAttrMode); } } @@ -2446,7 +2520,8 @@ SwXTextCursor::getPropertyDefaults( if (!pEntry) { if (pNames[i] == UNO_NAME_IS_SKIP_HIDDEN_TEXT || - pNames[i] == UNO_NAME_IS_SKIP_PROTECTED_TEXT) + pNames[i] == UNO_NAME_IS_SKIP_PROTECTED_TEXT || + pNames[i] == UNO_NAME_NO_FORMAT_ATTR) { continue; } diff --git a/xmloff/source/text/txtparai.cxx b/xmloff/source/text/txtparai.cxx index 5a37d1e46894..e0b8c8099ee5 100644 --- a/xmloff/source/text/txtparai.cxx +++ b/xmloff/source/text/txtparai.cxx @@ -1821,6 +1821,19 @@ void XMLParaContext::endFastElement(sal_Int32 ) if (m_xHints) { + bool bSetNoFormatAttr = false; + uno::Reference<beans::XPropertySet> xCursorProps(xAttrCursor, uno::UNO_QUERY); + if (m_xHints->GetHints().size() > 1) + { + // We have multiple hints, 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(); @@ -1960,6 +1973,10 @@ void XMLParaContext::endFastElement(sal_Int32 ) break; } } + if (bSetNoFormatAttr) + { + xCursorProps->setPropertyValue("NoFormatAttr", uno::Any(false)); + } } m_xHints.reset(); } commit 3998b98749739b2c499ffc4d83188e1034b66750 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Mon Dec 19 08:47:18 2022 +0100 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Thu Dec 22 06:12:45 2022 +0000 sw: ODT import/export of DOCX's paragraph marker formatting The bugdoc had a numbering, where the paragraph marker was explicitly formatted to a custom sans font, and this font is also used for the numbering portion's font. This was imported from DOCX correctly, but once you save to ODT and reload, the font used in the numbering portion changed from sans to serif, which is incorrect. The reason for this seems to be that earlier 5ba30f588d6e41a13d68b1461345fca7a7ca61ac (tdf#64222 sw: better DOCX import/export of paragraph marker formatting, 2019-09-06) introduced support for storing this paragraph marker formatting in RES_PARATR_LIST_AUTOFMT, but this was lost on ODT export / import. Fix the problem by 1) adding the autostyle to the autostyle pool, so the font gets written when writing automatic char styles 2) extending SwXTextPortion to have a mode where it exposes the RES_PARATR_LIST_AUTOFMT of the current text node and 3) improving lcl_CreatePortions() to expose a trailing empty text portion that works with these properties. This also required adjusting CppunitTest_sw_ooxmlexport2's testFdo64238_b, which explicitly asserted that the format of the paragraph marker is not exposed in the UNO API text portion enumeration. An additional improvement would be to go with a more explicit markup in the ODT output for RES_PARATR_LIST_AUTOFMT, but we would need to decide what name to use there, since currently we call this paragraph marker formatting RES_PARATR_LIST_AUTOFMT / ListAutoFormat, and somewhat confusingly this is primarily about paragraph marker formatting, not lists / numberings (that is just a consequence). Change-Id: I19c7eed19c6fc85c251ef87a5181c0719a0a382c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144447 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins (cherry picked from commit 6249858a8972aef077e0249bd93cfe8f01bce4d6) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144491 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144675 Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/sw/qa/core/unocore/data/paragraph-marker.docx b/sw/qa/core/unocore/data/paragraph-marker.docx new file mode 100644 index 000000000000..8dac2d96c76d Binary files /dev/null and b/sw/qa/core/unocore/data/paragraph-marker.docx differ diff --git a/sw/qa/core/unocore/unocore.cxx b/sw/qa/core/unocore/unocore.cxx index bd2385d1eb54..220e946fe206 100644 --- a/sw/qa/core/unocore/unocore.cxx +++ b/sw/qa/core/unocore/unocore.cxx @@ -679,6 +679,25 @@ CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, testListIdState) CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DIRECT_VALUE, eState); } +CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, testParagraphMarkerODFExport) +{ + // Given a document with a red numbering portion, from the paragraph marker's format: + load(DATA_DIRECTORY, "paragraph-marker.docx"); + + // When saving that as ODT + reload: + reload("writer8", nullptr); + + // Then make sure that it still has the correct color: + xmlDocUniquePtr pXmlDoc = parseLayoutDump(); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 00ff0000 (COL_LIGHTRED) + // - Actual : ffffffff (COL_AUTO) + // i.e. the custom "red" color was lost as RES_PARATR_LIST_AUTOFMT was not serialized to ODT. + CPPUNIT_ASSERT_EQUAL( + OUString("00ff0000"), + getXPath(pXmlDoc, "//Special[@nType='PortionType::Number']/SwFont", "color")); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport2.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport2.cxx index 48cec2f2cca2..e8bca2ab4740 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport2.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport2.cxx @@ -837,7 +837,8 @@ DECLARE_OOXMLEXPORT_TEST(testFdo64238_b, "fdo64238_b.docx") xRunEnum->nextElement(); numOfRuns++; } - CPPUNIT_ASSERT_EQUAL(sal_Int32(5), numOfRuns); + // "This is the ", "ODD", " [", "LEFT", "] header" and the colored paragraph marker + CPPUNIT_ASSERT_EQUAL(sal_Int32(6), numOfRuns); } DECLARE_OOXMLEXPORT_TEST(testFdo56679, "fdo56679.docx") diff --git a/sw/source/core/inc/unoport.hxx b/sw/source/core/inc/unoport.hxx index 936bc01e0521..4c0098be8681 100644 --- a/sw/source/core/inc/unoport.hxx +++ b/sw/source/core/inc/unoport.hxx @@ -76,7 +76,8 @@ enum SwTextPortionType PORTION_ANNOTATION, PORTION_ANNOTATION_END, PORTION_LINEBREAK, - PORTION_CONTENT_CONTROL + PORTION_CONTENT_CONTROL, + PORTION_LIST_AUTOFMT }; class SwXTextPortion : public cppu::WeakImplHelper @@ -123,6 +124,10 @@ private: bool m_bIsCollapsed; + /// Expose the paragraph's RES_PARATR_LIST_AUTOFMT, not the char props of the underlying (empty) + /// text. + bool m_bIsListAutoFormat; + void init(const SwUnoCursor* pPortionCursor); protected: diff --git a/sw/source/core/unocore/unoobj.cxx b/sw/source/core/unocore/unoobj.cxx index 3d4cf5dfe16a..a33a7d028688 100644 --- a/sw/source/core/unocore/unoobj.cxx +++ b/sw/source/core/unocore/unoobj.cxx @@ -542,10 +542,13 @@ SwUnoCursorHelper::SetCursorPropertyValue( rPropSet.setPropertyValue(*pEntry, prop.Value, items); } + IStyleAccess& rStyleAccess = rPam.GetDoc().GetIStyleAccess(); + // Add it to the autostyle pool, needed by the ODT export. + const std::shared_ptr<SfxItemSet> pAutoStyle + = rStyleAccess.getAutomaticStyle(items, IStyleAccess::AUTO_STYLE_CHAR); SwFormatAutoFormat item(RES_PARATR_LIST_AUTOFMT); - // TODO: for ODF export we'd need to add it to the autostyle pool // note: paragraph auto styles have ParaStyleName property for the parent style; character auto styles currently do not because there's a separate hint, but for this it would be a good way to add it in order to export it as style:parent-style-name, see XMLTextParagraphExport::Add() - item.SetStyleHandle(std::make_shared<SfxItemSet>(items)); + item.SetStyleHandle(pAutoStyle); pTextNd->SetAttr(item); } } diff --git a/sw/source/core/unocore/unoport.cxx b/sw/source/core/unocore/unoport.cxx index fa8b93eb84de..9988bd6cfff8 100644 --- a/sw/source/core/unocore/unoport.cxx +++ b/sw/source/core/unocore/unoport.cxx @@ -70,9 +70,14 @@ SwXTextPortion::SwXTextPortion( : PROPERTY_MAP_TEXTPORTION_EXTENSIONS)) , m_xParentText(rParent) , m_pFrameFormat(nullptr) - , m_ePortionType(eType) + , m_ePortionType(eType != PORTION_LIST_AUTOFMT ? eType : PORTION_TEXT) , m_bIsCollapsed(false) + , m_bIsListAutoFormat(false) { + if (eType == PORTION_LIST_AUTOFMT) + { + m_bIsListAutoFormat = true; + } init( pPortionCursor); } @@ -86,6 +91,7 @@ SwXTextPortion::SwXTextPortion( , m_pFrameFormat(&rFormat) , m_ePortionType(PORTION_FRAME) , m_bIsCollapsed(false) + , m_bIsListAutoFormat(false) { StartListening(rFormat.GetNotifier()); init( pPortionCursor); @@ -107,6 +113,7 @@ SwXTextPortion::SwXTextPortion( , m_pFrameFormat(nullptr) , m_ePortionType( bIsEnd ? PORTION_RUBY_END : PORTION_RUBY_START ) , m_bIsCollapsed(false) + , m_bIsListAutoFormat(false) { init( pPortionCursor); @@ -363,8 +370,23 @@ void SwXTextPortion::GetPropertyValue( break; default: beans::PropertyState eTemp; - bool bDone = SwUnoCursorHelper::getCursorPropertyValue( - rEntry, *pUnoCursor, &rVal, eTemp ); + bool bDone = false; + if (m_bIsListAutoFormat) + { + SwTextNode* pTextNode = pUnoCursor->GetNode().GetTextNode(); + std::shared_ptr<SfxItemSet> pListSet + = pTextNode->GetAttr(RES_PARATR_LIST_AUTOFMT).GetStyleHandle(); + if (pListSet) + { + m_pPropSet->getPropertyValue(rEntry, *pListSet, rVal); + bDone = true; + } + } + if (!bDone) + { + bDone = SwUnoCursorHelper::getCursorPropertyValue( + rEntry, *pUnoCursor, &rVal, eTemp ); + } if(!bDone) { if(!pSet) @@ -599,11 +621,30 @@ uno::Sequence< beans::GetDirectPropertyTolerantResult > SwXTextPortion::GetPrope const SfxItemPropertyMap& rPropMap = m_pPropSet->getPropertyMap(); - uno::Sequence< beans::PropertyState > aPropertyStates = - SwUnoCursorHelper::GetPropertyStates( - rUnoCursor, *m_pPropSet, - rPropertyNames, - SW_PROPERTY_STATE_CALLER_SWX_TEXT_PORTION_TOLERANT ); + uno::Sequence< beans::PropertyState > aPropertyStates; + if (m_bIsListAutoFormat) + { + SwTextNode* pTextNode = rUnoCursor.GetNode().GetTextNode(); + std::shared_ptr<SfxItemSet> pListSet + = pTextNode->GetAttr(RES_PARATR_LIST_AUTOFMT).GetStyleHandle(); + if (pListSet) + { + std::vector<beans::PropertyState> aStates; + for (const auto& rPropertyName : rPropertyNames) + { + aStates.push_back(m_pPropSet->getPropertyState(rPropertyName, *pListSet)); + } + aPropertyStates = comphelper::containerToSequence(aStates); + } + } + if (!aPropertyStates.hasElements()) + { + aPropertyStates = + SwUnoCursorHelper::GetPropertyStates( + rUnoCursor, *m_pPropSet, + rPropertyNames, + SW_PROPERTY_STATE_CALLER_SWX_TEXT_PORTION_TOLERANT ); + } const beans::PropertyState* pPropertyStates = aPropertyStates.getConstArray(); for (sal_Int32 i = 0; i < nProps; ++i) diff --git a/sw/source/core/unocore/unoportenum.cxx b/sw/source/core/unocore/unoportenum.cxx index f4ddd69bf862..32b17f781f93 100644 --- a/sw/source/core/unocore/unoportenum.cxx +++ b/sw/source/core/unocore/unoportenum.cxx @@ -1509,6 +1509,11 @@ static void lcl_CreatePortions( // text portion because there may be a hyperlink attribute xRef = new SwXTextPortion(pUnoCursor, i_xParentText, PORTION_TEXT); } + else if (bAtEnd && !xRef.is() && pTextNode->GetSwAttrSet().HasItem(RES_PARATR_LIST_AUTOFMT)) + { + // We have explicit paragraph marker formatting, export it. + xRef = new SwXTextPortion(pUnoCursor, i_xParentText, PORTION_LIST_AUTOFMT); + } else if (bAtEnd && !xRef.is() && pHints) { // See if there is an empty autofmt at the paragraph end. If so, export it, since that