sw/inc/IDocumentSettingAccess.hxx                |    1 
 sw/qa/extras/layout/data/A020-min.rtf            |   30 ++++++++++++
 sw/qa/extras/layout/layout2.cxx                  |   49 ++++++++++++++++++++
 sw/qa/extras/ooxmlexport/data/fdo74110.docx      |binary
 sw/source/core/doc/DocumentSettingManager.cxx    |   12 +++++
 sw/source/core/inc/DocumentSettingManager.hxx    |    3 -
 sw/source/core/text/atrstck.cxx                  |    8 ++-
 sw/source/core/text/itratr.cxx                   |   55 ++++++++++++++++++++++-
 sw/source/core/text/itratr.hxx                   |    5 ++
 sw/source/core/text/porlay.cxx                   |   19 +++++++
 sw/source/core/text/txtfrm.cxx                   |   17 +++++++
 sw/source/filter/ww8/ww8par.cxx                  |    2 
 sw/source/filter/xml/xmlimp.cxx                  |   10 ----
 sw/source/uibase/uno/SwXDocumentSettings.cxx     |   18 +++++++
 sw/source/writerfilter/dmapper/SettingsTable.cxx |    2 
 sw/source/writerfilter/filter/WriterFilter.cxx   |    1 
 16 files changed, 215 insertions(+), 17 deletions(-)

New commits:
commit 7b8cec8322b60673e686660caf875bc71117bbd0
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Tue Sep 24 19:06:55 2024 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Sep 27 18:09:57 2024 +0200

    tdf#162268 sw: ApplyParagraphMarkFormatToEmptyLineAtEndOfParagraph
    
    Commit 2b47fae7e3e23ee7c733708500cb0482ad7f8af1 introduced the
    compatibility setting ApplyTextAttrToEmptyLineAtEndOfParagraph, but that
    was probably a mistake.
    
    What Word is doing there is not applying a text attribute but applying the
    formatting of the paragraph marker; add a new compatibility setting
    ApplyParagraphMarkFormatToEmptyLineAtEndOfParagraph to do this.
    
    Change SwAttrIter to apply the RES_PARATR_LIST_AUTOFMT formatting when
    the position behind the last character is reached, and use it to set the
    height of the last line in SwLineLayout::CalcLine() in case it is empty
    or contains only spaces/tabs.
    
    Frustratingly this requires another change to fdo74110.docx to get rid
    of some odd font that's applied to the paragraph marker.
    
    Also, change SwTextFrame::IsHiddenNow() to take into account paragraph
    marker formatting; if all characters are hidden but the paragraph marker
    isn't hidden, the paragraph is still displayed in Word.
    
    Change-Id: Icccd3e822ad0301ccbe373b50431c3254f691d6e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173880
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/sw/inc/IDocumentSettingAccess.hxx 
b/sw/inc/IDocumentSettingAccess.hxx
index 53fb5bed5e8f..c386259a2952 100644
--- a/sw/inc/IDocumentSettingAccess.hxx
+++ b/sw/inc/IDocumentSettingAccess.hxx
@@ -99,6 +99,7 @@ enum class DocumentSettingId
     // tdf#119908 new paragraph justification
     JUSTIFY_LINES_WITH_SHRINKING,
     APPLY_TEXT_ATTR_TO_EMPTY_LINE_AT_END_OF_PARAGRAPH,
+    APPLY_PARAGRAPH_MARK_FORMAT_TO_EMPTY_LINE_AT_END_OF_PARAGRAPH,
     DO_NOT_MIRROR_RTL_DRAW_OBJS,
     // COMPATIBILITY FLAGS END
     BROWSE_MODE,
