import different first page header/footer from doc

When a Word section has a different first page header/footer,
this used to be imported into LO as a chain of two page styles.
Now that LO supports a single page style with different first page
header/footer we can import to that.

This change also incidentally fixes fdo#57908.
bnc#654230 had the same underlying problem, so the workaround committed
for that (which includes comments expressing lack of understanding)
has been removed.

Change-Id: I6df7e9abc8f2a327a3b33e06322ca943f6f24605
Reviewed-on: https://gerrit.libreoffice.org/2065
Reviewed-by: Tor Lillqvist <tml@iki.fi>
Tested-by: Tor Lillqvist <tml@iki.fi>
diff --git a/sw/source/filter/ww8/wrtw8sty.cxx b/sw/source/filter/ww8/wrtw8sty.cxx
index b0e4e92..3d40f4e 100644
--- a/sw/source/filter/ww8/wrtw8sty.cxx
+++ b/sw/source/filter/ww8/wrtw8sty.cxx
@@ -1587,7 +1587,7 @@ void MSWordExportBase::SectionProperties( const WW8_SepInfo& rSepInfo, WW8_PdAtt
    // a different header/footer for the first page.  The same effect can be
    // achieved by chaining two page styles together (SwPageDesc::GetFollow)
    // which are identical except for header/footer.
    // The latter method is still used by the doc/docx import filter.
    // The latter method was previously used by the doc/docx import filter.
    // In both of these cases, we emit a single Word section with different
    // first page header/footer.
    const SwFrmFmt* pPdFirstPgFmt = &pPd->GetFirst();
@@ -1622,12 +1622,6 @@ void MSWordExportBase::SectionProperties( const WW8_SepInfo& rSepInfo, WW8_PdAtt
            }
        }

        // The code above tries to detect if this is first page headers/footers,
        // but it doesn't work even for quite trivial testcases. As I don't actually
        // understand that code, I'll keep it. The simple and (at least for me) reliable way
        // to detect for first page seems to be just RES_POOLPAGE_FIRST.
        if( pPd->GetPoolFmtId() == RES_POOLPAGE_FIRST )
            titlePage = true;
        if( titlePage )
            AttrOutput().SectionTitlePage();

diff --git a/sw/source/filter/ww8/ww8par.cxx b/sw/source/filter/ww8/ww8par.cxx
index fdef14c..2659624 100644
--- a/sw/source/filter/ww8/ww8par.cxx
+++ b/sw/source/filter/ww8/ww8par.cxx
@@ -1932,27 +1932,11 @@ bool SwWW8ImplReader::HasOwnHeaderFooter(sal_uInt8 nWhichItems, sal_uInt8 grpfIh
    return false;
}

void SwWW8ImplReader::Read_HdFt(bool bIsTitle, int nSect,
    const SwPageDesc *pPrev, const wwSection &rSection)
