tdf#115576 sw: fix borders for single row/col autotable styles

The 4*4 autostyle table matrix has no box format that can handle
a table with a single column or single row. So the first
and last row/column boxes need to be combined to get all
of the necessary borders.

This could easily be seen by setting one column and X rows
using the default table style - missing right border.

It could also be seen by setting one row and X columns using
Box List yellow - missing bottom border.

Change-Id: Ib2cf873b6d4e10ba5145e680ea7b3e2e3aea3970
Reviewed-on: https://gerrit.libreoffice.org/82998
Tested-by: Jenkins
Reviewed-by: Justin Luth <justin_luth@sil.org>
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
diff --git a/sw/inc/tblafmt.hxx b/sw/inc/tblafmt.hxx
index 3e83829..2d87284 100644
--- a/sw/inc/tblafmt.hxx
+++ b/sw/inc/tblafmt.hxx
@@ -209,7 +209,8 @@ public:

    void UpdateFromSet( sal_uInt8 nPos, const SfxItemSet& rSet,
                                SwTableAutoFormatUpdateFlags eFlags, SvNumberFormatter const * );
    void UpdateToSet( sal_uInt8 nPos, SfxItemSet& rSet, SwTableAutoFormatUpdateFlags eFlags,
    void UpdateToSet( const sal_uInt8 nPos, const bool bSingleRowTable, const bool bSingleColTable,
                        SfxItemSet& rSet, SwTableAutoFormatUpdateFlags eFlags,
                        SvNumberFormatter* ) const ;

    void RestoreTableProperties(SwTable &table) const;
diff --git a/sw/qa/extras/htmlimport/data/reqif-table.xhtml b/sw/qa/extras/htmlimport/data/reqif-table.xhtml
index 242201d..a169a07 100644
--- a/sw/qa/extras/htmlimport/data/reqif-table.xhtml
+++ b/sw/qa/extras/htmlimport/data/reqif-table.xhtml
@@ -2,14 +2,51 @@
<reqif-xhtml:table width="100%" cellpadding="4" cellspacing="0">
	<reqif-xhtml:col width="128*"/>

	<reqif-xhtml:col width="128*"/>

	<reqif-xhtml:tr valign="top">
		<reqif-xhtml:td><reqif-xhtml:p align="left" style="text-decoration: none">
			<reqif-xhtml:br/>

			</reqif-xhtml:p>
		</reqif-xhtml:td>
	</reqif-xhtml:tr>
</reqif-xhtml:table>

<reqif-xhtml:p>Table 2.</reqif-xhtml:p>

<reqif-xhtml:table width="100%" cellpadding="4" cellspacing="0">
	<reqif-xhtml:tr valign="top">
		<reqif-xhtml:td><reqif-xhtml:p align="left" style="text-decoration: none">
			<reqif-xhtml:br/>

			</reqif-xhtml:p>
		</reqif-xhtml:td>
		<reqif-xhtml:td><reqif-xhtml:p align="left" style="text-decoration: none">
			<reqif-xhtml:br/>

			</reqif-xhtml:p>
		</reqif-xhtml:td>
		<reqif-xhtml:td><reqif-xhtml:p align="left" style="text-decoration: none">
			<reqif-xhtml:br/>

			</reqif-xhtml:p>
		</reqif-xhtml:td>
		<reqif-xhtml:td><reqif-xhtml:p align="left" style="text-decoration: none">
			<reqif-xhtml:br/>

			</reqif-xhtml:p>
		</reqif-xhtml:td>
		<reqif-xhtml:td><reqif-xhtml:p align="left" style="text-decoration: none">
			<reqif-xhtml:br/>

			</reqif-xhtml:p>
		</reqif-xhtml:td>
	</reqif-xhtml:tr>
</reqif-xhtml:table>

<reqif-xhtml:p>Table 3.</reqif-xhtml:p>

<reqif-xhtml:table width="100%" cellpadding="4" cellspacing="0">
	<reqif-xhtml:tr valign="top">
		<reqif-xhtml:td><reqif-xhtml:p align="left" style="text-decoration: none">
			<reqif-xhtml:br/>

@@ -22,6 +59,15 @@

			</reqif-xhtml:p>
		</reqif-xhtml:td>
	</reqif-xhtml:tr>
	<reqif-xhtml:tr valign="top">
		<reqif-xhtml:td><reqif-xhtml:p align="left" style="text-decoration: none">
			<reqif-xhtml:br/>

			</reqif-xhtml:p>
		</reqif-xhtml:td>
	</reqif-xhtml:tr>
	<reqif-xhtml:tr valign="top">
		<reqif-xhtml:td><reqif-xhtml:p align="left" style="text-decoration: none">
			<reqif-xhtml:br/>

diff --git a/sw/qa/extras/htmlimport/htmlimport.cxx b/sw/qa/extras/htmlimport/htmlimport.cxx
index 6ab84cf..714eb6d4 100644
--- a/sw/qa/extras/htmlimport/htmlimport.cxx
+++ b/sw/qa/extras/htmlimport/htmlimport.cxx
@@ -316,17 +316,25 @@ DECLARE_HTMLIMPORT_TEST(testReqIfBr, "reqif-br.xhtml")

DECLARE_HTMLIMPORT_TEST(testReqIfTable, "reqif-table.xhtml")
{
    // to see this: soffice --infilter="HTML (StarWriter):xhtmlns=reqif-xhtml" sw/qa/extras/htmlimport/data/reqif-table.xhtml
    // Load a table with xhtmlns=reqif-xhtml filter param.
    uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
    uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(),
                                                    uno::UNO_QUERY);
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), xTables->getCount());
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), xTables->getCount());
    uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
    uno::Reference<text::XTextRange> xCell(xTable->getCellByName("A1"), uno::UNO_QUERY);
    auto aBorder = getProperty<table::BorderLine2>(xCell, "TopBorder");
    // This was 0, tables had no borders, even if the default autoformat has
    // borders and the markup allows no custom borders.
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(18), aBorder.LineWidth);
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Top Border", static_cast<sal_uInt32>(18), aBorder.LineWidth);
    aBorder = getProperty<table::BorderLine2>(xCell, "BottomBorder");
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Bottom Border", static_cast<sal_uInt32>(18), aBorder.LineWidth);
    aBorder = getProperty<table::BorderLine2>(xCell, "LeftBorder");
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Left Border", static_cast<sal_uInt32>(18), aBorder.LineWidth);
    aBorder = getProperty<table::BorderLine2>(xCell, "RightBorder");
    // This was 0. Single column tables had no right border.  tdf#115576
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Right Border", static_cast<sal_uInt32>(18), aBorder.LineWidth);
}