diff --git a/sw/qa/extras/layout/data/A020-min.rtf 
b/sw/qa/extras/layout/data/A020-min.rtf
new file mode 100644
index 000000000000..23a1be8eb242
--- /dev/null
+++ b/sw/qa/extras/layout/data/A020-min.rtf
@@ -0,0 +1,30 @@
+{ 
tf1deflang1025nsinsicpg1252\uc1deff1\deff0\stshfdbch0\stshfloch0\stshfhich0\stshfbi0\deflang3079\deflangfe3079
   hemelang3079    hemelangfe0     hemelangcs0
+{onttbl{0bidi romancharset0prq2{\*\panose 02020603050405020304}Times New 
Roman{\*alt Times New Roman};}
+{1bidi swisscharset0prq2{\*\panose 020b0604020202020204}Arial{\*alt 
Arial};}
+}
+{\*\defchp s22 }
+{\*\defpap \ql \li0 i0\sa160\sl259\slmult1\widctlpar\wrapdefaultspalphaspnum
aautodjustright in0\lin0\itap0 }
+
oqfpromote
+{\stylesheet{\ql \li0 i0\widctlpar\wrapdefaultaautodjustright in0\lin0\itap0 
 tlchcs1 f1fs22lang1025 
+\ltrchcs0 1s22\lang1031\langfe3079+{\*+{\s34\ql \li0 i0\widctlpar
+       qc      x4536   qr      x9072\wrapdefaultaautodjustright 
in0\lin0\itap0  tlchcs1 f1fs22lang1025 \ltrchcs0 1
s22\lang1031\langfe3079+dditive  tlchcs1 f1 \ltrchcs0 
1\lang1031\langfe0\langnp1031\langfenp0 \sbasedon10 \slink34 \slocked Kopfzeile 
Zchn;}
+}
+
+\paperw11907\paperh16840\margl1418\margr1418\margt851\margb851\gutter0\ltrsect 
+\deftab708\widowctrltnbjenddoc\hyphhotz425   rackmoves0      
rackformatting1\donotembedsysfont0 elyonvml0\donotembedlingdata1\grfdocevents0
alidatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0
+\showxmlerrors0
oextrasprl\prcolbl+\jcompressiewkind1iewscale100\pgbrdrhead\pgbrdrfoot
olnhtadjtblet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0
+
+\ltrpar \sectd \ltrsect\sbknone\linex0\headery709ootery709+   qc      x4536   
qr      x9072\wrapdefaultaautodjustright in0\lin0\itap0 tlchcs1 
f1fs22lang1025 \ltrchcs0 1s22\lang1031\langfe3079+\line \line 
+\par \line \line \line \line }{ tlchcs1 f1 \ltrchcs0 
+\par }}
+
+\pard\plain \ltrpar\ql \li0 i0\widctlpar\wrapdefaultaautodjustright 
in0\lin0\itap0  tlchcs1 f1fs22lang1025 
+\ltrchcs0 1s22\lang1031\langfe3079+\par
+}
diff --git a/sw/qa/extras/layout/layout2.cxx b/sw/qa/extras/layout/layout2.cxx
index 50f2cba4d986..7e54b860b1b9 100644
--- a/sw/qa/extras/layout/layout2.cxx
+++ b/sw/qa/extras/layout/layout2.cxx
@@ -13,8 +13,10 @@
 #include <com/sun/star/text/XTextTable.hpp>
 #include <com/sun/star/linguistic2/XHyphenator.hpp>
 #include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <com/sun/star/view/XViewSettingsSupplier.hpp>
 #include <com/sun/star/linguistic2/XSpellChecker1.hpp>
 
+#include <comphelper/propertysequence.hxx>
 #include <comphelper/scopeguard.hxx>
 #include <comphelper/sequence.hxx>
 #include <unotools/syslocaleoptions.hxx>
