sw table styles: Direct formatting takes precedence over table style.

Make sure we don't reset the direct formatting with the table style when
updating.

Change-Id: I07b4a687fd0403bd80d73732a66101b967398507
diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index 51631a3..f338348 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -1255,8 +1255,9 @@ public:

    void SetRowsToRepeat( SwTable &rTable, sal_uInt16 nSet );

    // AutoFormat for table/table selection.
    bool SetTableAutoFormat( const SwSelBoxes& rBoxes, const SwTableAutoFormat& rNew );
    /// AutoFormat for table/table selection.
    /// @param bResetDirect Reset direct formatting that might be applied to the cells.
    bool SetTableAutoFormat(const SwSelBoxes& rBoxes, const SwTableAutoFormat& rNew, bool bResetDirect = false);

    // Query attributes.
    bool GetTableAutoFormat( const SwSelBoxes& rBoxes, SwTableAutoFormat& rGet );
diff --git a/sw/inc/fesh.hxx b/sw/inc/fesh.hxx
index a4829e8..47fe673 100644
--- a/sw/inc/fesh.hxx
+++ b/sw/inc/fesh.hxx
@@ -725,7 +725,8 @@ public:

    /// Update the direct formatting according to the current table style.
    /// @param pTableNode Table node to update.  When nullptr, current cursor position is used.
    bool UpdateTableStyleFormatting(SwTableNode *pTableNode = nullptr);
    /// @param bResetDirect Reset direct formatting that might be applied to the cells.
    bool UpdateTableStyleFormatting(SwTableNode *pTableNode = nullptr, bool bResetDirect = false);

    bool GetTableAutoFormat( SwTableAutoFormat& rGet );

diff --git a/sw/inc/swtable.hxx b/sw/inc/swtable.hxx
index 5f645e3..14e31c8 100644
--- a/sw/inc/swtable.hxx
+++ b/sw/inc/swtable.hxx
@@ -397,6 +397,9 @@ class SW_DLLPUBLIC SwTableBox: public SwClient      //Client of FrameFormat.
    SwTableLine *pUpper;
    SwTableBox_Impl* pImpl;

    /// Do we contain any direct formatting?
    bool mbDirectFormatting;

    // In case Format contains formulas/values already,
    // a new one must be created for the new box.
    static SwTableBoxFormat* CheckBoxFormat( SwTableBoxFormat* );
@@ -404,7 +407,7 @@ class SW_DLLPUBLIC SwTableBox: public SwClient      //Client of FrameFormat.
public:
    TYPEINFO_OVERRIDE();

    SwTableBox() : pSttNd(0), pUpper(0), pImpl(0) {}
    SwTableBox() : pSttNd(0), pUpper(0), pImpl(0), mbDirectFormatting(false) {}

    SwTableBox( SwTableBoxFormat*, sal_uInt16 nLines, SwTableLine *pUp = 0 );
    SwTableBox( SwTableBoxFormat*, const SwStartNode&, SwTableLine *pUp = 0 );
@@ -421,6 +424,12 @@ public:
    SwFrameFormat* GetFrameFormat()       { return static_cast<SwFrameFormat*>(GetRegisteredIn()); }
    SwFrameFormat* GetFrameFormat() const { return const_cast<SwFrameFormat*>(static_cast<const SwFrameFormat*>(GetRegisteredIn())); }

    /// Set that this table box contains formatting that is not set by the table style.
    void SetDirectFormatting(bool bDirect) { mbDirectFormatting = bDirect; }

    /// Do we contain any direct formatting (ie. something not affected by the table style)?
    bool HasDirectFormatting() const { return mbDirectFormatting; }

    // Creates its own FrameFormat if more boxes depend on it.
    SwFrameFormat* ClaimFrameFormat();
    void ChgFrameFormat( SwTableBoxFormat *pNewFormat );
diff --git a/sw/source/core/docnode/ndtbl.cxx b/sw/source/core/docnode/ndtbl.cxx
index 5d3499b..3911d84 100644
--- a/sw/source/core/docnode/ndtbl.cxx
+++ b/sw/source/core/docnode/ndtbl.cxx
@@ -3669,19 +3669,19 @@ struct _SetAFormatTabPara
};

// Forward declare so that the Lines and Boxes can use recursion
static bool lcl_SetAFormatBox(_FndBox &, _SetAFormatTabPara *pSetPara);
static bool lcl_SetAFormatLine(_FndLine &, _SetAFormatTabPara *pPara);
static bool lcl_SetAFormatBox(_FndBox &, _SetAFormatTabPara *pSetPara, bool bResetDirect);
static bool lcl_SetAFormatLine(_FndLine &, _SetAFormatTabPara *pPara, bool bResetDirect);