DECLARE_HTMLIMPORT_TEST(testImageSize, "image-size.html")
diff --git a/sw/source/core/doc/tblafmt.cxx b/sw/source/core/doc/tblafmt.cxx
index 1954bc3b..765154b3e 100644
--- a/sw/source/core/doc/tblafmt.cxx
+++ b/sw/source/core/doc/tblafmt.cxx
@@ -559,7 +559,7 @@ void SwTableAutoFormat::UpdateFromSet( sal_uInt8 nPos,
    // we cannot handle the rest, that's specific to StarCalc
}

void SwTableAutoFormat::UpdateToSet(sal_uInt8 nPos, SfxItemSet& rSet,
void SwTableAutoFormat::UpdateToSet(const sal_uInt8 nPos, const bool bSingleRowTable, const bool bSingleColTable, SfxItemSet& rSet,
                                 SwTableAutoFormatUpdateFlags eFlags, SvNumberFormatter* pNFormatr) const
{
    const SwBoxAutoFormat& rChg = GetBoxFormat( nPos );
@@ -617,7 +617,26 @@ void SwTableAutoFormat::UpdateToSet(sal_uInt8 nPos, SfxItemSet& rSet,
    {
        if( IsFrame() )
        {
            rSet.Put( rChg.GetBox() );
            SvxBoxItem aAutoFormatBox = rChg.GetBox();

            // No format box is adequate to specify the borders of single column/row tables, so combine first/last.
            if ( bSingleRowTable || bSingleColTable )
            {
                sal_uInt8 nSingleRowOrColumnId = 15; //LAST_ROW_END_COLUMN
                if ( !bSingleRowTable )
                    nSingleRowOrColumnId = nPos + 3;  //LAST COLUMN (3, 7, 11, 15)
                else if ( !bSingleColTable )
                    nSingleRowOrColumnId = nPos + 12; //LAST ROW (12, 13, 14, 15)

                assert( nSingleRowOrColumnId < 16 );
                const SvxBoxItem aLastAutoFormatBox( GetBoxFormat(nSingleRowOrColumnId).GetBox() );
                if ( bSingleRowTable )
                    aAutoFormatBox.SetLine( aLastAutoFormatBox.GetLine(SvxBoxItemLine::BOTTOM), SvxBoxItemLine::BOTTOM );
                if ( bSingleColTable )
                    aAutoFormatBox.SetLine( aLastAutoFormatBox.GetLine(SvxBoxItemLine::RIGHT), SvxBoxItemLine::RIGHT );
            }

            rSet.Put( aAutoFormatBox );
// FIXME - uncomment the lines to put the diagonal line items
//            rSet.Put( rChg.GetTLBR() );
//            rSet.Put( rChg.GetBLTR() );
diff --git a/sw/source/core/docnode/ndtbl.cxx b/sw/source/core/docnode/ndtbl.cxx
index 8a6cc42..00e249b 100644
--- a/sw/source/core/docnode/ndtbl.cxx
+++ b/sw/source/core/docnode/ndtbl.cxx
@@ -162,7 +162,8 @@ lcl_SetDfltBoxAttr(SwTableBox& rBox, DfltBoxAttrList_t & rBoxFormatArr,
        pNewTableBoxFormat->SetFormatAttr( pBoxFrameFormat->GetAttrSet().Get( RES_FRM_SIZE ) );

        if( pAutoFormat )
            pAutoFormat->UpdateToSet( nId, const_cast<SfxItemSet&>(static_cast<SfxItemSet const &>(pNewTableBoxFormat->GetAttrSet())),
            pAutoFormat->UpdateToSet( nId, false, false,
                                    const_cast<SfxItemSet&>(static_cast<SfxItemSet const &>(pNewTableBoxFormat->GetAttrSet())),
                                    SwTableAutoFormatUpdateFlags::Box,
                                    pDoc->GetNumberFormatter() );
        else
@@ -190,12 +191,13 @@ static SwTableBoxFormat *lcl_CreateDfltBoxFormat( SwDoc &rDoc, std::vector<SwTab

static SwTableBoxFormat *lcl_CreateAFormatBoxFormat( SwDoc &rDoc, std::vector<SwTableBoxFormat*> &rBoxFormatArr,
                                    const SwTableAutoFormat& rAutoFormat,
                                    sal_uInt16 nCols, sal_uInt8 nId )
                                    const sal_uInt16 nRows, const sal_uInt16 nCols, sal_uInt8 nId )
{
    if( !rBoxFormatArr[nId] )
    {
        SwTableBoxFormat* pBoxFormat = rDoc.MakeTableBoxFormat();
        rAutoFormat.UpdateToSet( nId, const_cast<SfxItemSet&>(static_cast<SfxItemSet const &>(pBoxFormat->GetAttrSet())),
        rAutoFormat.UpdateToSet( nId, nRows==1, nCols==1,
                                const_cast<SfxItemSet&>(static_cast<SfxItemSet const &>(pBoxFormat->GetAttrSet())),
                                SwTableAutoFormatUpdateFlags::Box,
                                rDoc.GetNumberFormatter( ) );
        if( USHRT_MAX != nCols )
@@ -488,13 +490,13 @@ const SwTable* SwDoc::InsertTable( const SwInsertTableOptions& rInsTableOpts,
            {
                sal_uInt8 nId = SwTableAutoFormat::CountPos(i, nCols, n, nRows);
                pBoxF = ::lcl_CreateAFormatBoxFormat( *this, aBoxFormatArr, *pTAFormat,
                                                nCols, nId );
                                                nRows, nCols, nId );

                // Set the Paragraph/Character Attributes if needed
                if( pTAFormat->IsFont() || pTAFormat->IsJustify() )
                {
                    aCharSet.ClearItem();
                    pTAFormat->UpdateToSet( nId, aCharSet,
                    pTAFormat->UpdateToSet( nId, nRows==1, nCols==1, aCharSet,
                                        SwTableAutoFormatUpdateFlags::Char, nullptr );
                    if( aCharSet.Count() )
                        GetNodes()[ aNdIdx.GetIndex()+1 ]->GetContentNode()->
@@ -786,14 +788,14 @@ const SwTable* SwDoc::TextToTable( const SwInsertTableOptions& rInsTableOpts,
                    {
                        bChgSz = nullptr == (*aBoxFormatArr2)[ nId ];
                        pBoxF = ::lcl_CreateAFormatBoxFormat( *this, *aBoxFormatArr2,
                                                *pTAFormat, USHRT_MAX, nId );
                                                *pTAFormat, USHRT_MAX, USHRT_MAX, nId );
                    }

                    // Set Paragraph/Character Attributes if needed
                    if( pTAFormat->IsFont() || pTAFormat->IsJustify() )
                    {
                        aCharSet.ClearItem();
                        pTAFormat->UpdateToSet( nId, aCharSet,
                        pTAFormat->UpdateToSet( nId, nRows==1, nCols==1, aCharSet,
                                            SwTableAutoFormatUpdateFlags::Char, nullptr );
                        if( aCharSet.Count() )
                        {
@@ -3588,10 +3590,11 @@ struct SetAFormatTabPara
    SwUndoTableAutoFormat* pUndo;
    sal_uInt16 nEndBox, nCurBox;
    sal_uInt8 nAFormatLine, nAFormatBox;
    bool bSingleRowTable;

    explicit SetAFormatTabPara( const SwTableAutoFormat& rNew )
        : rTableFormat( const_cast<SwTableAutoFormat&>(rNew) ), pUndo( nullptr ),
        nEndBox( 0 ), nCurBox( 0 ), nAFormatLine( 0 ), nAFormatBox( 0 )
        nEndBox( 0 ), nCurBox( 0 ), nAFormatLine( 0 ), nAFormatBox( 0 ), bSingleRowTable(false)
    {}
};

@@ -3616,7 +3619,7 @@ static bool lcl_SetAFormatBox(FndBox_ & rBox, SetAFormatTabPara *pSetPara, bool 
            pSetPara->nAFormatBox = 0;
        else if( pSetPara->nCurBox == pSetPara->nEndBox )
            pSetPara->nAFormatBox = 3;
        else
        else //Even column(1) or Odd column(2)
            pSetPara->nAFormatBox = static_cast<sal_uInt8>(1 + ((pSetPara->nCurBox-1) & 1));
    }

@@ -3632,8 +3635,10 @@ static bool lcl_SetAFormatBox(FndBox_ & rBox, SetAFormatTabPara *pSetPara, bool 
            SfxItemSet aCharSet(pDoc->GetAttrPool(), svl::Items<RES_CHRATR_BEGIN, RES_PARATR_LIST_END-1>{});
            SfxItemSet aBoxSet(pDoc->GetAttrPool(), aTableBoxSetRange);
            sal_uInt8 nPos = pSetPara->nAFormatLine * 4 + pSetPara->nAFormatBox;
            pSetPara->rTableFormat.UpdateToSet(nPos, aCharSet, SwTableAutoFormatUpdateFlags::Char, nullptr);
            pSetPara->rTableFormat.UpdateToSet(nPos, aBoxSet, SwTableAutoFormatUpdateFlags::Box, pDoc->GetNumberFormatter());
            const bool bSingleRowTable = pSetPara->bSingleRowTable;
            const bool bSingleColTable = pSetPara->nEndBox == 0;
            pSetPara->rTableFormat.UpdateToSet(nPos, bSingleRowTable, bSingleColTable, aCharSet, SwTableAutoFormatUpdateFlags::Char, nullptr);
            pSetPara->rTableFormat.UpdateToSet(nPos, bSingleRowTable, bSingleColTable, aBoxSet, SwTableAutoFormatUpdateFlags::Box, pDoc->GetNumberFormatter());

            if (aCharSet.Count())
            {
@@ -3658,10 +3663,15 @@ static bool lcl_SetAFormatBox(FndBox_ & rBox, SetAFormatTabPara *pSetPara, bool 
    }
    else
    {
        // Not sure how this situation can occur, but apparently we have some kind of table in table.
        // I am guessing at how to best handle singlerow in this situation.
        const bool bOrigSingleRowTable = pSetPara->bSingleRowTable;
        pSetPara->bSingleRowTable = rBox.GetLines().size() == 1;
        for (auto const& rpFndLine : rBox.GetLines())
        {
            lcl_SetAFormatLine(*rpFndLine, pSetPara, bResetDirect);
        }
        pSetPara->bSingleRowTable = bOrigSingleRowTable;
    }

    if (!rBox.GetUpper()->GetUpper()) // a BaseLine
@@ -3717,6 +3727,7 @@ bool SwDoc::SetTableAutoFormat(const SwSelBoxes& rBoxes, const SwTableAutoFormat

    SetAFormatTabPara aPara( rNew );
    FndLines_t& rFLns = pFndBox->GetLines();
    aPara.bSingleRowTable = rFLns.size() == 1;

    for (FndLines_t::size_type n = 0; n < rFLns.size(); ++n)
    {
diff --git a/sw/source/filter/html/htmltab.cxx b/sw/source/filter/html/htmltab.cxx
index f04aa01..0d659d7 100644
--- a/sw/source/filter/html/htmltab.cxx
+++ b/sw/source/filter/html/htmltab.cxx
@@ -1478,7 +1478,7 @@ void HTMLTable::FixFrameFormat( SwTableBox *pBox,
            if (pTableFormat)
            {
                sal_uInt8 nPos = SwTableAutoFormat::CountPos(nCol, m_nCols, nRow, m_nRows);
                pTableFormat->UpdateToSet(nPos,
                pTableFormat->UpdateToSet(nPos, m_nRows==1, m_nCols==1,
                                          const_cast<SfxItemSet&>(static_cast<SfxItemSet const&>(
                                              pFrameFormat->GetAttrSet())),
                                          SwTableAutoFormatUpdateFlags::Box,