@@ -2203,6 +2205,53 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf137819)
     CPPUNIT_ASSERT(sTextRightSidePosition.toInt32() < 
sShapeRightSidePosition.toInt32());
 }
 
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testParagraphMarkLineHeight)
+{
+    createSwDoc("A020-min.rtf");
+
+    uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
+    uno::Reference<view::XViewSettingsSupplier> xViewSettingsSupplier(
+        xModel->getCurrentController(), uno::UNO_QUERY);
+    uno::Reference<beans::XPropertySet> 
xViewSettings(xViewSettingsSupplier->getViewSettings());
+    uno::Any aOldHidden{ 
xViewSettings->getPropertyValue(u"ShowHiddenCharacters"_ustr) };
+    uno::Any aOldNon{ 
xViewSettings->getPropertyValue(u"ShowNonprintingCharacters"_ustr) };
+    comphelper::ScopeGuard g([&] {
+        xViewSettings->setPropertyValue(u"ShowHiddenCharacters"_ustr, 
aOldHidden);
+        xViewSettings->setPropertyValue(u"ShowNonprintingCharacters"_ustr, 
aOldNon);
+    });
+
+    xViewSettings->setPropertyValue(u"ShowHiddenCharacters"_ustr, 
uno::Any(true));
+    xViewSettings->setPropertyValue(u"ShowNonprintingCharacters"_ustr, 
uno::Any(true));
+
+    {
+        xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+        assertXPath(pXmlDoc, 
"/root/page/header/txt[1]/SwParaPortion/SwLineLayout[1]"_ostr,
+                    "height"_ostr, "184");
+        assertXPath(pXmlDoc, 
"/root/page/header/txt[1]/SwParaPortion/SwLineLayout[2]"_ostr,
+                    "height"_ostr, "184");
+        assertXPath(pXmlDoc, 
"/root/page/header/txt[1]/SwParaPortion/SwLineLayout[3]"_ostr,
+                    "height"_ostr, "184");
+        assertXPath(pXmlDoc, 
"/root/page/header/txt[2]/SwParaPortion/SwLineLayout[1]"_ostr,
+                    "height"_ostr, "184");
+        assertXPath(pXmlDoc, 
"/root/page/header/txt[2]/SwParaPortion/SwLineLayout[2]"_ostr,
+                    "height"_ostr, "184");
+        assertXPath(pXmlDoc, 
"/root/page/header/txt[2]/SwParaPortion/SwLineLayout[3]"_ostr,
+                    "height"_ostr, "184");
+        assertXPath(pXmlDoc, 
"/root/page/header/txt[2]/SwParaPortion/SwLineLayout[4]"_ostr,
+                    "height"_ostr, "184");
+        assertXPath(pXmlDoc, 
"/root/page/header/txt[2]/SwParaPortion/SwLineLayout[5]"_ostr,
+                    "height"_ostr, "253");
+    }
+
+    xViewSettings->setPropertyValue(u"ShowNonprintingCharacters"_ustr, 
uno::Any(false));
+
+    {
+        xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+        assertXPath(pXmlDoc, 
"/root/page/header/txt[1]/SwParaPortion/SwLineLayout[1]"_ostr,
+                    "height"_ostr, "184"); // FIXME should be 253, but better 
than 0
+    }
+}
+
 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf122014)
 {
     createSwDoc("tdf122014.docx");
diff --git a/sw/qa/extras/ooxmlexport/data/fdo74110.docx 
b/sw/qa/extras/ooxmlexport/data/fdo74110.docx
index cda0772c5738..0a3d515e9846 100644
Binary files a/sw/qa/extras/ooxmlexport/data/fdo74110.docx and 
b/sw/qa/extras/ooxmlexport/data/fdo74110.docx differ
diff --git a/sw/source/core/doc/DocumentSettingManager.cxx 
b/sw/source/core/doc/DocumentSettingManager.cxx
index 8015878f2357..26a75dc45628 100644
--- a/sw/source/core/doc/DocumentSettingManager.cxx
+++ b/sw/source/core/doc/DocumentSettingManager.cxx
@@ -259,6 +259,8 @@ bool sw::DocumentSettingManager::get(/*[in]*/ 
DocumentSettingId id) const
         case DocumentSettingId::HYPHENATE_URLS: return mbHyphenateURLs;
         case 
DocumentSettingId::APPLY_TEXT_ATTR_TO_EMPTY_LINE_AT_END_OF_PARAGRAPH:
             return mbApplyTextAttrToEmptyLineAtEndOfParagraph;
+        case 
DocumentSettingId::APPLY_PARAGRAPH_MARK_FORMAT_TO_EMPTY_LINE_AT_END_OF_PARAGRAPH:
+            return mbApplyParagraphMarkFormatToEmptyLineAtEndOfParagraph;
         case DocumentSettingId::DO_NOT_BREAK_WRAPPED_TABLES:
             return mbDoNotBreakWrappedTables;
         case DocumentSettingId::ALLOW_TEXT_AFTER_FLOATING_TABLE_BREAK:
@@ -463,6 +465,11 @@ void sw::DocumentSettingManager::set(/*[in]*/ 
DocumentSettingId id, /*[in]*/ boo
             mbApplyTextAttrToEmptyLineAtEndOfParagraph = value;
             break;
 
+        case 
DocumentSettingId::APPLY_PARAGRAPH_MARK_FORMAT_TO_EMPTY_LINE_AT_END_OF_PARAGRAPH:
+            mbApplyParagraphMarkFormatToEmptyLineAtEndOfParagraph = value;
+            break;
+
+
         case DocumentSettingId::DO_NOT_MIRROR_RTL_DRAW_OBJS:
             mbDoNotMirrorRtlDrawObjs = value;
             break;
@@ -1144,6 +1151,11 @@ void 
sw::DocumentSettingManager::dumpAsXml(xmlTextWriterPtr pWriter) const
                                 
BAD_CAST(OString::boolean(mbApplyTextAttrToEmptyLineAtEndOfParagraph).getStr()));
     (void)xmlTextWriterEndElement(pWriter);
 
+    (void)xmlTextWriterStartElement(pWriter, 
BAD_CAST("mbApplyParagraphMarkFormatToEmptyLineAtEndOfParagraph"));
+    (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"),
+                                
BAD_CAST(OString::boolean(mbApplyParagraphMarkFormatToEmptyLineAtEndOfParagraph).getStr()));
+    (void)xmlTextWriterEndElement(pWriter);
+
     (void)xmlTextWriterStartElement(pWriter, 
BAD_CAST("mbDoNotMirrorRtlDrawObjs"));
     (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"),
                                 
BAD_CAST(OString::boolean(mbDoNotMirrorRtlDrawObjs).getStr()));
diff --git a/sw/source/core/inc/DocumentSettingManager.hxx 
b/sw/source/core/inc/DocumentSettingManager.hxx
index f9e1faf9aacd..9125496cdc17 100644
--- a/sw/source/core/inc/DocumentSettingManager.hxx
+++ b/sw/source/core/inc/DocumentSettingManager.hxx
@@ -178,7 +178,8 @@ class DocumentSettingManager final :
     bool mbDoNotBreakWrappedTables = false;
     bool mbAllowTextAfterFloatingTableBreak = false;
     bool mbJustifyLinesWithShrinking = false;
-    bool mbApplyTextAttrToEmptyLineAtEndOfParagraph = true;
+    bool mbApplyTextAttrToEmptyLineAtEndOfParagraph = false; // this was a 
mistake
+    bool mbApplyParagraphMarkFormatToEmptyLineAtEndOfParagraph = false;
     bool mbDoNotMirrorRtlDrawObjs = false;
     // If this is on as_char flys wrapping will be handled the same like in 
Word
     bool mbNoNumberingShowFollowBy;
diff --git a/sw/source/core/text/atrstck.cxx b/sw/source/core/text/atrstck.cxx
index 85689a2c82a8..7d2b6afddc7f 100644
--- a/sw/source/core/text/atrstck.cxx
+++ b/sw/source/core/text/atrstck.cxx
@@ -341,15 +341,19 @@ void SwAttrHandler::PushAndChg( const SwTextAttr& rAttr, 
SwFont& rFnt )
     // they have to be pushed to each stack they belong to
     if ( RES_TXTATR_INETFMT == rAttr.Which() ||
          RES_TXTATR_CHARFMT == rAttr.Which() ||
+         RES_PARATR_LIST_AUTOFMT == rAttr.Which() ||
          RES_TXTATR_AUTOFMT == rAttr.Which() )
     {
-        const SfxItemSet* pSet = CharFormat::GetItemSet( rAttr.GetAttr() );
+        const SfxItemSet* pSet = rAttr.Which() == RES_PARATR_LIST_AUTOFMT
+            ? 
rAttr.GetAttr().StaticWhichCast(RES_PARATR_LIST_AUTOFMT).GetStyleHandle().get()
+            : CharFormat::GetItemSet( rAttr.GetAttr() );
         if ( !pSet ) return;
 
+        bool const inParent{rAttr.Which() != RES_TXTATR_AUTOFMT && 
rAttr.Which() != RES_PARATR_LIST_AUTOFMT};
         for ( sal_uInt16 i = RES_CHRATR_BEGIN; i < RES_CHRATR_END; i++)
         {
             const SfxPoolItem* pItem;
-            bool bRet = SfxItemState::SET == pSet->GetItemState( i, 
rAttr.Which() != RES_TXTATR_AUTOFMT, &pItem );
+            bool bRet = SfxItemState::SET == pSet->GetItemState(i, inParent, 
&pItem);
 
             if ( bRet )
             {
diff --git a/sw/source/core/text/itratr.cxx b/sw/source/core/text/itratr.cxx
index b002e80610aa..ae38bda0bab3 100644
--- a/sw/source/core/text/itratr.cxx
+++ b/sw/source/core/text/itratr.cxx
@@ -38,6 +38,7 @@
 #include <fmtfld.hxx>
 #include <doc.hxx>
 #include <IDocumentLayoutAccess.hxx>
+#include <IDocumentSettingAccess.hxx>
 #include <txatbase.hxx>
 #include <viewsh.hxx>
 #include <rootfrm.hxx>
@@ -301,7 +302,33 @@ void SwAttrIter::SeekFwd(const sal_Int32 nOldPos, const 
sal_Int32 nNewPos)
         if ( pTextAttr->GetAnyEnd() > nNewPos )  Chg( pTextAttr );
         m_nStartIndex++;
     }
+}
 
+void SwAttrIter::SeekToEnd()
+{
+    if (m_pTextNode->GetDoc().getIDocumentSettingAccess().get(
+            
DocumentSettingId::APPLY_PARAGRAPH_MARK_FORMAT_TO_EMPTY_LINE_AT_END_OF_PARAGRAPH))
+    {
+        SfxItemPool & 
rPool{const_cast<SwAttrPool&>(m_pTextNode->GetDoc().GetAttrPool())};
+        SwFormatAutoFormat const& 
rListAutoFormat{m_pTextNode->GetAttr(RES_PARATR_LIST_AUTOFMT)};
+        std::shared_ptr<SfxItemSet> const 
pSet{rListAutoFormat.GetStyleHandle()};
+        if (!pSet)
+        {
+            return;
+        }
+        if (pSet->HasItem(RES_TXTATR_CHARFMT))
+        {
+            SwFormatCharFormat const& 
rCharFormat{pSet->Get(RES_TXTATR_CHARFMT)};
+            m_pEndCharFormatAttr.reset(new SwTextAttrEnd{
+                    SfxPoolItemHolder{rPool, &rCharFormat}, -1, -1});
+            Chg(m_pEndCharFormatAttr.get());
+        }
+        // note: RES_TXTATR_CHARFMT should be cleared here but it looks like
+        // SwAttrHandler only looks at RES_CHRATR_* anyway
+        m_pEndAutoFormatAttr.reset(new SwTextAttrEnd{
+                SfxPoolItemHolder{rPool, &rListAutoFormat}, -1, -1});
+        Chg(m_pEndAutoFormatAttr.get());
+    }
 }
 
 bool SwAttrIter::Seek(TextFrameIndex const nNewPos)
@@ -368,7 +395,8 @@ bool SwAttrIter::Seek(TextFrameIndex const nNewPos)
                                        m_pMergedPara->mergedText, nullptr, 
nullptr);
             }
         }
