[Libreoffice-commits] core.git: sw/qa sw/source

Justin Luth (via logerrit) logerrit at kemper.freedesktop.org
Wed Jun 16 14:54:29 UTC 2021


 sw/qa/extras/ooxmlexport/ooxmlexport16.cxx |    4 +-
 sw/source/core/text/inftxt.hxx             |    3 --
 sw/source/core/text/txttab.cxx             |   41 +++++++++++++++++++++++------
 3 files changed, 36 insertions(+), 12 deletions(-)

New commits:
commit c54de8cca177154d267238ed6d0b6cb4f3f86c8d
Author:     Justin Luth <justin_luth at sil.org>
AuthorDate: Tue Jun 8 10:19:36 2021 +0200
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Wed Jun 16 16:53:47 2021 +0200

    tdf#142404 DOCX c15: line full before out-of-bounds TabOverSpacing
    
    MS Word 2016 does something very weird. It attaches a
    TabOverMargin to the previous word, and pulls it down to a new line.
    Well, I don't think we want to attempt anything silly like that,
    but at least we can have the tab itself start on the new line
    (and thus take up the whole line).
    This seems to be true only for a left-tab.
    The other tabs have a different kind of strangeness
    that I haven't identified yet.
    
    In order to do that, when we request a tabstop position,
    we must query a tabstop beyond the end margin.
    So modify the GetTabStop function to allow for
    not checking against an nRight position (when passed a zero).
    
    This is complicated by the function's ability to ALWAYS
    return the first tabstop - even if it is past the given
    right-most edge. So I made nRight modifiable,
    so that in this case, it isn't considered to be past
    the right edge. That is fine for both cases where
    this function is used.
    
    It is a bit ugly, but I don't see how to make it cleaner,
    when these inherent complications are already built-in.
    
    This also has an impact on older DOCX, but the impact
    is still valid. (In those, the entire paragraph
    extends past the end in Word. With this patch, at
    least the first line becomes more than just an
    auto-tabstop.)
    
    Change-Id: I42791a959aea2932b5776789ba45307fbca41a5f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/116878
    Tested-by: Jenkins
    Reviewed-by: Justin Luth <justin_luth at sil.org>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>

diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx
index b550e62ef6a2..8ab528c6307c 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx
@@ -252,9 +252,9 @@ DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testTdf142404_tabOverSpacingC15, "tdf142404_
     // Pages 2/3 are TabOverMargin - in this particular case tabs should not go over margin.
     CPPUNIT_ASSERT_EQUAL(OUString("TabOverflow does what?"), parseDump("//page[3]/body/txt[2]/Text[1]", "Portion"));
     // Not 1 line high (Word 2010 DOCX and ODT), or 4 lines high (prev LO DOCX),
-    // but 3 lines high (8 lines high in Word 2016 because of the same weirdness as previous test).
+    // but 8 lines high.
     nHeight = parseDump("//page[3]/body/txt[2]/infos/bounds", "height").toInt32();
-    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("3 lines high (but 8 in Word)", 242*3, nHeight, 121);
+    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("8 lines high", 242*8, nHeight, 121);
 }
 
 DECLARE_OOXMLEXPORT_TEST(testTdf139580, "tdf139580.odt")
diff --git a/sw/source/core/text/inftxt.hxx b/sw/source/core/text/inftxt.hxx
index 19d730d02e5c..4d5bb0651163 100644
--- a/sw/source/core/text/inftxt.hxx
+++ b/sw/source/core/text/inftxt.hxx
@@ -75,8 +75,7 @@ class SwLineInfo
     ~SwLineInfo();
 public:
     // #i24363# tab stops relative to indent - returns the tab stop following nSearchPos or NULL
-    const SvxTabStop *GetTabStop( const SwTwips nSearchPos,
-                                 const SwTwips nRight ) const;
+    const SvxTabStop* GetTabStop(const SwTwips nSearchPos, SwTwips& nRight) const;
     const SvxLineSpacingItem *GetLineSpacing() const { return m_pSpace; }
     sal_uInt16 GetDefTabStop() const { return m_nDefTabStop; }
     void SetDefTabStop( sal_uInt16 nNew ) const
diff --git a/sw/source/core/text/txttab.cxx b/sw/source/core/text/txttab.cxx
index 101c63cde87e..565c660b23be 100644
--- a/sw/source/core/text/txttab.cxx
+++ b/sw/source/core/text/txttab.cxx
@@ -40,16 +40,24 @@
  * If the tab stop is outside the print area, we
  * return 0 if it is not the first tab stop.
  */
-const SvxTabStop *SwLineInfo::GetTabStop( const SwTwips nSearchPos, const SwTwips nRight ) const
+const SvxTabStop* SwLineInfo::GetTabStop(const SwTwips nSearchPos, SwTwips& nRight) const
 {
     for( sal_uInt16 i = 0; i < m_pRuler->Count(); ++i )
     {
         const SvxTabStop &rTabStop = m_pRuler->operator[](i);
-        if( rTabStop.GetTabPos() > SwTwips(nRight) )
+        if (nRight && rTabStop.GetTabPos() > nRight)
+        {
+            // Consider the first tabstop to always be in-bounds.
+            if (!i)
+                nRight = rTabStop.GetTabPos();
             return i ? nullptr : &rTabStop;
-
+        }
         if( rTabStop.GetTabPos() > nSearchPos )
+        {
+            if (!i && !nRight)
+                nRight = rTabStop.GetTabPos();
             return &rTabStop;
+        }
     }
     return nullptr;
 }
