sw/qa/extras/layout/data/space+break.fodt |    2 
 sw/qa/extras/layout/layout3.cxx           |   50 +++++++-
 sw/qa/extras/uiwriter/uiwriter4.cxx       |  159 +++++++++++++++++++++-----
 sw/source/core/text/guess.cxx             |  180 +++++++++++++++++++-----------
 sw/source/core/text/inftxt.cxx            |   99 +++++-----------
 sw/source/core/text/inftxt.hxx            |   19 +++
 sw/source/core/text/itrcrsr.cxx           |   18 ++-
 sw/source/core/text/itrform2.cxx          |    2 
 sw/source/core/text/porlin.cxx            |   14 +-
 sw/source/core/text/portxt.cxx            |    4 
 sw/source/core/text/txttab.cxx            |    2 
 11 files changed, 365 insertions(+), 184 deletions(-)

New commits:
commit 853e13f9146e83b959bc53152ec103470d55fb4f
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Fri Dec 29 14:22:23 2023 +0600
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Sat Dec 30 09:51:28 2023 +0100

    tdf#57187: make sure to put trailing blanks to hole portion in narrow lines
    
    This needs to avoid special processing of trailing spaces after some tabs
    (tdf#106234). Also it needs to allow cursor movement over the newly added
    Hole portions.
    
    It turns out, that it also simplifies the fixes for tdf#104349 and 
tdf#104668.
    The special handling of paint of the trailing blanks is not needed, when the
    trailing blanks are SwHolePortion, which doesn't draw any background. Also,
    there's no need in special code in SwTextGuess::Guess for that case.
    
    This required to enable creation of the hole portions also for left-aligned
    lines, which were not adjusting break position correctly, because of a wrong
    condition that could never be true.
    
    Change-Id: I0e391be7b1caee4277a505368c3b13a00b5d9506
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161400
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/sw/qa/extras/layout/data/space+break.fodt 
b/sw/qa/extras/layout/data/space+break.fodt
index fbd81f37f501..7b53a8b012fa 100644
--- a/sw/qa/extras/layout/data/space+break.fodt
+++ b/sw/qa/extras/layout/data/space+break.fodt
@@ -44,7 +44,7 @@
  </office:master-styles>
  <office:body>
   <office:text>
-   <text:p text:style-name="P1">Lorem ipsum <text:s 
text:c="10"/><text:line-break/>Lorem ipsum <text:s 
text:c="1000"/><text:line-break/>Lorem ipsum <text:s text:c="1000"/>Lorem 
ipsum</text:p>
+   <text:p text:style-name="P1">Lorem ipsum <text:s 
text:c="10"/><text:line-break/>Lorem ipsum <text:s 
text:c="100"/><text:line-break/>Lorem ipsum <text:s 
text:c="1000"/><text:line-break/>Lorem ipsum <text:s text:c="1000"/>Lorem 
ipsum</text:p>
   </office:text>
  </office:body>
 </office:document>
\ No newline at end of file
diff --git a/sw/qa/extras/layout/layout3.cxx b/sw/qa/extras/layout/layout3.cxx
index 15f113754d46..da882cba559d 100644
--- a/sw/qa/extras/layout/layout3.cxx
+++ b/sw/qa/extras/layout/layout3.cxx
@@ -2125,26 +2125,62 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf152307)
     CPPUNIT_ASSERT_MESSAGE(aMsg.getStr(), nTabBottom < nFooterTop);
 }
 
-CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf158900)
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf57187_Tdf158900)
 {
     // Given a document with a single paragraph, having some long space runs 
and line breaks
     createSwDoc("space+break.fodt");
     xmlDocUniquePtr pXmlDoc = parseLayoutDump();
-    // Make sure there is only one page, one paragraph, and four lines
+    // Make sure there is only one page, one paragraph, and five lines
     assertXPath(pXmlDoc, "/root/page"_ostr, 1);
     assertXPath(pXmlDoc, "/root/page/body/txt/SwParaPortion"_ostr, 1);
-    // Without the fix in place, this would fail: there used to be 5 lines
-    assertXPath(pXmlDoc, 
"/root/page/body/txt/SwParaPortion/SwLineLayout"_ostr, 4);
-    // Check that the second line has correct portions
-    // Without the fix in place, this would fail: the line had only 2 portions 
(text + hole),
-    // and the break was on a separate third line
+    // Without the fix in place, this would fail: there used to be 6 lines
+    assertXPath(pXmlDoc, 
"/root/page/body/txt/SwParaPortion/SwLineLayout"_ostr, 5);
+
+    // tdf#57187: Check that relatively short lines have spaces not 
participating in layout.
+    // First line has 11 spaces in the end, and then a manual line break. It 
is rather short:
+    // without block justification, it is narrower than the available space.
+    // It uses the "first check if everything fits to line" return path in 
SwTextGuess::Guess.
+    // Check that the spaces are put into a Hole portion, thus not 
participating in layout.
+    // Without the fix, this would fail: there were only 2 portions, no Hole 
nor Margin portions.
+    assertXPath(pXmlDoc, 
"/root/page/body/txt/SwParaPortion/SwLineLayout[1]/*"_ostr, 4);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt/SwParaPortion/SwLineLayout[1]/*[1]"_ostr, "type"_ostr,
+                u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt/SwParaPortion/SwLineLayout[1]/*[1]"_ostr,
+                "length"_ostr, u"11"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt/SwParaPortion/SwLineLayout[1]/*[2]"_ostr, "type"_ostr,
+                u"PortionType::Hole"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt/SwParaPortion/SwLineLayout[1]/*[2]"_ostr,
+                "length"_ostr, u"11"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt/SwParaPortion/SwLineLayout[1]/*[3]"_ostr, "type"_ostr,
+                u"PortionType::Break"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt/SwParaPortion/SwLineLayout[1]/*[4]"_ostr, "type"_ostr,
+                u"PortionType::Margin"_ustr);
+    // Second line has 101 spaces in the end, and then a manual line break.
+    // It uses the "second check if everything fits to line" return path in 
SwTextGuess::Guess.
+    // Check that the spaces are put into a Hole portion, thus not 
participating in layout.
+    // Without the fix, this would fail: there were only 2 portions, no Hole 
portion.
     assertXPath(pXmlDoc, 
"/root/page/body/txt/SwParaPortion/SwLineLayout[2]/*"_ostr, 3);
     assertXPath(pXmlDoc, 
"/root/page/body/txt/SwParaPortion/SwLineLayout[2]/*[1]"_ostr, "type"_ostr,
                 u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt/SwParaPortion/SwLineLayout[2]/*[1]"_ostr,
+                "length"_ostr, u"11"_ustr);
     assertXPath(pXmlDoc, 
"/root/page/body/txt/SwParaPortion/SwLineLayout[2]/*[2]"_ostr, "type"_ostr,
                 u"PortionType::Hole"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt/SwParaPortion/SwLineLayout[2]/*[2]"_ostr,
+                "length"_ostr, u"101"_ustr);
     assertXPath(pXmlDoc, 
"/root/page/body/txt/SwParaPortion/SwLineLayout[2]/*[3]"_ostr, "type"_ostr,
                 u"PortionType::Break"_ustr);
+
+    // tdf#158900: Check that the break after a long line with trailing spaces 
is kept on same line.
+    // Without the fix in place, this would fail: the line had only 2 portions 
(text + hole),
+    // and the break was on a separate third line
+    assertXPath(pXmlDoc, 
"/root/page/body/txt/SwParaPortion/SwLineLayout[3]/*"_ostr, 3);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt/SwParaPortion/SwLineLayout[3]/*[1]"_ostr, "type"_ostr,
+                u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt/SwParaPortion/SwLineLayout[3]/*[2]"_ostr, "type"_ostr,
+                u"PortionType::Hole"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt/SwParaPortion/SwLineLayout[3]/*[3]"_ostr, "type"_ostr,
+                u"PortionType::Break"_ustr);
 }
 
 } // end of anonymous namespace
diff --git a/sw/qa/extras/uiwriter/uiwriter4.cxx 
b/sw/qa/extras/uiwriter/uiwriter4.cxx
index 58b4e020ae21..c1f0be1757d6 100644
--- a/sw/qa/extras/uiwriter/uiwriter4.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter4.cxx
@@ -2109,24 +2109,64 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, 
testMsWordCompTrailingBlanks)
     CPPUNIT_ASSERT_EQUAL(true, pDoc->getIDocumentSettingAccess().get(
                                    
DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS));
     calcLayout();
-    // Check that trailing spaces spans have no width if option is enabled
-
-    CPPUNIT_ASSERT_EQUAL(
-        OUString("0"),
-        
parseDump("/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[4]"_ostr,
-                  "width"_ostr));
-    CPPUNIT_ASSERT_EQUAL(
-        OUString("0"),
-        
parseDump("/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[5]"_ostr,
-                  "width"_ostr));
-    CPPUNIT_ASSERT_EQUAL(
-        OUString("0"),
-        
parseDump("/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[4]"_ostr,
-                  "width"_ostr));
-    CPPUNIT_ASSERT_EQUAL(
-        OUString("0"),
-        
parseDump("/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[5]"_ostr,
-                  "width"_ostr));
+    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+    // Check that trailing spaces spans are put into Hole portion if option is 
enabled
+
+    assertXPath(pXmlDoc, "/root/page/body/txt"_ostr, 3);
+
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*"_ostr, 4);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[1]"_ostr,
+                "type"_ostr, u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[1]"_ostr,
+                "portion"_ostr, u"TEST "_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[2]"_ostr,
+                "type"_ostr, u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[2]"_ostr,
+                "portion"_ostr, u"   "_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[3]"_ostr,
+                "type"_ostr, u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[3]"_ostr,
+                "portion"_ostr, u"   T"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[4]"_ostr,
+                "type"_ostr, u"PortionType::Hole"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[4]"_ostr,
+                "portion"_ostr, u"         "_ustr); // All the trailing blanks
+
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*"_ostr, 4);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[1]"_ostr,
+                "type"_ostr, u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[1]"_ostr,
+                "portion"_ostr, u"TEST "_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[2]"_ostr,
+                "type"_ostr, u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[2]"_ostr,
+                "portion"_ostr, u"   "_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[3]"_ostr,
+                "type"_ostr, u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[3]"_ostr,
+                "portion"_ostr, u"   T"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[4]"_ostr,
+                "type"_ostr, u"PortionType::Hole"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[4]"_ostr,
+                "portion"_ostr, u"         "_ustr); // All the trailing blanks
+
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*"_ostr, 4);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[1]"_ostr,
+                "type"_ostr, u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[1]"_ostr,
+                "portion"_ostr, u"TEST "_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[2]"_ostr,
+                "type"_ostr, u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[2]"_ostr,
+                "portion"_ostr, u"   "_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[3]"_ostr,
+                "type"_ostr, u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[3]"_ostr,
+                "portion"_ostr, u"   T"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[4]"_ostr,
+                "type"_ostr, u"PortionType::Hole"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[4]"_ostr,
+                "portion"_ostr, u"         "_ustr); // All the trailing blanks
 
     // The option is false in settings.xml
     createSwDoc("MsWordCompTrailingBlanksFalse.odt");
@@ -2134,19 +2174,76 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest4, 
testMsWordCompTrailingBlanks)
     CPPUNIT_ASSERT_EQUAL(false, pDoc->getIDocumentSettingAccess().get(
                                     
DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS));
     calcLayout();
-    // Check that trailing spaces spans have width if option is disabled
-    
CPPUNIT_ASSERT(parseDump("/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[4]"_ostr,
-                             "width"_ostr)
-                   != "0");
-    
CPPUNIT_ASSERT(parseDump("/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[5]"_ostr,
-                             "width"_ostr)
-                   != "0");
-    
CPPUNIT_ASSERT(parseDump("/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[4]"_ostr,
-                             "width"_ostr)
-                   != "0");
-    
CPPUNIT_ASSERT(parseDump("/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[5]"_ostr,
-                             "width"_ostr)
-                   != "0");
+    pXmlDoc = parseLayoutDump();
+    // Check that trailing spaces spans are put into Text portions if option 
is disabled
+
+    assertXPath(pXmlDoc, "/root/page/body/txt"_ostr, 3);
+
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*"_ostr, 5);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[1]"_ostr,
+                "type"_ostr, u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[1]"_ostr,
+                "portion"_ostr, u"TEST "_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[2]"_ostr,
+                "type"_ostr, u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[2]"_ostr,
+                "portion"_ostr, u"   "_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[3]"_ostr,
+                "type"_ostr, u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[3]"_ostr,
+                "portion"_ostr, u"   T   "_ustr); // first colored trailing 
blank span here
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[4]"_ostr,
+                "type"_ostr, u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[4]"_ostr,
+                "portion"_ostr, u"   "_ustr); // second colored trailing blank 
span here
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[5]"_ostr,
+                "type"_ostr, u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[5]"_ostr,
+                "portion"_ostr, u"   "_ustr); // third colored trailing blank 
span here
+
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*"_ostr, 5);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[1]"_ostr,
+                "type"_ostr, u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[1]"_ostr,
+                "portion"_ostr, u"TEST "_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[2]"_ostr,
+                "type"_ostr, u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[2]"_ostr,
+                "portion"_ostr, u"   "_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[3]"_ostr,
+                "type"_ostr, u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[3]"_ostr,
+                "portion"_ostr, u"   T   "_ustr); // first colored trailing 
blank span here
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[4]"_ostr,
+                "type"_ostr, u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[4]"_ostr,
+                "portion"_ostr, u"   "_ustr); // second colored trailing blank 
span here
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[5]"_ostr,
+                "type"_ostr, u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[2]/SwParaPortion/SwLineLayout/child::*[5]"_ostr,
+                "portion"_ostr, u"   "_ustr); // third colored trailing blank 
span here
+
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*"_ostr, 5);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[1]"_ostr,
+                "type"_ostr, u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[1]"_ostr,
+                "portion"_ostr, u"TEST "_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[2]"_ostr,
+                "type"_ostr, u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[2]"_ostr,
+                "portion"_ostr, u"   "_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[3]"_ostr,
+                "type"_ostr, u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[3]"_ostr,
+                "portion"_ostr, u"   T   "_ustr); // first colored trailing 
blank span here
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[4]"_ostr,
+                "type"_ostr, u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[4]"_ostr,
+                "portion"_ostr, u"   "_ustr); // second colored trailing blank 
span here
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[5]"_ostr,
+                "type"_ostr, u"PortionType::Text"_ustr);
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[3]/SwParaPortion/SwLineLayout/child::*[5]"_ostr,
+                "portion"_ostr, u"   "_ustr); // third colored trailing blank 
span here
 
     // MsWordCompTrailingBlanks option should be false by default in new 
documents
     createSwDoc();
diff --git a/sw/source/core/text/guess.cxx b/sw/source/core/text/guess.cxx
index 6123ad1b6767..3c85a42f4f15 100644
--- a/sw/source/core/text/guess.cxx
+++ b/sw/source/core/text/guess.cxx
@@ -44,6 +44,108 @@ namespace{
 
 bool IsBlank(sal_Unicode ch) { return ch == CH_BLANK || ch == CH_FULL_BLANK || 
ch == CH_NB_SPACE || ch == CH_SIX_PER_EM; }
 
+// Used when spaces should not be counted in layout
+// Returns adjusted cut position
+TextFrameIndex AdjustCutPos(TextFrameIndex cutPos, TextFrameIndex& rBreakPos,
+                            const SwTextFormatInfo& rInf)
+{
+    assert(cutPos >= rInf.GetIdx());
+    TextFrameIndex x = rBreakPos = cutPos;
+
+    // we step back until a non blank character has been found
+    // or there is only one more character left
+    while (x && x > rInf.GetIdx() + TextFrameIndex(1) && 
IsBlank(rInf.GetChar(--x)))
+        --rBreakPos;
+
+    while (IsBlank(rInf.GetChar(cutPos)))
+        ++cutPos;
+
+    return cutPos;
+}
+
+bool hasBlanksInLine(const SwTextFormatInfo& rInf, TextFrameIndex end)
+{
+    for (auto x = rInf.GetLineStart(); x < end; ++x)
+        if (IsBlank(rInf.GetChar(x)))
+            return true;
+    return false;
+}
+
+// Called for the last text run in a line; if it is block-adjusted, or center 
/ right-adjusted
+// with Word compatibility option set, and it has trailing spaces, then the 
function sets the
+// values, and returns 'false' value that SwTextGuess::Guess should return, to 
create a
+// trailing SwHolePortion.
+bool maybeAdjustPositionsForBlockAdjust(TextFrameIndex& rCutPos, 
TextFrameIndex& rBreakPos,
+                                        TextFrameIndex& rBreakStart, 
sal_uInt16& rBreakWidth,
+                                        sal_uInt16& rExtraBlankWidth, 
sal_uInt16& rMaxSizeDiff,
+                                        const SwTextFormatInfo& rInf, const 
SwScriptInfo& rSI,
+                                        sal_uInt16 maxComp)
+{
+    const auto& adjObj = 
rInf.GetTextFrame()->GetTextNodeForParaProps()->GetSwAttrSet().GetAdjust();
+    const SvxAdjust& adjust = adjObj.GetAdjust();
+    if (adjust == SvxAdjust::Block)
+    {
+        if (rInf.DontBlockJustify())
+            return true; // See tdf#106234
+    }
+    else
+    {
+        // tdf#104668 space chars at the end should be cut if the 
compatibility option is enabled
+        if (!rInf.GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(
+                DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS))
+            return true;
+        // for LTR mode only
+        if (rInf.GetTextFrame()->IsRightToLeft())
+            return true;
+    }
+    if (auto ch = rInf.GetChar(rCutPos); !ch) // end of paragraph - last line
+    {
+        if (adjust == SvxAdjust::Block)
+        {
+            // Check adjustment for last line
+            switch (adjObj.GetLastBlock())
+            {
+                default:
+                    return true;
+                case SvxAdjust::Center: // tdf#104668
+                    if 
(!rInf.GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(
+                            DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS))
+                        return true;
+                    break;
+                case SvxAdjust::Block:
+                    break; // OK - last line uses block-adjustment
+            }
+        }
+    }
+    else if (ch != CH_BREAK && !IsBlank(ch))
+        return true;
+
+    // tdf#57187: block-adjusted line shorter than full width, terminated by 
manual
+    // line break, must not use trailing spaces for adjustment
+    TextFrameIndex breakPos;
+    TextFrameIndex newCutPos = AdjustCutPos(rCutPos, breakPos, rInf);
+
+    if (auto ch = rInf.GetChar(newCutPos); ch && ch != CH_BREAK)
+        return true; // next is neither line break nor paragraph end
+    if (breakPos == newCutPos)
+        return true; // no trailing whitespace
+    if (adjust == SvxAdjust::Block && adjObj.GetOneWord() != SvxAdjust::Block
+        && !hasBlanksInLine(rInf, breakPos))
+        return true; // line can't block-adjust
+
+    // Some trailing spaces actually found, and in case of block adjustment, 
the text portion
+    // itself has spaces to be able to block-adjust, or single word is allowed 
to adjust
+    rBreakStart = rCutPos = newCutPos;
+    rBreakPos = breakPos;
+
+    rInf.GetTextSize(&rSI, rInf.GetIdx(), breakPos - rInf.GetIdx(), maxComp, 
rBreakWidth,
+                     rMaxSizeDiff, rInf.GetCachedVclData().get());
+    rInf.GetTextSize(&rSI, breakPos, rBreakStart - breakPos, maxComp, 
rExtraBlankWidth,
+                     rMaxSizeDiff, rInf.GetCachedVclData().get());
+
+    return false; // require SwHolePortion creation
+}
+
 }
 
 // provides information for line break calculation
@@ -88,38 +190,6 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, 
SwTextFormatInfo &rInf,
         nLineWidth += nSpacesInLine * (nSpaceWidth/0.8 - nSpaceWidth);
     }
 
-    // tdf#104668 space chars at the end should be cut if the compatibility 
option is enabled
-    // for LTR mode only
-    if ( !rInf.GetTextFrame()->IsRightToLeft() )
-    {
-        if (rInf.GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(
-                    DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS))
-        {
-            if ( rAdjust == SvxAdjust::Right || rAdjust == SvxAdjust::Center )
-            {
-                TextFrameIndex nSpaceCnt(0);
-                for (sal_Int32 i = rInf.GetText().getLength() - 1;
-                     sal_Int32(rInf.GetIdx()) <= i; --i)
-                {
-                    sal_Unicode cChar = rInf.GetText()[i];
-                    if ( cChar != CH_BLANK && cChar != CH_FULL_BLANK && cChar 
!= CH_SIX_PER_EM )
-                        break;
-                    ++nSpaceCnt;
-                }
-                TextFrameIndex nCharsCnt = nMaxLen - nSpaceCnt;
-                if ( nSpaceCnt && nCharsCnt < rPor.GetLen() )
-                {
-                    if (nSpaceCnt)
-                        rInf.GetTextSize( &rSI, rInf.GetIdx() + nCharsCnt, 
nSpaceCnt,
-                                          nMaxComp, m_nExtraBlankWidth, 
nMaxSizeDiff );
-                    nMaxLen = nCharsCnt;
-                    if ( !nMaxLen )
-                        return true;
-                }
-            }
-        }
-    }
-
     if ( rInf.GetLen() < nMaxLen )
         nMaxLen = rInf.GetLen();
 
@@ -183,12 +253,15 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, 
SwTextFormatInfo &rInf,
         {
             // portion fits to line
             m_nCutPos = rInf.GetIdx() + nMaxLen;
+            bool bRet = maybeAdjustPositionsForBlockAdjust(m_nCutPos, 
m_nBreakPos, m_nBreakStart,
+                                                           m_nBreakWidth, 
m_nExtraBlankWidth,
+                                                           nMaxSizeDiff, rInf, 
rSI, nMaxComp);
             if( nItalic &&
                 (m_nCutPos >= TextFrameIndex(rInf.GetText().getLength()) ||
                   // #i48035# Needed for CalcFitToContent
                   // if first line ends with a manual line break
                   rInf.GetText()[sal_Int32(m_nCutPos)] == CH_BREAK))
-                m_nBreakWidth = m_nBreakWidth + nItalic;
+                m_nBreakWidth += nItalic;
 
             // save maximum width for later use
             if ( nMaxSizeDiff )
@@ -196,7 +269,7 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, 
SwTextFormatInfo &rInf,
 
             m_nBreakWidth += nLeftRightBorderSpace;
 
-            return true;
+            return bRet;
         }
     }
 
@@ -335,8 +408,12 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, 
SwTextFormatInfo &rInf,
         // there likely has been a pixel rounding error in GetTextBreak
         if ( m_nBreakWidth <= nLineWidth )
         {
+            bool bRet = maybeAdjustPositionsForBlockAdjust(m_nCutPos, 
m_nBreakPos, m_nBreakStart,
+                                                           m_nBreakWidth, 
m_nExtraBlankWidth,
+                                                           nMaxSizeDiff, rInf, 
rSI, nMaxComp);
+
             if (nItalic && (m_nBreakPos + TextFrameIndex(1)) >= 
TextFrameIndex(rInf.GetText().getLength()))
-                m_nBreakWidth = m_nBreakWidth + nItalic;
+                m_nBreakWidth += nItalic;
 
             // save maximum width for later use
             if ( nMaxSizeDiff )
@@ -344,7 +421,7 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, 
SwTextFormatInfo &rInf,
 
             m_nBreakWidth += nLeftRightBorderSpace;
 
-            return true;
+            return bRet;
         }
     }
 
@@ -359,36 +436,11 @@ bool SwTextGuess::Guess( const SwTextPortion& rPor, 
SwTextFormatInfo &rInf,
 
     TextFrameIndex nPorLen(0);
     // do not call the break iterator nCutPos is a blank
-    sal_Unicode cCutChar = m_nCutPos < 
TextFrameIndex(rInf.GetText().getLength())
-        ? rInf.GetText()[sal_Int32(m_nCutPos)]
-        : 0;
+    sal_Unicode cCutChar = rInf.GetChar(m_nCutPos);
     if (IsBlank(cCutChar))
     {
-        m_nBreakPos = m_nCutPos;
-        TextFrameIndex nX = m_nBreakPos;
-
-        if ( rAdjust == SvxAdjust::Left )
-        {
-            // we step back until a non blank character has been found
-            // or there is only one more character left
-            while (nX && TextFrameIndex(rInf.GetText().getLength()) < 
m_nBreakPos &&
-                   IsBlank(rInf.GetChar(--nX)))
-                --m_nBreakPos;
-        }
-        else // #i20878#
-        {
-            while (nX && m_nBreakPos > rInf.GetLineStart() + TextFrameIndex(1) 
&&
-                   IsBlank(rInf.GetChar(--nX)))
-                --m_nBreakPos;
-        }
-
-        if( m_nBreakPos > rInf.GetIdx() )
-            nPorLen = m_nBreakPos - rInf.GetIdx();
-        while (++m_nCutPos < TextFrameIndex(rInf.GetText().getLength()) &&
-               IsBlank(rInf.GetChar(m_nCutPos)))
-            ; // nothing
-
-        m_nBreakStart = m_nCutPos;
+        m_nCutPos = m_nBreakStart = AdjustCutPos(m_nCutPos, m_nBreakPos, rInf);
+        nPorLen = m_nBreakPos - rInf.GetIdx();
     }
     else
     {
diff --git a/sw/source/core/text/inftxt.cxx b/sw/source/core/text/inftxt.cxx
index c005ad75b7bf..3d9121ef1ec2 100644
--- a/sw/source/core/text/inftxt.cxx
+++ b/sw/source/core/text/inftxt.cxx
@@ -1213,74 +1213,6 @@ void SwTextPaintInfo::DrawBackBrush( const SwLinePortion 
&rPor ) const
         aFillColor = *m_pFnt->GetBackColor();
     }
 
-    // tdf#104349 do not highlight portions of space chars before end of line 
if the compatibility option is enabled
-    // for LTR mode only
-    if ( !GetTextFrame()->IsRightToLeft() )
-    {
-        if 
(GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS))
-        {
-            bool           draw = false;
-            bool           full = false;
-            const sal_Int32 nMaxLen = GetText().getLength();
-            const sal_Int32 nCurrPorEnd(GetIdx() + rPor.GetLen());
-            const SwLinePortion* pPos = &rPor;
-            TextFrameIndex nIdx = GetIdx();
-
-            do
-            {
-                const sal_Int32 nEndPos = std::min(sal_Int32(nIdx + 
pPos->GetLen()), nMaxLen);
-                for (sal_Int32 i = sal_Int32(nIdx); i < nEndPos; ++i)
-                {
-                    if (i < nMaxLen && i >= nCurrPorEnd && GetText()[i] == 
CH_TXTATR_NEWLINE)
-                        goto drawcontinue;
-
-                    if (i == nMaxLen || GetText()[i] != CH_BLANK)
-                    {
-                        draw = true;
-                        if (i >= nCurrPorEnd)
-                        {
-                            full = true;
-                            goto drawcontinue;
-                        }
-                    }
-                }
-                nIdx += pPos->GetLen();
-                pPos = pPos->GetNextPortion();
-            } while ( pPos );
-
-        drawcontinue:
-
-            if ( !draw )
-                return;
-
-            if ( !full )
-            {
-                const sal_Int32 nLastPos = std::min(nCurrPorEnd, nMaxLen) - 1;
-                for (sal_Int32 i = nLastPos; TextFrameIndex(i) >= GetIdx(); 
--i)
-                {
-                    if (GetText()[i] == CH_TXTATR_NEWLINE)
-                        continue;
-
-                    if (GetText()[i] != CH_BLANK)
-                    {
-                        const sal_uInt16 nOldWidth = rPor.Width();
-                        const sal_uInt16 nExcessWidth
-                            = GetTextSize(m_pOut, nullptr, GetText(), 
TextFrameIndex(i + 1),
-                                          TextFrameIndex(nLastPos - 
i)).Width();
-                        const_cast<SwLinePortion&>(rPor).Width(nOldWidth - 
nExcessWidth);
-                        CalcRect( rPor, nullptr, &aIntersect, true );
-                        const_cast<SwLinePortion&>(rPor).Width( nOldWidth );
-
-                        if ( !aIntersect.HasArea() )
-                            return;
-
-                        break;
-                    }
-                }
-            }
-        }
-    }
-
     pTmpOut->Push( vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR );
 
     pTmpOut->SetFillColor(aFillColor);
@@ -1798,6 +1730,37 @@ SwTextFormatInfo::SwTextFormatInfo( const 
SwTextFormatInfo& rInf,
     SetFirstMulti( rInf.IsFirstMulti() );
 }
 
+void SwTextFormatInfo::UpdateTabSeen(PortionType type)
+{
+    switch (type)
+    {
+        case PortionType::TabLeft:
+            m_eLastTabsSeen = TabSeen::Left;
+            break;
+        case PortionType::TabRight:
+            m_eLastTabsSeen = TabSeen::Right;
+            break;
+        case PortionType::TabCenter:
+            m_eLastTabsSeen = TabSeen::Center;
+            break;
+        case PortionType::TabDecimal:
+            m_eLastTabsSeen = TabSeen::Decimal;
+            break;
+        case PortionType::Break:
+            m_eLastTabsSeen = TabSeen::None;
+            break;
+        default:
+            break;
+    }
+}
+
+void SwTextFormatInfo::SetLast(SwLinePortion* pNewLast)
+{
+    m_pLast = pNewLast;
+    assert(pNewLast); // We never pass nullptr here. If we start, then a check 
is needed below.
+    UpdateTabSeen(pNewLast->GetWhichPor());
+}
+
 bool SwTextFormatInfo::CheckFootnotePortion_( SwLineLayout const * pCurr )
 {
     const sal_uInt16 nHeight = pCurr->GetRealHeight();
diff --git a/sw/source/core/text/inftxt.hxx b/sw/source/core/text/inftxt.hxx
index f2f6d146136e..2ddaee7b2e8f 100644
--- a/sw/source/core/text/inftxt.hxx
+++ b/sw/source/core/text/inftxt.hxx
@@ -517,6 +517,16 @@ class SwTextFormatInfo : public SwTextPaintInfo
     sal_Unicode   m_cHookChar;    // For tabs in fields etc.
     sal_uInt8   m_nMaxHyph;       // Max. line count of followup hyphenations
 
+    // Used to stop justification after center/right/decimal tab stops - see 
tdf#tdf#106234
+    enum class TabSeen
+    {
+        None,
+        Left,
+        Center,
+        Right,
+        Decimal,
+    } m_eLastTabsSeen = TabSeen::None;
+
     // Hyphenating ...
     bool InitHyph( const bool bAuto = false );
     bool CheckFootnotePortion_( SwLineLayout const * pCurr );
@@ -566,7 +576,7 @@ public:
 
     void SetRoot( SwLineLayout *pNew ) { m_pRoot = pNew; }
     SwLinePortion *GetLast() { return m_pLast; }
-    void SetLast( SwLinePortion *pNewLast ) { m_pLast = pNewLast; }
+    void SetLast(SwLinePortion* pNewLast);
     bool IsFull() const { return m_bFull; }
     void SetFull( const bool bNew ) { m_bFull = bNew; }
     bool IsHyphForbud() const
@@ -593,6 +603,13 @@ public:
     void SetDropInit( const bool bNew ) { m_bDropInit = bNew; }
     bool IsQuick() const { return m_bQuick; }
     bool IsTest() const { return m_bTestFormat; }
+    // see tdf#106234
+    void UpdateTabSeen(PortionType);
+    bool DontBlockJustify() const
+    {
+        return m_eLastTabsSeen == TabSeen::Center || m_eLastTabsSeen == 
TabSeen::Right
+               || m_eLastTabsSeen == TabSeen::Decimal;
+    }
 
     TextFrameIndex GetLineStart() const { return m_nLineStart; }
     void SetLineStart(TextFrameIndex const nNew) { m_nLineStart = nNew; }
diff --git a/sw/source/core/text/itrcrsr.cxx b/sw/source/core/text/itrcrsr.cxx
index 4ae582d7df59..6da37f66a5de 100644
--- a/sw/source/core/text/itrcrsr.cxx
+++ b/sw/source/core/text/itrcrsr.cxx
@@ -399,18 +399,30 @@ void SwTextCursor::CtorInitTextCursor( SwTextFrame 
*pNewFrame, SwTextSizeInfo *p
     // GetInfo().SetOut( GetInfo().GetWin() );
 }
 
+static bool isTrailingDecoration(SwLinePortion* p)
+{
+    // Optional no-width portion, followed only by no-width portions and/or 
terminating portions?
+    for (; p; p = p->GetNextPortion())
+    {
+        if (p->IsMarginPortion() || p->IsBreakPortion())
+            return true;
+        if (p->Width())
+            return false;
+    }
+    return true; // no more portions
+}
+
 // tdf#120715 tdf#43100: Make width for some HolePortions, so cursor will be 
able to move into it.
 // It should not change the layout, so this should be called after the layout 
is calculated.
 void SwTextCursor::AddExtraBlankWidth()
 {
     SwLinePortion* pPos = m_pCurr->GetNextPortion();
-    SwLinePortion* pNextPos;
     while (pPos)
     {
-        pNextPos = pPos->GetNextPortion();
+        SwLinePortion* pNextPos = pPos->GetNextPortion();
         // Do it only if it is the last portion that able to handle the cursor,
         // else the next portion would miscalculate the cursor position
-        if (pPos->ExtraBlankWidth() && (!pNextPos || 
pNextPos->IsMarginPortion()))
+        if (pPos->ExtraBlankWidth() && isTrailingDecoration(pNextPos))
         {
             pPos->Width(pPos->Width() + pPos->ExtraBlankWidth());
             pPos->ExtraBlankWidth(0);
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index 55fa779a86aa..09d9f7c213f0 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -1261,7 +1261,7 @@ SwTextPortion *SwTextFormatter::WhichTextPor( 
SwTextFormatInfo &rInf ) const
             // If pCurr does not have a width, it can however already have 
content.
             // E.g. for non-displayable characters
 
-            auto const ch(rInf.GetText()[sal_Int32(rInf.GetIdx())]);
+            auto const ch(rInf.GetChar(rInf.GetIdx()));
             SwTextFrame const*const pFrame(rInf.GetTextFrame());
             SwPosition aPosition(pFrame->MapViewToModelPos(rInf.GetIdx()));
             sw::mark::IFieldmark *pBM = 
pFrame->GetDoc().getIDocumentMarkAccess()->getInnerFieldmarkFor(aPosition);
diff --git a/sw/source/core/text/porlin.cxx b/sw/source/core/text/porlin.cxx
index 31010a1e776e..4f93c9d727ce 100644
--- a/sw/source/core/text/porlin.cxx
+++ b/sw/source/core/text/porlin.cxx
@@ -21,6 +21,7 @@
 #include <SwPortionHandler.hxx>
 
 #include "porlin.hxx"
+#include "portxt.hxx"
 #include "inftxt.hxx"
 #include "pormulti.hxx"
 #if OSL_DEBUG_LEVEL > 0
@@ -86,10 +87,10 @@ void SwLinePortion::PrePaint( const SwTextPaintInfo& rInf,
         return;
 
     const sal_uInt16 nHalfView = nViewWidth / 2;
-    sal_uInt16 nLastWidth = pLast->Width();
+    sal_uInt16 nLastWidth = pLast->Width() + pLast->ExtraBlankWidth();
 
     if ( pLast->InSpaceGrp() && rInf.GetSpaceAdd() )
-        nLastWidth = nLastWidth + pLast->CalcSpacing( rInf.GetSpaceAdd(), rInf 
);
+        nLastWidth += pLast->CalcSpacing( rInf.GetSpaceAdd(), rInf );
 
     sal_uInt16 nPos;
     SwTextPaintInfo aInf( rInf );
@@ -276,9 +277,10 @@ void SwLinePortion::Move(SwTextPaintInfo & rInf) const
     bool bCounterDir = ( ! bFrameDir && DIR_RIGHT2LEFT == rInf.GetDirection() 
) ||
                        (   bFrameDir && DIR_LEFT2RIGHT == rInf.GetDirection() 
);
 
+    SwTwips nTmp = PrtWidth() + ExtraBlankWidth();
     if ( InSpaceGrp() && rInf.GetSpaceAdd(/*bShrink=*/true) )
     {
-        SwTwips nTmp = PrtWidth() + CalcSpacing( 
rInf.GetSpaceAdd(/*bShrink=*/true), rInf );
+        nTmp += CalcSpacing( rInf.GetSpaceAdd(/*bShrink=*/true), rInf );
         if( rInf.IsRotated() )
             rInf.Y( rInf.Y() + ( bB2T ? -nTmp : nTmp ) );
         else if ( bCounterDir )
@@ -294,11 +296,11 @@ void SwLinePortion::Move(SwTextPaintInfo & rInf) const
             rInf.IncKanaIdx();
         }
         if( rInf.IsRotated() )