void SwWW8ImplReader::Read_HdFt(int nSect, const SwPageDesc *pPrev,
    const wwSection &rSection)
{
    sal_uInt8 nWhichItems = 0;
    SwPageDesc *pPD = 0;
    if (!bIsTitle)
    {
        nWhichItems =
            rSection.maSep.grpfIhdt & ~(WW8_HEADER_FIRST | WW8_FOOTER_FIRST);
        pPD = rSection.mpPage;
    }
    else
    {
        // Always read title page header/footer data - it could be used by following sections
        nWhichItems = ( WW8_HEADER_FIRST | WW8_FOOTER_FIRST );

        pPD = rSection.mpTitlePage;
    }

    sal_uInt8 grpfIhdt = rSection.maSep.grpfIhdt;

    SwPageDesc *pPD = rSection.mpPage;

    if( pHdFt )
    {
@@ -1962,7 +1946,7 @@ void SwWW8ImplReader::Read_HdFt(bool bIsTitle, int nSect,

        for( sal_uInt8 nI = 0x20; nI; nI >>= 1, nNumber-- )
        {
            if (nI & nWhichItems)
            if (nI & grpfIhdt)
            {
                bool bOk = true;
                if( bVer67 )
@@ -1975,10 +1959,14 @@ void SwWW8ImplReader::Read_HdFt(bool bIsTitle, int nSect,

                bool bUseLeft
                    = (nI & ( WW8_HEADER_EVEN | WW8_FOOTER_EVEN )) ? true: false;
                bool bUseFirst
                    = (nI & ( WW8_HEADER_FIRST | WW8_FOOTER_FIRST )) ? true: false;
                bool bFooter
                    = (nI & ( WW8_FOOTER_EVEN | WW8_FOOTER_ODD | WW8_FOOTER_FIRST )) ? true: false;

                SwFrmFmt& rFmt = bUseLeft ? pPD->GetLeft() : pPD->GetMaster();
                SwFrmFmt& rFmt = bUseLeft ? pPD->GetLeft()
                    : bUseFirst ? pPD->GetFirst()
                    : pPD->GetMaster();

                SwFrmFmt* pHdFtFmt;
                if (bFooter)
@@ -1989,6 +1977,8 @@ void SwWW8ImplReader::Read_HdFt(bool bIsTitle, int nSect,
                        pPD->GetMaster().SetFmtAttr(SwFmtFooter(true));
                    if (bUseLeft)
                        pPD->GetLeft().SetFmtAttr(SwFmtFooter(true));
                    if (bUseFirst)
                        pPD->GetFirst().SetFmtAttr(SwFmtFooter(true));
                    pHdFtFmt = const_cast<SwFrmFmt*>(rFmt.GetFooter().GetFooterFmt());
                }
                else
@@ -1999,6 +1989,8 @@ void SwWW8ImplReader::Read_HdFt(bool bIsTitle, int nSect,
                        pPD->GetMaster().SetFmtAttr(SwFmtHeader(true));
                    if (bUseLeft)
                        pPD->GetLeft().SetFmtAttr(SwFmtHeader(true));
                    if (bUseFirst)
                        pPD->GetFirst().SetFmtAttr(SwFmtHeader(true));
                    pHdFtFmt = const_cast<SwFrmFmt*>(rFmt.GetHeader().GetHeaderFmt());
                }

@@ -2042,18 +2034,10 @@ void wwSectionManager::SetHdFt(wwSection &rSection, int nSect,
    OSL_ENSURE(rSection.mpPage, "makes no sense to call with a main page");
    if (rSection.mpPage)
    {
        mrReader.Read_HdFt(false, nSect, pPrevious ? pPrevious->mpPage : 0,
        mrReader.Read_HdFt(nSect, pPrevious ? pPrevious->mpPage : 0,
                rSection);
    }

    if (rSection.mpTitlePage)
    {
        // 2 Pagedescs noetig: 1.Seite und folgende
        // 1. Seite einlesen
        mrReader.Read_HdFt(true, nSect, pPrevious ? pPrevious->mpTitlePage : 0,
            rSection);
    }

    // Kopf / Fuss - Index Updaten
    // Damit der Index auch spaeter noch stimmt
    if (mrReader.pHdFt)
@@ -3730,9 +3714,9 @@ void SwWW8ImplReader::DeleteStk(SwFltControlStack* pStck)
}

void wwSectionManager::SetSegmentToPageDesc(const wwSection &rSection,
    bool bTitlePage, bool bIgnoreCols)
    bool bIgnoreCols)
{
    SwPageDesc &rPage = bTitlePage ? *rSection.mpTitlePage : *rSection.mpPage;
    SwPageDesc &rPage = *rSection.mpPage;

    SetNumberingType(rSection, rPage);

@@ -3756,26 +3740,14 @@ void wwSectionManager::SetSegmentToPageDesc(const wwSection &rSection,
        }
    }
    wwULSpaceData aULData;
    GetPageULData(rSection, bTitlePage, aULData);
    GetPageULData(rSection, aULData);
    SetPageULSpaceItems(rFmt, aULData, rSection);

    SetPage(rPage, rFmt, rSection, bIgnoreCols);

    bool bSetBorder = false;
    switch (rSection.maSep.pgbApplyTo)
    {
        case 0:
        case 3:
            bSetBorder = true;
            break;
        case 1:
            bSetBorder = bTitlePage;
            break;
        case 2:
            bSetBorder = !bTitlePage;
            break;
    }
    if (bSetBorder)
    if (rSection.maSep.pgbApplyTo & 1)
        mrReader.SetPageBorder(rPage.GetFirst(), rSection);
    if (rSection.maSep.pgbApplyTo & 2)
        mrReader.SetPageBorder(rFmt, rSection);

    mrReader.SetDocumentGrid(rFmt, rSection);
@@ -3793,16 +3765,12 @@ void wwSectionManager::SetUseOn(wwSection &rSection)
    UseOnPage eUse = eUseBase;
    if (!bEven)
        eUse = (UseOnPage)(eUse | nsUseOnPage::PD_HEADERSHARE | nsUseOnPage::PD_FOOTERSHARE);
    eUse = (UseOnPage)(eUse | nsUseOnPage::PD_FIRSTSHARE);
    if (!rSection.HasTitlePage())
        eUse = (UseOnPage)(eUse | nsUseOnPage::PD_FIRSTSHARE);

    OSL_ENSURE(rSection.mpPage, "Makes no sense to call me with no pages to set");
    if (rSection.mpPage)
        rSection.mpPage->WriteUseOn(eUse);
    if (rSection.mpTitlePage)
    {
        rSection.mpTitlePage->WriteUseOn(
            (UseOnPage) (eUseBase | nsUseOnPage::PD_HEADERSHARE | nsUseOnPage::PD_FOOTERSHARE | nsUseOnPage::PD_FIRSTSHARE));
    }
}

//Set the page descriptor on this node, handle the different cases for a text
@@ -3835,32 +3803,11 @@ void GiveNodePageDesc(SwNodeIndex &rIdx, const SwFmtPageDesc &rPgDesc,
    }
}

//Map a word section with to either one or two writer page descriptors
//depending on if the word section has a title page
//Map a word section to a writer page descriptor
SwFmtPageDesc wwSectionManager::SetSwFmtPageDesc(mySegIter &rIter,
    mySegIter &rStart, bool bIgnoreCols)
{
    SwFmtPageDesc aEmpty;
    // Always read title page header/footer data - it could be used by following sections
    {
        if (IsNewDoc() && rIter == rStart)
        {
            rIter->mpTitlePage =
                mrReader.rDoc.GetPageDescFromPool(RES_POOLPAGE_FIRST);
        }
        else
        {
            sal_uInt16 nPos = mrReader.rDoc.MakePageDesc(
                ViewShell::GetShellRes()->GetPageDescName(mnDesc, ShellResource::FIRST_PAGE)
                , 0, false);
            rIter->mpTitlePage = &mrReader.rDoc.GetPageDesc(nPos);
        }
        OSL_ENSURE(rIter->mpTitlePage, "no page!");
        if (!rIter->mpTitlePage)
            return aEmpty;

        SetSegmentToPageDesc(*rIter, true, bIgnoreCols);
    }

    if (IsNewDoc() && rIter == rStart)
    {
@@ -3871,7 +3818,7 @@ SwFmtPageDesc wwSectionManager::SetSwFmtPageDesc(mySegIter &rIter,
    {
        sal_uInt16 nPos = mrReader.rDoc.MakePageDesc(
            ViewShell::GetShellRes()->GetPageDescName(mnDesc, ShellResource::NORMAL_PAGE),
                rIter->mpTitlePage, false);
            0, false);
        rIter->mpPage = &mrReader.rDoc.GetPageDesc(nPos);
    }
    OSL_ENSURE(rIter->mpPage, "no page!");
@@ -3886,18 +3833,12 @@ SwFmtPageDesc wwSectionManager::SetSwFmtPageDesc(mySegIter &rIter,
    SetUseOn(*rIter);

    //Set hd/ft after set page
    if (rIter->mpTitlePage)
        SetSegmentToPageDesc(*rIter, true, bIgnoreCols);
    SetSegmentToPageDesc(*rIter, false, bIgnoreCols);
    SetSegmentToPageDesc(*rIter, bIgnoreCols);

    SwFmtPageDesc aRet(rIter->HasTitlePage() ?
        rIter->mpTitlePage : rIter->mpPage);
    SwFmtPageDesc aRet(rIter->mpPage);

    rIter->mpPage->SetFollow(rIter->mpPage);

    if (rIter->mpTitlePage)
        rIter->mpTitlePage->SetFollow(rIter->mpPage);

    if (rIter->PageRestartNo())
        aRet.SetNumOffset(rIter->PageStartAt());

@@ -4077,7 +4018,6 @@ void wwSectionManager::InsertSegments()
                // #i40766# Need to cache the page descriptor in case there is
                // no page break in the section
                SwPageDesc *pOrig = aIter->mpPage;
                SwPageDesc *pOrigTitle = aIter->mpTitlePage;
                bool bFailed = true;
                SwFmtPageDesc aDesc(SetSwFmtPageDesc(aIter, aStart, true));
                if (aDesc.GetPageDesc())
@@ -4101,7 +4041,6 @@ void wwSectionManager::InsertSegments()
                if(bFailed)
                {
                    aIter->mpPage = pOrig;
                    aIter->mpTitlePage = pOrigTitle;
                }
            }
        }
diff --git a/sw/source/filter/ww8/ww8par.hxx b/sw/source/filter/ww8/ww8par.hxx
index 8ff035e..0a19e72 100644
--- a/sw/source/filter/ww8/ww8par.hxx
+++ b/sw/source/filter/ww8/ww8par.hxx
@@ -694,7 +694,6 @@ public:
    WW8_BRC brc[4];
    SwNodeIndex maStart;
    SwSection *mpSection;
    SwPageDesc *mpTitlePage;
    SwPageDesc *mpPage;
    SvxFrameDirection meDir;
    short mLinkId;
@@ -750,10 +749,9 @@ private:
        wwULSpaceData() : bHasHeader(false), bHasFooter(false) {}
    };

    void SetSegmentToPageDesc(const wwSection &rSection, bool bTitlePage,
        bool bIgnoreCols);
    void SetSegmentToPageDesc(const wwSection &rSection, bool bIgnoreCols);

    void GetPageULData(const wwSection &rNewSection, bool bFirst,
    void GetPageULData(const wwSection &rNewSection,
        wwULSpaceData& rData) const;
    void SetPageULSpaceItems(SwFrmFmt &rFmt, wwULSpaceData& rData,
        const wwSection &rSection) const;
@@ -1219,7 +1217,7 @@ private:
    SwWW8StyInf *GetStyle(sal_uInt16 nColl) const;
    void AppendTxtNode(SwPosition& rPos);

    void Read_HdFt(bool bIsTitle, int nSect, const SwPageDesc *pPrev,
    void Read_HdFt(int nSect, const SwPageDesc *pPrev,
        const wwSection &rSection);
    void Read_HdFtText(long nStartCp, long nLen, SwFrmFmt* pHdFtFmt);
    void Read_HdFtTextAsHackedFrame(long nStart, long nLen,
diff --git a/sw/source/filter/ww8/ww8par6.cxx b/sw/source/filter/ww8/ww8par6.cxx
index c4f260e..f293835 100644
--- a/sw/source/filter/ww8/ww8par6.cxx
+++ b/sw/source/filter/ww8/ww8par6.cxx
@@ -512,7 +512,7 @@ void SwWW8ImplReader::SetPageBorder(SwFrmFmt &rFmt, const wwSection &rSection) c
    rFmt.SetFmtAttr(aSet);
}

void wwSectionManager::GetPageULData(const wwSection &rSection, bool bFirst,
void wwSectionManager::GetPageULData(const wwSection &rSection,
    wwSectionManager::wwULSpaceData& rData) const
{
    sal_Int32 nWWUp = rSection.maSep.dyaTop;
@@ -535,13 +535,8 @@ void wwSectionManager::GetPageULData(const wwSection &rSection, bool bFirst,
        nWWUp += rSection.maSep.dzaGutter;
    }

    if( bFirst )
        rData.bHasHeader = (rSection.maSep.grpfIhdt & WW8_HEADER_FIRST) !=0;
    else
    {
        rData.bHasHeader = (rSection.maSep.grpfIhdt &
            (WW8_HEADER_EVEN | WW8_HEADER_ODD)) != 0;
    }
    rData.bHasHeader = (rSection.maSep.grpfIhdt &
        (WW8_HEADER_EVEN | WW8_HEADER_ODD | WW8_HEADER_FIRST)) != 0;

    if( rData.bHasHeader )
    {
@@ -562,13 +557,8 @@ void wwSectionManager::GetPageULData(const wwSection &rSection, bool bFirst,
    else // kein Header -> Up einfach uebernehmen
        rData.nSwUp = Abs(nWWUp);

    if( bFirst )
        rData.bHasFooter = (rSection.maSep.grpfIhdt &  WW8_FOOTER_FIRST) !=0;
    else
    {
        rData.bHasFooter = (rSection.maSep.grpfIhdt &
            (WW8_FOOTER_EVEN | WW8_FOOTER_ODD)) != 0;
    }
    rData.bHasFooter = (rSection.maSep.grpfIhdt &
        (WW8_FOOTER_EVEN | WW8_FOOTER_ODD | WW8_FOOTER_FIRST)) != 0;

    if( rData.bHasFooter )
    {
@@ -766,7 +756,7 @@ void SwWW8ImplReader::HandleLineNumbering(const wwSection &rSection)
}

wwSection::wwSection(const SwPosition &rPos) : maStart(rPos.nNode),
    mpSection(0), mpTitlePage(0), mpPage(0), meDir(FRMDIR_HORI_LEFT_TOP),
    mpSection(0), mpPage(0), meDir(FRMDIR_HORI_LEFT_TOP),
    nPgWidth(SvxPaperInfo::GetPaperSize(PAPER_A4).Width()),
    nPgLeft(MM_250), nPgRight(MM_250), mnBorders(0), mbHasFootnote(false)
{
@@ -1115,10 +1105,14 @@ void wwSectionManager::CreateSep(const long nTxtPos, bool /*bMustHaveBreak*/)
        aNewSection.maSep.grpfIhdt = ReadBSprm(pSep, eVer <= ww::eWW2 ? 128 : 153, 0);
    else if (mrReader.pHdFt)
    {
        aNewSection.maSep.grpfIhdt = WW8_HEADER_ODD | WW8_FOOTER_ODD;
        aNewSection.maSep.grpfIhdt = WW8_HEADER_ODD | WW8_FOOTER_ODD
            | WW8_HEADER_FIRST | WW8_FOOTER_FIRST;

        if (aNewSection.HasTitlePage())
            aNewSection.maSep.grpfIhdt |= WW8_HEADER_FIRST | WW8_FOOTER_FIRST;
        // It is possible for a first page header to be provided
        // for this section, but not actually shown in this section.  In this
        // case (aNewSection.maSep.grpfIhdt & WW8_HEADER_FIRST) will be nonzero
        // but aNewSection.HasTitlePage() will be false.
        // Likewise for first page footer.

        if (mrReader.pWDop->fFacingPages)
            aNewSection.maSep.grpfIhdt |= WW8_HEADER_EVEN | WW8_FOOTER_EVEN;
@@ -1161,41 +1155,41 @@ void wwSectionManager::CreateSep(const long nTxtPos, bool /*bMustHaveBreak*/)
void SwWW8ImplReader::CopyPageDescHdFt(const SwPageDesc* pOrgPageDesc,
    SwPageDesc* pNewPageDesc, sal_uInt8 nCode )
{
    // copy first header content section
    if (nCode & WW8_HEADER_FIRST)
        rDoc.CopyHeader(pOrgPageDesc->GetMaster(), pNewPageDesc->GetMaster());

    // copy first footer content section
    if( nCode & WW8_FOOTER_FIRST )
        rDoc.CopyFooter(pOrgPageDesc->GetMaster(), pNewPageDesc->GetMaster());

    if( nCode & (   WW8_HEADER_ODD  | WW8_FOOTER_ODD
                  | WW8_HEADER_EVEN | WW8_FOOTER_EVEN ) )
    // copy odd header content section
    if( nCode & WW8_HEADER_ODD )
    {
        // copy odd header content section
        if( nCode & WW8_HEADER_ODD )
        {
            rDoc.CopyHeader(pOrgPageDesc->GetMaster(),
                            pNewPageDesc->GetMaster() );
        }
        // copy odd footer content section
        if( nCode & WW8_FOOTER_ODD )
        {
            rDoc.CopyFooter(pOrgPageDesc->GetMaster(),
                            pNewPageDesc->GetMaster());
        }
        // copy even header content section
        if( nCode & WW8_HEADER_EVEN )
        {
            rDoc.CopyHeader(pOrgPageDesc->GetLeft(),
                            pNewPageDesc->GetLeft());
        }
        // copy even footer content section
        if( nCode & WW8_FOOTER_EVEN )
        {
            rDoc.CopyFooter(pOrgPageDesc->GetLeft(),
                            pNewPageDesc->GetLeft());
        }
        rDoc.CopyHeader(pOrgPageDesc->GetMaster(),
                        pNewPageDesc->GetMaster() );
    }
    // copy odd footer content section
    if( nCode & WW8_FOOTER_ODD )
    {
        rDoc.CopyFooter(pOrgPageDesc->GetMaster(),
                        pNewPageDesc->GetMaster());
    }
    // copy even header content section
    if( nCode & WW8_HEADER_EVEN )
    {
        rDoc.CopyHeader(pOrgPageDesc->GetLeft(),
                        pNewPageDesc->GetLeft());
    }
    // copy even footer content section
    if( nCode & WW8_FOOTER_EVEN )
    {
        rDoc.CopyFooter(pOrgPageDesc->GetLeft(),
                        pNewPageDesc->GetLeft());
    }
    // copy first page header content section
    if( nCode & WW8_HEADER_FIRST )
    {
        rDoc.CopyHeader(pOrgPageDesc->GetFirst(),
                        pNewPageDesc->GetFirst());
    }
    // copy first page footer content section
    if( nCode & WW8_FOOTER_FIRST )
    {
        rDoc.CopyFooter(pOrgPageDesc->GetFirst(),
                        pNewPageDesc->GetFirst());
    }
}