sw/qa/extras/layout/data/tdf158658a.rtf |   25 +++++++++++++++
 sw/qa/extras/layout/data/tdf158658b.rtf |   27 ++++++++++++++++
 sw/qa/extras/layout/layout2.cxx         |    6 +--
 sw/qa/extras/layout/layout3.cxx         |   52 +++++++++++++++++++++++++++++---
 sw/source/core/text/inftxt.cxx          |    6 +++
 sw/source/core/text/txttab.cxx          |    5 +--
 6 files changed, 112 insertions(+), 9 deletions(-)

New commits:
commit a726a78fa96e25e12176129b2eabea779126ee56
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Thu Jun 13 12:59:19 2024 +0200
Commit:     Thorsten Behrens <thorsten.behr...@allotropia.de>
CommitDate: Fri Jun 14 19:43:04 2024 +0200

    tdf#158658 sw: text formatting: try to make TabOverMargin more crazy
    
    ... to better match Word's formatting; this commit is not based on a
    complete diagnosis of Word's compatibility-mode tab-in-margin
    formatting disorders.
    
    1. in SwTabPortion::PreFormat() allow a left aligned tab beyond the
       width of the paragraph, like already done for TabOverSpacing
    
    2. in SwTextFormatInfo::GetLineWidth() add some extra width to the
       paragraph so text can be hidden in the right margin.
       (it's very unclear what Word does here exactly, in one case it puts
       339 additional "a" characters in the margin but then the 340th "a"
       goes onto a new line...)
    
    3. in SwTextFormatter::NewTabPortion() allow manual tab stops to be
       positioned beyond the width of the paragraph, like already done
       for TabOverSpacing
    
    testTdf118672, testTdf120287b, testTdf120287c fail but the files,
    converted to RTF, render in Word 2013 basically the same as in Writer
    with this change.
    
    Change-Id: I5f74ced09c704bfd9967df61351c8bac6540e714
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168819
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 10d753b8aadb50ec4309551b97d4cf2163ea3e3d)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168863
    Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de>