-        if (m_pMergedPara || m_pTextNode->GetpSwpHints())
+        // also reset it if the RES_PARATR_LIST_AUTOFMT has been applied!
+        if (m_pMergedPara || m_pTextNode->GetpSwpHints() || 
m_pEndAutoFormatAttr)
         {
             if( m_pRedline )
                 m_pRedline->Clear( nullptr );
@@ -376,6 +404,8 @@ bool SwAttrIter::Seek(TextFrameIndex const nNewPos)
             // reset font to its original state
             m_aAttrHandler.Reset();
             m_aAttrHandler.ResetFont( *m_pFont );
+            m_pEndCharFormatAttr.reset();
+            m_pEndAutoFormatAttr.reset();
 
             if( m_nPropFont )
                 m_pFont->SetProportion( m_nPropFont );
@@ -395,6 +425,24 @@ bool SwAttrIter::Seek(TextFrameIndex const nNewPos)
         }
     }
 
+    bool isToEnd{false};
+    if (m_pMergedPara)
+    {
+        if (!m_pMergedPara->extents.empty())
+        {
+            auto const& rLast{m_pMergedPara->extents.back()};
+            isToEnd = rLast.pNode == newPos.first && rLast.nEnd == 
newPos.second;
+        }
+        else
+        {
+            isToEnd = true;
+        }
+    }
+    else
+    {
+        isToEnd = newPos.second == m_pTextNode->Len();
+    }
+
     if (m_pTextNode->GetpSwpHints())
     {
         if (m_pMergedPara)
@@ -424,6 +472,11 @@ bool SwAttrIter::Seek(TextFrameIndex const nNewPos)
         }
     }
 