-            rInf.Y( rInf.Y() + ( bB2T ? -PrtWidth() : PrtWidth() ) );
+            rInf.Y(rInf.Y() + (bB2T ? -nTmp : nTmp));
         else if ( bCounterDir )
-            rInf.X( rInf.X() - PrtWidth() );
+            rInf.X(rInf.X() - nTmp);
         else
-            rInf.X( rInf.X() + PrtWidth() );
+            rInf.X(rInf.X() + nTmp);
     }
     if (IsMultiPortion() && static_cast<SwMultiPortion 
const*>(this)->HasTabulator())
         rInf.IncSpaceIdx();
diff --git a/sw/source/core/text/portxt.cxx b/sw/source/core/text/portxt.cxx
index 1042dcf54165..0372a357df6e 100644
--- a/sw/source/core/text/portxt.cxx
+++ b/sw/source/core/text/portxt.cxx
@@ -434,8 +434,8 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf )
 
                 // UAX #14 Unicode Line Breaking Algorithm Non-tailorable Line 
breaking rule LB6:
                 // https://www.unicode.org/reports/tr14/#LB6 Do not break 
before hard line breaks
-                if (rInf.GetChar(aGuess.BreakStart()) == CH_BREAK)
-                    bFull = false; // Keep following SwBreakPortion in the 
same line
+                if (auto ch = rInf.GetChar(aGuess.BreakStart()); !ch || ch == 
CH_BREAK)
+                    bFull = false; // Keep following SwBreakPortion / para 
break in the same line
             }
         }
         else    // case C2, last exit
diff --git a/sw/source/core/text/txttab.cxx b/sw/source/core/text/txttab.cxx
index 389e4efb2e46..e7141aaec538 100644
--- a/sw/source/core/text/txttab.cxx
+++ b/sw/source/core/text/txttab.cxx
@@ -320,6 +320,8 @@ SwTabPortion *SwTextFormatter::NewTabPortion( 
SwTextFormatInfo &rInf, bool bAuto
             }
         }
     }
+    if (pTabPor)
+        rInf.UpdateTabSeen(pTabPor->GetWhichPor());
 
     return pTabPor;
 }

Reply via email to