diff --git a/sw/qa/extras/layout/data/tdf158658a.rtf 
b/sw/qa/extras/layout/data/tdf158658a.rtf
new file mode 100644
index 000000000000..712fd5a7f733
--- /dev/null
+++ b/sw/qa/extras/layout/data/tdf158658a.rtf
@@ -0,0 +1,25 @@
+{ 
tf1deflang1025nsinsicpg1252\uc1deff0\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\deflang3079\deflangfe3079
        hemelang3079    hemelangfe0     hemelangcs0
+{onttbl{0bidi romancharset0prq2 Times New Roman;}
+{dbminor31505bidi romancharset0prq2 Times New Roman;}{himinor31506
bidi swisscharset0prq2 Calibri;}
+}
+{\*\defchp s22\lochf31506\hichf31506\dbchf31505 }
+{\*\defpap \ql \li0 i0\sa160\sl259\slmult1\widctlpar\wrapdefaultspalphaspnum
aautodjustright in0\lin0\itap0 }
oqfpromote
+{\stylesheet{
+\ql \li0 i0
owidctlpar\wrapdefaultaautodjustright in0\lin0\itap0  tlchcs1 
f0fs26lang1025 \ltrchcs0 s26\lang1031\langfe3079\loch
0\hichf0\dbchf31505+{\s17\ql \li0 i0
owidctlpar      qc      x4252   qr      x8504\wrapdefaultaautodjustright 
in0\lin0\itap0  tlchcs1 f0fs26lang1025 \ltrchcs0 
+s26\lang1031\langfe3079\loch0\hichf0\dbchf31505+}
+
+\paperw11907\paperh16840\margl1418\margr851\margt1418\margb1134\gutter0\ltrsect
 
+\deftab709\widowctrltnbjenddoc\hyphhotz425   rackmoves0      
rackformatting1\donotembedsysfont0 elyonvml0\donotembedlingdata1\grfdocevents0
alidatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\hyphcaps0\horzdoc\dghspace120
+\dgvspace120\dghorigin1701\dgvorigin1984\dghshow0\dgvshow3\jcompressiewkind1
iewscale100et0{\*\wgrffmtfilter 013f}\ilfomacatclnup0
+
+\ltrpar \sectd \ltrsect\linex0\headery703ootery709+   qc      x4820   qr      
x9923\wrapdefaultaautodjustright in-285\lin0\itap0  tlchcs1 
f0fs26lang1025 \ltrchcs0 
s26\lang1031\langfe3079\lochf0\hichf0\dbchf31505+
s24\hichf0\dbchf31505\loch0 \hich0 Xx\loch0 Xx  ab Xxxxxxxx Xxxx Xxxxxxxx  
     ab XXXXXXXX     ab      ab      ab      ab      ab      ab      ab      ab 
     ab }{ tlchcs1 bf0fs24 \ltrchcs0 s24\ul
+\par }}
+
+\pard\plain \ltrpar\ql \li0 i-1701\widctlpar   x3969\wrapdefault
aautodjustright in-1701\lin0\itap0  tlchcs1 
+f0fs26lang1025 \ltrchcs0 
s26\lang1031\langfe3079\lochf0\hichf0\dbchf31505+\par }
+}
diff --git a/sw/qa/extras/layout/data/tdf158658b.rtf 
b/sw/qa/extras/layout/data/tdf158658b.rtf
new file mode 100644
index 000000000000..f0e23903662f
--- /dev/null
+++ b/sw/qa/extras/layout/data/tdf158658b.rtf
@@ -0,0 +1,27 @@
+{ 
tf1deflang1025nsinsicpg1252\uc1deff0\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi0\deflang3079\deflangfe3079
       hemelang3079    hemelangfe0     hemelangcs0
+{onttbl{0bidi romancharset0prq2 Times New Roman{\*alt Arial};}
+{dbminor31505bidi romancharset0prq2 Times New Roman{\*alt Arial};}
+{himinor31506bidi swisscharset0prq2 Calibri;}}
+{\*\defchp s22\lochf31506\hichf31506\dbchf31505 }{\*\defpap \ql \li0 
i0\sa160\sl259\slmult1\widctlpar\wrapdefaultspalphaspnumaautodjustright 
in0\lin0\itap0 }
+
oqfpromote
+{\stylesheet{\ql \li0 i0\widctlpar\wrapdefaultspalphaspnumaautodjustright 
in0\lin0\itap0  tlchcs1 f0fs26lang1025 \ltrchcs0 
s26\lang3079\langfe3079\loch0\hichf0\dbchf31505+\snext0 \sqformat 
\spriority0 Normal;}
+{\s18\ql \li0 i0\widctlpar     qc      x4536   qr      
x9072\wrapdefaultspalphaspnumaautodjustright in0\lin0\itap0  tlchcs1 
f0fs18lang1025 \ltrchcs0 
+s18\lang3079\langfe3079\loch0\hichf0\dbchf31505+}
+\paperw4876\paperh3175\margl113\margr113\margt113\margb0\gutter0\ltrsect 
+\deftab708\widowctrltnbjenddoc\hyphhotz425   rackmoves0      
rackformatting1\donotembedsysfont0 elyonvml0\donotembedlingdata1\grfdocevents0
alidatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0
+\showxmlerrors0
oxlattoyenxpshrtn
oultrlspc\dntblnsbdb
ospaceforul\hyphcaps0
ormshade\horzdoc\dgmargin\dghspace130\dgvspace180\dghorigin113\dgvorigin113\dghshow0\dgvshow0
+\jexpandiewkind1iewscale240\pgbrdrhead\pgbrdrfoot
olnhtadjtbl
ojkernpunctet0{\*\wgrffmtfilter 013f}\ilfomacatclnup0
+\ltrpar
+
+\sectd \ltrsect
+\lndscpsxn\psz5\linex0ootery0ndnhere\sectlinegrid354\sectdefaultcl\sftnbj
+{ooterr \ltrpar \pard\plain \ltrpar\s18\ql \li0 i0\widctlpar
+       qc      x4536   qr      x9072\wrapdefaultspalphaspnum
aautodjustright in0\lin0\itap0 tlchcs1 f0fs18lang1025 \ltrchcs0 
s18\lang3079\langfe3079\lochf0\hichf0\dbchf31505+\ltrchcs0   ab      ab }{
ield{\*ldinst { tlchcs1 f0 \ltrchcs0 \hichf0\dbchf31505\loch0  PAGE  \* 
MERGEFORMAT }}{ldrslt { tlchcs1 f0 \ltrchcs0 \lang1024\langfe1024
oproof
+\hichf0\dbchf31505\loch0 4}}}\sectd 
\ltrsect\lndscpsxn\linex0ndnhere\sectdefaultcl\sftnbj { tlchcs1 f0 \ltrch
cs0 
+\par }}
+
+\par }
+}
diff --git a/sw/qa/extras/layout/layout2.cxx b/sw/qa/extras/layout/layout2.cxx
index 2e46ebfbfc29..683c39c72d0a 100644
--- a/sw/qa/extras/layout/layout2.cxx
+++ b/sw/qa/extras/layout/layout2.cxx
@@ -2386,12 +2386,12 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf118672)
         return;
 
     // This ended as "fol*1 2 3 4 5 6 7 8 9", i.e. "10con-" was moved to the 