static bool lcl_SetAFormatLine(_FndLine & rLine, _SetAFormatTabPara *pPara)
static bool lcl_SetAFormatLine(_FndLine & rLine, _SetAFormatTabPara *pPara, bool bResetDirect)
{
    for (auto const& it : rLine.GetBoxes())
    {
        lcl_SetAFormatBox(*it, pPara);
        lcl_SetAFormatBox(*it, pPara, bResetDirect);
    }
    return true;
}

static bool lcl_SetAFormatBox( _FndBox & rBox, _SetAFormatTabPara *pSetPara )
static bool lcl_SetAFormatBox(_FndBox & rBox, _SetAFormatTabPara *pSetPara, bool bResetDirect)
{
    if (!rBox.GetUpper()->GetUpper()) // Box on first level?
    {
@@ -3696,41 +3696,44 @@ static bool lcl_SetAFormatBox( _FndBox & rBox, _SetAFormatTabPara *pSetPara )
    if (rBox.GetBox()->GetSttNd())
    {
        SwTableBox* pSetBox = static_cast<SwTableBox*>(rBox.GetBox());
        SwDoc* pDoc = pSetBox->GetFrameFormat()->GetDoc();
        SfxItemSet aCharSet( pDoc->GetAttrPool(), 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,
                                        SwTableAutoFormat::UPDATE_CHAR, 0 );
        pSetPara->rTableFormat.UpdateToSet( nPos, aBoxSet,
                                        SwTableAutoFormat::UPDATE_BOX,
                                        pDoc->GetNumberFormatter() );
        if( aCharSet.Count() )
        if (!pSetBox->HasDirectFormatting() || bResetDirect)
        {
            sal_uLong nSttNd = pSetBox->GetSttIdx()+1;
            sal_uLong nEndNd = pSetBox->GetSttNd()->EndOfSectionIndex();
            for( ; nSttNd < nEndNd; ++nSttNd )
            if (bResetDirect)
                pSetBox->SetDirectFormatting(false);

            SwDoc* pDoc = pSetBox->GetFrameFormat()->GetDoc();
            SfxItemSet aCharSet(pDoc->GetAttrPool(), 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, SwTableAutoFormat::UPDATE_CHAR, 0);
            pSetPara->rTableFormat.UpdateToSet(nPos, aBoxSet, SwTableAutoFormat::UPDATE_BOX, pDoc->GetNumberFormatter());

            if (aCharSet.Count())
            {
                SwContentNode* pNd = pDoc->GetNodes()[ nSttNd ]->GetContentNode();
                if( pNd )
                    pNd->SetAttr( aCharSet );
                sal_uLong nSttNd = pSetBox->GetSttIdx()+1;
                sal_uLong nEndNd = pSetBox->GetSttNd()->EndOfSectionIndex();
                for (; nSttNd < nEndNd; ++nSttNd)
                {
                    SwContentNode* pNd = pDoc->GetNodes()[ nSttNd ]->GetContentNode();
                    if (pNd)
                        pNd->SetAttr(aCharSet);
                }
            }
        }

        if( aBoxSet.Count() )
        {
            if( pSetPara->pUndo &&
                SfxItemState::SET == aBoxSet.GetItemState( RES_BOXATR_FORMAT ))
                pSetPara->pUndo->SaveBoxContent( *pSetBox );
            if (aBoxSet.Count())
            {
                if (pSetPara->pUndo && SfxItemState::SET == aBoxSet.GetItemState(RES_BOXATR_FORMAT))
                    pSetPara->pUndo->SaveBoxContent( *pSetBox );

            pSetBox->ClaimFrameFormat()->SetFormatAttr( aBoxSet );
                pSetBox->ClaimFrameFormat()->SetFormatAttr(aBoxSet);
            }
        }
    }
    else
    {
        for (auto const& rpFndLine : rBox.GetLines())
        {
            lcl_SetAFormatLine( *rpFndLine, pSetPara );
            lcl_SetAFormatLine(*rpFndLine, pSetPara, bResetDirect);
        }
    }

@@ -3739,10 +3742,7 @@ static bool lcl_SetAFormatBox( _FndBox & rBox, _SetAFormatTabPara *pSetPara )
    return true;
}

/**
 * AutoFormat for the Table/TableSelection
 */
bool SwDoc::SetTableAutoFormat( const SwSelBoxes& rBoxes, const SwTableAutoFormat& rNew )
bool SwDoc::SetTableAutoFormat(const SwSelBoxes& rBoxes, const SwTableAutoFormat& rNew, bool bResetDirect)
{
    OSL_ENSURE( !rBoxes.empty(), "No valid Box list" );
    SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
@@ -3807,7 +3807,7 @@ bool SwDoc::SetTableAutoFormat( const SwSelBoxes& rBoxes, const SwTableAutoForma
        aPara.pUndo = pUndo;
        for (auto const& it : pLine->GetBoxes())
        {
            lcl_SetAFormatBox(*it, &aPara);
            lcl_SetAFormatBox(*it, &aPara, bResetDirect);
        }

        pLine->SetUpper( pSaveBox );
diff --git a/sw/source/core/docnode/ndtbl1.cxx b/sw/source/core/docnode/ndtbl1.cxx
index 797c159..8a4d953 100644
--- a/sw/source/core/docnode/ndtbl1.cxx
+++ b/sw/source/core/docnode/ndtbl1.cxx
@@ -1155,6 +1155,8 @@ void SwDoc::SetBoxAttr( const SwCursor& rCursor, const SfxPoolItem &rNew )
                pNew->SetFormatAttr( rNew );
                aFormatCmp.push_back( new SwTableFormatCmp( pOld, pNew, 0 ) );
            }

            pBox->SetDirectFormatting(true);
        }

        SwHTMLTableLayout *pTableLayout = rTable.GetHTMLTableLayout();
diff --git a/sw/source/core/frmedt/fetab.cxx b/sw/source/core/frmedt/fetab.cxx
index 5d4551c..f996e1e 100644
--- a/sw/source/core/frmedt/fetab.cxx
+++ b/sw/source/core/frmedt/fetab.cxx
@@ -1190,7 +1190,7 @@ bool SwFEShell::SetTableStyle(const SwTableAutoFormat& rStyle)
    return UpdateTableStyleFormatting(pTableNode);
}