@@ -61,6 +69,10 @@ sal_uInt16 SwLineInfo::NumberOfTabStops() const
 
 SwTabPortion *SwTextFormatter::NewTabPortion( SwTextFormatInfo &rInf, bool bAuto ) const
 {
+    IDocumentSettingAccess const& rIDSA(rInf.GetTextFrame()->GetDoc().getIDocumentSettingAccess());
+    const bool bTabOverSpacing = rIDSA.get(DocumentSettingId::TAB_OVER_SPACING);
+    const bool bTabsRelativeToIndent = rIDSA.get(DocumentSettingId::TABS_RELATIVE_TO_INDENT);
+
     // Update search location - since Center/Decimal tabstops' width is dependent on the following text.
     SwTabPortion* pTmpLastTab = rInf.GetLastTab();
     if (pTmpLastTab && (pTmpLastTab->IsTabCenterPortion() || pTmpLastTab->IsTabDecimalPortion()))
@@ -78,8 +90,6 @@ SwTabPortion *SwTextFormatter::NewTabPortion( SwTextFormatInfo &rInf, bool bAuto
         // nTabLeft: The absolute value, the tab stops are relative to: Tabs origin.
 
         // #i91133#
-        const bool bTabsRelativeToIndent =
-            m_pFrame->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::TABS_RELATIVE_TO_INDENT);
         const SwTwips nTabLeft = bRTL
                                  ? m_pFrame->getFrameArea().Right() -
                                    ( bTabsRelativeToIndent ? GetTabLeft() : 0 )
@@ -132,8 +142,15 @@ SwTabPortion *SwTextFormatter::NewTabPortion( SwTextFormatInfo &rInf, bool bAuto
         // any hard set tab stops:
         // Note: If there are no user defined tab stops, there is always a
         // default tab stop.
+        const SwTwips nOldRight = nMyRight;
+        // Accept left-tabstops beyond the paragraph margin for bTabOverSpacing
+        if (bTabOverSpacing)
+            nMyRight = 0;
         const SvxTabStop* pTabStop = m_aLineInf.GetTabStop( nSearchPos, nMyRight );
-        if ( pTabStop )
+        if (!nMyRight)
+            nMyRight = nOldRight;
+        if (pTabStop &&
+            (pTabStop->GetTabPos() <= nMyRight || pTabStop->GetAdjustment() == SvxTabAdjust::Left))
         {
             cFill = ' ' != pTabStop->GetFill() ? pTabStop->GetFill() : 0;
             cDec = pTabStop->GetDecimal();
@@ -179,6 +196,7 @@ SwTabPortion *SwTextFormatter::NewTabPortion( SwTextFormatInfo &rInf, bool bAuto
             }
             cFill = 0;
             eAdj = SvxTabAdjust::Left;
+            pTabStop = nullptr;
         }
 
         // #i115705# - correction and refactoring:
@@ -330,6 +348,7 @@ bool SwTabPortion::PreFormat( SwTextFormatInfo &rInf )
     const bool bTabOverflow = rIDSA.get(DocumentSettingId::TAB_OVERFLOW);
     const bool bTabOverMargin = rIDSA.get(DocumentSettingId::TAB_OVER_MARGIN);
     const bool bTabOverSpacing = rIDSA.get(DocumentSettingId::TAB_OVER_SPACING);
+    const sal_Int32 nTextFrameWidth = rInf.GetTextFrame()->getFrameArea().Width();
 
     // The minimal width of a tab is one blank at least.
     // #i37686# In compatibility mode, the minimum width
@@ -385,11 +404,17 @@ bool SwTabPortion::PreFormat( SwTextFormatInfo &rInf )
                 if ((bTabOverMargin || bTabOverSpacing) && GetTabPos() > rInf.Width()
                     && (!m_bAutoTabStop || (!bTabOverMargin && rInf.X() > rInf.Width())))
                 {
-                    if (bTabOverMargin || GetTabPos() < rInf.GetTextFrame()->getFrameArea().Width())
+                    if (bTabOverMargin || GetTabPos() < nTextFrameWidth)
                     {
                         rInf.SetLastTab(this);
                         break;
                     }
+                    else
+                    {
+                        assert(!bTabOverMargin && bTabOverSpacing && GetTabPos() >= nTextFrameWidth);
+                        bFull = true;
+                        break;
+                    }
                 }
 
                 PrtWidth( o3tl::narrowing<sal_uInt16>(GetTabPos() - rInf.X()) );
@@ -401,7 +426,7 @@ bool SwTabPortion::PreFormat( SwTextFormatInfo &rInf )
                 bool bAtParaEnd = rInf.GetIdx() + GetLen() == TextFrameIndex(rInf.GetText().getLength());
                 if ( bFull && bTabCompat &&
                      ( ( bTabOverflow && ( rInf.IsTabOverflow() || !m_bAutoTabStop ) ) || bAtParaEnd ) &&
-                     GetTabPos() >= rInf.GetTextFrame()->getFrameArea().Width() )
+                     GetTabPos() >= nTextFrameWidth)
                 {
                     bFull = false;
                     if ( bTabOverflow && !m_bAutoTabStop )


More information about the Libreoffice-commits mailing list