next line.
+    // Bizarrely, Word lets the text run into the right margin (loaded from 
.rtf)
     assertXPath(pXmlDoc, 
"/root/page/body/txt[1]/SwParaPortion/SwLineLayout[1]"_ostr,
                 "portion"_ostr,
+
                 "He heard quiet steps behind him. That didn't bode well. Who 
could be fol*1 2 "
-                "3 4 5 6 7 8 9 10con");
-    assertXPath(pXmlDoc, 
"/root/page/body/txt[1]/SwParaPortion/SwLineLayout[2]"_ostr,
-                "portion"_ostr, "setetur");
+                "3 4 5 6 7 8 9 10consetetur");
 }
 
 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf150200)
diff --git a/sw/qa/extras/layout/layout3.cxx b/sw/qa/extras/layout/layout3.cxx
index 61628bc27a4d..bd7758159895 100644
--- a/sw/qa/extras/layout/layout3.cxx
+++ b/sw/qa/extras/layout/layout3.cxx
@@ -397,16 +397,60 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf120287b)
     assertXPath(
         pXmlDoc,
         
"/root/page/body/txt[1]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::TabRight']"_ostr,
-        "width"_ostr, "18");
+        "width"_ostr, "1");
 }
 
 CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf120287c)
 {
     createSwDoc("tdf120287c.fodt");
     xmlDocUniquePtr pXmlDoc = parseLayoutDump();
-    // This was 2, the second line was not broken into a 2nd and a 3rd one,
-    // rendering text outside the paragraph frame.
-    assertXPath(pXmlDoc, 
"/root/page/body/txt[1]/SwParaPortion/SwLineLayout"_ostr, 3);
+    // This was 3, the second line was broken into a 2nd and a 3rd one,
+    // not rendering text outside the paragraph frame like Word 2013 does.
+    assertXPath(pXmlDoc, 
"/root/page/body/txt[1]/SwParaPortion/SwLineLayout"_ostr, 2);
+}
+
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf158658a)
+{
+    createSwDoc("tdf158658a.rtf");
+    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+
+    // Word 2013 puts all tabs into one line, the last 8 of them are off the 
page
+    assertXPath(pXmlDoc, 
"/root/page[1]/header/txt[1]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(
+        pXmlDoc,
+        
"/root/page[1]/header/txt[1]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::TabCenter']"_ostr,
+        1);
+    assertXPath(
+        pXmlDoc,
+        
"/root/page[1]/header/txt[1]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::TabRight']"_ostr,
+        1);
+    assertXPath(
+        pXmlDoc,
+        
"/root/page[1]/header/txt[1]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::TabLeft']"_ostr,
+        9);
+}
+
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf158658b)
+{
+    createSwDoc("tdf158658b.rtf");
+    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+
+    // Word 2013 puts all tabs and the field following into one line
+    // but also puts the field off the page, while in Writer it's
+    // aligned to the right margin; should be good enough for now...
+    assertXPath(pXmlDoc, 
"/root/page[1]/footer/txt[1]/SwParaPortion/SwLineLayout"_ostr, 1);
+    assertXPath(
+        pXmlDoc,
+        
"/root/page[1]/footer/txt[1]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::TabCenter']"_ostr,
+        1);
+    assertXPath(
+        pXmlDoc,
+        
"/root/page[1]/footer/txt[1]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::TabRight']"_ostr,
+        1);
+    assertXPath(
+        pXmlDoc,
+        
"/root/page[1]/footer/txt[1]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::TabLeft']"_ostr,
+        0);
 }
 
 CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf155177)