+    if (isToEnd && !m_pEndAutoFormatAttr)
+    {
+        SeekToEnd();
+    }
+
     m_pFont->SetActual( m_pScriptInfo->WhichFont(nNewPos) );
 
     if( m_pRedline )
diff --git a/sw/source/core/text/itratr.hxx b/sw/source/core/text/itratr.hxx
index 4ad2c6d04c5f..91b3d4f9200c 100644
--- a/sw/source/core/text/itratr.hxx
+++ b/sw/source/core/text/itratr.hxx
@@ -21,6 +21,7 @@
 #include <o3tl/deleter.hxx>
 #include "atrhndl.hxx"
 #include <swfont.hxx>
+#include <txatbase.hxx>
 
 namespace sw { struct MergedPara; }
 class SwTextAttr;
@@ -33,6 +34,9 @@ class SAL_DLLPUBLIC_RTTI SwAttrIter
 {
     friend class SwFontSave;
 protected:
+    struct Destr{ void operator()(SwTextAttr *const pAttr) { 
SwTextAttr::Destroy(pAttr); } };
+    ::std::unique_ptr<SwTextAttr, Destr> m_pEndCharFormatAttr;
+    ::std::unique_ptr<SwTextAttr, Destr> m_pEndAutoFormatAttr;
 
     SwAttrHandler m_aAttrHandler;
     SwViewShell *m_pViewShell;
@@ -58,6 +62,7 @@ private:
     sw::MergedPara const* m_pMergedPara;
 
     void SeekFwd(sal_Int32 nOldPos, sal_Int32 nNewPos);
+    void SeekToEnd();
     void SetFnt( SwFont* pNew ) { m_pFont = pNew; }
     void InitFontAndAttrHandler(
         SwTextNode const& rPropsNode, SwTextNode const& rTextNode,
diff --git a/sw/source/core/text/porlay.cxx b/sw/source/core/text/porlay.cxx
index 37cb23961cff..f1b36ee1557b 100644
--- a/sw/source/core/text/porlay.cxx
+++ b/sw/source/core/text/porlay.cxx
@@ -569,9 +569,26 @@ void SwLineLayout::CalcLine( SwTextFormatter &rLine, 
SwTextFormatInfo &rInf )
         {
             bHasBlankPortion = true;
         }
+        else
+        {
+            bHasOnlyBlankPortions = false;
+            bHasNonBlankPortions = true;
+        }
     }
 
-    if (bIgnoreBlanksAndTabsForLineHeightCalculation && !bHasNonBlankPortions 
&&
+    if (!rInf.IsNewLine()
+        && TextFrameIndex(rInf.GetText().getLength()) <= rInf.GetIdx()
+        && !bHasNonBlankPortions
+        && rInf.GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(
+            
DocumentSettingId::APPLY_PARAGRAPH_MARK_FORMAT_TO_EMPTY_LINE_AT_END_OF_PARAGRAPH))
+    {
+        // Word: for empty last line, line height is based on paragraph marker
+        // formatting, ignoring blanks/tabs
+        rLine.SeekAndChg(rInf);
+        SetAscent(rInf.GetAscent());
+        Height(rInf.GetTextHeight());
+    }
+    else if (bIgnoreBlanksAndTabsForLineHeightCalculation && 
!bHasNonBlankPortions &&
         (bHasTabPortions || (bHasBlankPortion && (nSpacePortionAscent > 0 || 
nSpacePortionHeight > 0))))
     {
         //Word increases line height if _only_ spaces and|or tabstops are in a 
line
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index fbd3a3891fbb..ad813eddfc57 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -25,6 +25,7 @@
 #include <editeng/lspcitem.hxx>
 #include <editeng/lrspitem.hxx>
 #include <editeng/brushitem.hxx>
+#include <editeng/charhiddenitem.hxx>
 #include <editeng/pgrditem.hxx>
 #include <comphelper/configuration.hxx>
 #include <swmodule.hxx>
@@ -1540,6 +1541,22 @@ bool SwTextFrame::IsHiddenNow() const
         bHiddenCharsHidePara = static_cast<SwTextNode 
const*>(SwFrame::GetDep())->HasHiddenCharAttribute( true );
         bHiddenParaField = static_cast<SwTextNode 
const*>(SwFrame::GetDep())->IsHiddenByParaField();
     }
+    if (bHiddenCharsHidePara && GetDoc().getIDocumentSettingAccess().get(
+            
DocumentSettingId::APPLY_PARAGRAPH_MARK_FORMAT_TO_EMPTY_LINE_AT_END_OF_PARAGRAPH))
+    {
+        // apparently in Word it's always the last para marker that determines 
hidden?
+        // even in case when they are merged by delete redline (it's obvious 
when they are merged by hidden-attribute
+        SwTextNode const*const pNode{ m_pMergedPara
+            ? m_pMergedPara->pLastNode
+            : static_cast<SwTextNode const*>(SwFrame::GetDep()) };
+        SwFormatAutoFormat const& 
rListAutoFormat{pNode->GetAttr(RES_PARATR_LIST_AUTOFMT)};
+        std::shared_ptr<SfxItemSet> const 
pSet{rListAutoFormat.GetStyleHandle()};
+        SvxCharHiddenItem const*const pItem{pSet ? 
pSet->GetItemIfSet(RES_CHRATR_HIDDEN) : nullptr};
+        if (!pItem || !pItem->GetValue())
+        {
+            bHiddenCharsHidePara = false;
+        }
+    }
     const SwViewShell* pVsh = getRootFrame()->GetCurrShell();
 
     if ( pVsh && ( bHiddenCharsHidePara || bHiddenParaField ) )
diff --git a/sw/source/filter/ww8/ww8par.cxx b/sw/source/filter/ww8/ww8par.cxx
index a59c7042968a..6c4b50f2b226 100644
--- a/sw/source/filter/ww8/ww8par.cxx
+++ b/sw/source/filter/ww8/ww8par.cxx
@@ -1958,7 +1958,7 @@ void SwWW8ImplReader::ImportDop()
     
m_rDoc.getIDocumentSettingAccess().set(DocumentSettingId::PROP_LINE_SPACING_SHRINKS_FIRST_LINE,
 true);
     
m_rDoc.getIDocumentSettingAccess().set(DocumentSettingId::CONTINUOUS_ENDNOTES, 
true);
     // rely on default for HYPHENATE_URLS=false
-    // rely on default for 
APPLY_TEXT_ATTR_TO_EMPTY_LINE_AT_END_OF_PARAGRAPH=true
+    
m_rDoc.getIDocumentSettingAccess().set(DocumentSettingId::APPLY_PARAGRAPH_MARK_FORMAT_TO_EMPTY_LINE_AT_END_OF_PARAGRAPH,
 true);
 
     IDocumentSettingAccess& rIDSA = m_rDoc.getIDocumentSettingAccess();
     if (m_xWDop->fDontBreakWrappedTables)
diff --git a/sw/source/filter/xml/xmlimp.cxx b/sw/source/filter/xml/xmlimp.cxx
index a26a9fc4b863..5132e3a0cac4 100644
--- a/sw/source/filter/xml/xmlimp.cxx
+++ b/sw/source/filter/xml/xmlimp.cxx
@@ -1312,7 +1312,6 @@ void SwXMLImport::SetConfigurationSettings(const Sequence 
< PropertyValue > & aC
     bool bCollapseEmptyCellPara = false;
     bool bAutoFirstLineIndentDisregardLineSpace = false;
     bool bHyphenateURLs = false;
-    bool bApplyTextAttrToEmptyLineAtEndOfParagraph = false;
     bool bDoNotBreakWrappedTables = false;
     bool bAllowTextAfterFloatingTableBreak = false;
     bool bDropCapPunctuation = false;
@@ -1414,10 +1413,6 @@ void SwXMLImport::SetConfigurationSettings(const 
Sequence < PropertyValue > & aC
                 {
                     bHyphenateURLs = true;
                 }
-                else if (rValue.Name == 
"ApplyTextAttrToEmptyLineAtEndOfParagraph")
-                {
-                    bApplyTextAttrToEmptyLineAtEndOfParagraph = true;
-                }
                 else if (rValue.Name == "DoNotBreakWrappedTables")
                 {
                     rValue.Value >>= bDoNotBreakWrappedTables;
@@ -1599,11 +1594,6 @@ void SwXMLImport::SetConfigurationSettings(const 
Sequence < PropertyValue > & aC
         xProps->setPropertyValue(u"HyphenateURLs"_ustr, Any(true));
     }
 
-    if (!bApplyTextAttrToEmptyLineAtEndOfParagraph)
-    {
-        
xProps->setPropertyValue(u"ApplyTextAttrToEmptyLineAtEndOfParagraph"_ustr, 
Any(false));
-    }
-
     if (bDoNotMirrorRtlDrawObjs)
     {
         xProps->setPropertyValue(u"DoNotMirrorRtlDrawObjs"_ustr, Any(true));
diff --git a/sw/source/uibase/uno/SwXDocumentSettings.cxx 
b/sw/source/uibase/uno/SwXDocumentSettings.cxx
index 6baeff0a965a..5c43390f53ef 100644
--- a/sw/source/uibase/uno/SwXDocumentSettings.cxx
+++ b/sw/source/uibase/uno/SwXDocumentSettings.cxx
@@ -160,6 +160,7 @@ enum SwDocumentSettingsPropertyHandles
     HANDLE_DROP_CAP_PUNCTUATION,
     HANDLE_USE_VARIABLE_WIDTH_NBSP,
     HANDLE_APPLY_TEXT_ATTR_TO_EMPTY_LINE_AT_END_OF_PARAGRAPH,
+    HANDLE_APPLY_PARAGRAPH_MARK_FORMAT_TO_EMPTY_LINE_AT_END_OF_PARAGRAPH,
     HANDLE_DO_NOT_MIRROR_RTL_DRAW_OBJS,
     HANDLE_PAINT_HELL_OVER_HEADER_FOOTER,
     HANDLE_MIN_ROW_HEIGHT_INCL_BORDER,
@@ -270,6 +271,7 @@ static rtl::Reference<MasterPropertySetInfo> 
lcl_createSettingsInfo()
         { u"DropCapPunctuation"_ustr, HANDLE_DROP_CAP_PUNCTUATION, 
cppu::UnoType<bool>::get(), 0 },
         { u"UseVariableWidthNBSP"_ustr, HANDLE_USE_VARIABLE_WIDTH_NBSP, 
cppu::UnoType<bool>::get(), 0 },
         { u"ApplyTextAttrToEmptyLineAtEndOfParagraph"_ustr, 
HANDLE_APPLY_TEXT_ATTR_TO_EMPTY_LINE_AT_END_OF_PARAGRAPH, 
cppu::UnoType<bool>::get(), 0 },
+        { u"ApplyParagraphMarkFormatToEmptyLineAtEndOfParagraph"_ustr, 
HANDLE_APPLY_PARAGRAPH_MARK_FORMAT_TO_EMPTY_LINE_AT_END_OF_PARAGRAPH, 
cppu::UnoType<bool>::get(), 0 },
         { u"DoNotMirrorRtlDrawObjs"_ustr, HANDLE_DO_NOT_MIRROR_RTL_DRAW_OBJS, 
cppu::UnoType<bool>::get(), 0 },
         { u"PaintHellOverHeaderFooter"_ustr, 
HANDLE_PAINT_HELL_OVER_HEADER_FOOTER, cppu::UnoType<bool>::get(), 0 },
         { u"MinRowHeightInclBorder"_ustr, HANDLE_MIN_ROW_HEIGHT_INCL_BORDER, 
cppu::UnoType<bool>::get(), 0 },
@@ -1094,6 +1096,16 @@ void SwXDocumentSettings::_setSingleValue( const 
comphelper::PropertyInfo & rInf
             }
         }
         break;
+        case 
HANDLE_APPLY_PARAGRAPH_MARK_FORMAT_TO_EMPTY_LINE_AT_END_OF_PARAGRAPH:
+        {
+            bool bTmp;
+            if (rValue >>= bTmp)
+            {
+                mpDoc->getIDocumentSettingAccess().set(
+                    
DocumentSettingId::APPLY_PARAGRAPH_MARK_FORMAT_TO_EMPTY_LINE_AT_END_OF_PARAGRAPH,
 bTmp);
+            }
+        }
+        break;
         case HANDLE_DO_NOT_MIRROR_RTL_DRAW_OBJS:
         {
             bool bTmp;
@@ -1718,6 +1730,12 @@ void SwXDocumentSettings::_getSingleValue( const 
comphelper::PropertyInfo & rInf
                 
DocumentSettingId::APPLY_TEXT_ATTR_TO_EMPTY_LINE_AT_END_OF_PARAGRAPH);
         }
         break;
+        case 
HANDLE_APPLY_PARAGRAPH_MARK_FORMAT_TO_EMPTY_LINE_AT_END_OF_PARAGRAPH:
+        {
+            rValue <<= mpDoc->getIDocumentSettingAccess().get(
+                
DocumentSettingId::APPLY_PARAGRAPH_MARK_FORMAT_TO_EMPTY_LINE_AT_END_OF_PARAGRAPH);
+        }
+        break;
         case HANDLE_DO_NOT_MIRROR_RTL_DRAW_OBJS:
         {
             rValue <<= mpDoc->getIDocumentSettingAccess().get(
diff --git a/sw/source/writerfilter/dmapper/SettingsTable.cxx 
b/sw/source/writerfilter/dmapper/SettingsTable.cxx
index b49a6e013ace..c06c5bd395f7 100644
--- a/sw/source/writerfilter/dmapper/SettingsTable.cxx
+++ b/sw/source/writerfilter/dmapper/SettingsTable.cxx
@@ -643,6 +643,8 @@ void 
SettingsTable::ApplyProperties(rtl::Reference<SwXTextDocument> const& xDoc)
     // Shared between DOCX and RTF, unconditional flags.
     xDocumentSettings->setPropertyValue(u"TableRowKeep"_ustr, uno::Any(true));
     xDocumentSettings->setPropertyValue(u"AddVerticalFrameOffsets"_ustr, 
uno::Any(true));
+    
xDocumentSettings->setPropertyValue(u"ApplyParagraphMarkFormatToEmptyLineAtEndOfParagraph"_ustr,
+                                uno::Any(true));
 
     if (GetWordCompatibilityMode() <= 14)
     {
diff --git a/sw/source/writerfilter/filter/WriterFilter.cxx 
b/sw/source/writerfilter/filter/WriterFilter.cxx
index 201e2e1a4ee4..f5a90061c267 100644
--- a/sw/source/writerfilter/filter/WriterFilter.cxx
+++ b/sw/source/writerfilter/filter/WriterFilter.cxx
@@ -336,7 +336,6 @@ void WriterFilter::setTargetDocument(const 
uno::Reference<lang::XComponent>& xDo
     xSettings->setPropertyValue(u"PaintHellOverHeaderFooter"_ustr, 
uno::Any(true));
 
     // rely on default for HyphenateURLs=false
-    // rely on default for 
APPLY_TEXT_ATTR_TO_EMPTY_LINE_AT_END_OF_PARAGRAPH=true
     xSettings->setPropertyValue(u"DoNotMirrorRtlDrawObjs"_ustr, 
uno::Any(true));
     xSettings->setPropertyValue(u"ContinuousEndnotes"_ustr, uno::Any(true));
 }

Reply via email to