bool SwFEShell::UpdateTableStyleFormatting(SwTableNode *pTableNode)
bool SwFEShell::UpdateTableStyleFormatting(SwTableNode *pTableNode, bool bResetDirect)
{
    if (!pTableNode)
    {
@@ -1227,7 +1227,7 @@ bool SwFEShell::UpdateTableStyleFormatting(SwTableNode *pTableNode)
    {
        SET_CURR_SHELL( this );
        StartAllAction();
        bRet = GetDoc()->SetTableAutoFormat(aBoxes, *pTableStyle);
        bRet = GetDoc()->SetTableAutoFormat(aBoxes, *pTableStyle, bResetDirect);
        DELETEZ( pLastCols );
        DELETEZ( pLastRows );
        EndAllActionAndCall();
diff --git a/sw/source/core/table/swtable.cxx b/sw/source/core/table/swtable.cxx
index 3a6abf1..a3dfb89f 100644
--- a/sw/source/core/table/swtable.cxx
+++ b/sw/source/core/table/swtable.cxx
@@ -1650,7 +1650,8 @@ SwTableBox::SwTableBox( SwTableBoxFormat* pFormat, sal_uInt16 nLines, SwTableLin
    aLines(),
    pSttNd( 0 ),
    pUpper( pUp ),
    pImpl( 0 )
    pImpl( 0 ),
    mbDirectFormatting(false)
{
    aLines.reserve( nLines );
    CheckBoxFormat( pFormat )->Add( this );
@@ -1661,7 +1662,8 @@ SwTableBox::SwTableBox( SwTableBoxFormat* pFormat, const SwNodeIndex &rIdx,
    : SwClient( 0 ),
    aLines(),
    pUpper( pUp ),
    pImpl( 0 )
    pImpl( 0 ),
    mbDirectFormatting(false)
{
    CheckBoxFormat( pFormat )->Add( this );

@@ -1681,7 +1683,8 @@ SwTableBox::SwTableBox( SwTableBoxFormat* pFormat, const SwStartNode& rSttNd, Sw
    aLines(),
    pSttNd( &rSttNd ),
    pUpper( pUp ),
    pImpl( 0 )
    pImpl( 0 ),
    mbDirectFormatting(false)
{
    CheckBoxFormat( pFormat )->Add( this );

diff --git a/sw/source/uibase/shells/textsh1.cxx b/sw/source/uibase/shells/textsh1.cxx
index 49a1dc5..3aef579 100644
--- a/sw/source/uibase/shells/textsh1.cxx
+++ b/sw/source/uibase/shells/textsh1.cxx
@@ -540,6 +540,10 @@ void SwTextShell::Execute(SfxRequest &rReq)
            // we don't want to change writing direction.
            aAttribs.erase( RES_FRAMEDIR );
            rWrtSh.ResetAttr( aAttribs );

            // also clear the direct formatting flag inside SwTableBox(es)
            GetView().GetDocShell()->GetFEShell()->UpdateTableStyleFormatting(nullptr, true);

            rReq.Done();
            break;
        }