diff --git a/sw/source/core/text/inftxt.cxx b/sw/source/core/text/inftxt.cxx
index 8eced32e8990..66dae09b35c4 100644
--- a/sw/source/core/text/inftxt.cxx
+++ b/sw/source/core/text/inftxt.cxx
@@ -1942,6 +1942,12 @@ SwTwips SwTextFormatInfo::GetLineWidth()
         if (pLastTab->GetWhichPor() == PortionType::TabLeft)
             nLineWidth = nTextFrameWidth - pLastTab->GetTabPos();
     }
+    else if (GetLast() == pLastTab)
+    {   // tdf#158658 Put content after tab into margin like Word.
+        // FIXME using Width() is entirely arbitrary here, Word adds even more
+        // width but not infinitely much.
+        nLineWidth = std::max<SwTwips>(Width(), nLineWidth);
+    }
     return nLineWidth;
 }
 
diff --git a/sw/source/core/text/txttab.cxx b/sw/source/core/text/txttab.cxx
index e7141aaec538..3f72f5375000 100644
--- a/sw/source/core/text/txttab.cxx
+++ b/sw/source/core/text/txttab.cxx
@@ -70,6 +70,7 @@ sal_uInt16 SwLineInfo::NumberOfTabStops() const
 SwTabPortion *SwTextFormatter::NewTabPortion( SwTextFormatInfo &rInf, bool 
bAuto ) const
 {
     IDocumentSettingAccess const& 
rIDSA(rInf.GetTextFrame()->GetDoc().getIDocumentSettingAccess());
+    const bool bTabOverMargin = rIDSA.get(DocumentSettingId::TAB_OVER_MARGIN);
     const bool bTabOverSpacing = 
rIDSA.get(DocumentSettingId::TAB_OVER_SPACING);
     const bool bTabsRelativeToIndent = 
rIDSA.get(DocumentSettingId::TABS_RELATIVE_TO_INDENT);
 
@@ -145,7 +146,7 @@ SwTabPortion *SwTextFormatter::NewTabPortion( 
SwTextFormatInfo &rInf, bool bAuto
         // default tab stop.
         const SwTwips nOldRight = nMyRight;
         // Accept left-tabstops beyond the paragraph margin for bTabOverSpacing
-        if (bTabOverSpacing)
+        if (bTabOverSpacing || bTabOverMargin)
             nMyRight = 0;
         const SvxTabStop* pTabStop = m_aLineInf.GetTabStop( nSearchPos, 
nMyRight );
         if (!nMyRight)
@@ -419,7 +420,7 @@ bool SwTabPortion::PreFormat( SwTextFormatInfo &rInf )
             {
                 // handle this case in PostFormat
                 if ((bTabOverMargin || bTabOverSpacing) && GetTabPos() > 
rInf.Width()
-                    && (!m_bAutoTabStop || (!bTabOverMargin && rInf.X() > 
rInf.Width())))
+                    && (!m_bAutoTabStop || rInf.X() > rInf.Width()))
                 {
                     if (bTabOverMargin || GetTabPos() < nTextFrameWidth)
                     {

Reply via email to