tdf#59323: pptx export: add placeholder index to master footer placeholders

OOXML uses placeholder index to determine from which layout placeholder it
should be inheriting styles, position etc.

Added maPlaceholderShapeToIndexMap that stores corresponding Placeholder index
for a Placeholder XShape on the master slide.

Right now only used for placeholder types Footer, DateAndTime and SlideNumber.

Change-Id: If788f235d00b6d1cde7194d9e4a0789e019432c3
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117010
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
diff --git a/sd/source/filter/eppt/epptooxml.hxx b/sd/source/filter/eppt/epptooxml.hxx
index 93029f0..fffaa10 100644
--- a/sd/source/filter/eppt/epptooxml.hxx
+++ b/sd/source/filter/eppt/epptooxml.hxx
@@ -118,6 +118,12 @@ private:

    static void WriteDiagram(const FSHelperPtr& pFS, PowerPointShapeExport& rDML, const css::uno::Reference<css::drawing::XShape>& rXShape, int nDiagramId);

    /** Create a new placeholder index for a master placeholder shape

        @param rXShape Master placeholder shape
        @returns Placeholder index
    */
    unsigned CreateNewPlaceholderIndex(const css::uno::Reference<css::drawing::XShape>& rXShape);
    /// Should we export as .pptm, ie. do we contain macros?
    bool mbPptm;

@@ -142,6 +148,10 @@ private:

    ::oox::drawingml::ShapeExport::ShapeHashMap maShapeMap;

    unsigned mnPlaceholderIndexMax; ///< Last used placeholder index
    /// Map of placeholder indexes for Master placeholders
    std::unordered_map< css::uno::Reference<css::drawing::XShape>, unsigned > maPlaceholderShapeToIndexMap;

    struct AuthorComments {
        sal_Int32 nId;
        sal_Int32 nLastIndex;
diff --git a/sd/source/filter/eppt/pptx-epptooxml.cxx b/sd/source/filter/eppt/pptx-epptooxml.cxx
index 6a85023..9bf8069 100644
--- a/sd/source/filter/eppt/pptx-epptooxml.cxx
+++ b/sd/source/filter/eppt/pptx-epptooxml.cxx
@@ -134,8 +134,35 @@ void WriteSndAc(const FSHelperPtr& pFS, const OUString& sSoundRelId, const OUStr
        pFS->endElement(FSNS(XML_p, XML_stSnd));
        pFS->endElement(FSNS(XML_p, XML_sndAc));
}
}

const char* getPlaceholderTypeName(PlaceholderType ePlaceholder)
{
    switch (ePlaceholder)
    {
        case SlideImage:
            return "sldImg";
        case Notes:
            return "body";
        case Header:
            return "hdr";
        case Footer:
            return "ftr";
        case SlideNumber:
            return "sldNum";
        case DateAndTime:
            return "dt";
        case Outliner:
            return "body";
        case Title:
            return "title";
        case Subtitle:
            return "subTitle";
        default:
            SAL_INFO("sd.eppt", "warning: unhandled placeholder type: " << ePlaceholder);
            return "";
    }
}
}
}

namespace {
@@ -344,6 +371,7 @@ PowerPointExport::PowerPointExport(const Reference< XComponentContext >& rContex
    , mnAnimationNodeIdMax(1)
    , mnDiagramId(1)
    , mbCreateNotes(false)
    , mnPlaceholderIndexMax(1)
{
    comphelper::SequenceAsHashMap aArgumentsMap(rArguments);
    mbPptm = aArgumentsMap.getUnpackedValueOrDefault("IsPPTM", false);
@@ -1522,41 +1550,22 @@ ShapeExport& PowerPointShapeExport::WritePlaceholderShape(const Reference< XShap
    mpFS->endElementNS(XML_p, XML_cNvSpPr);
    mpFS->startElementNS(XML_p, XML_nvPr);

    const char* pType = nullptr;
    switch (ePlaceholder)
    {
    case SlideImage:
        pType = "sldImg";
        break;
    case Notes:
        pType = "body";
        break;
    case Header:
        pType = "hdr";
        break;
    case Footer:
        pType = "ftr";
        break;
    case SlideNumber:
        pType = "sldNum";
        break;
    case DateAndTime:
        pType = "dt";
        break;
    case Outliner:
        pType = "body";
        break;
    case Title:
        pType = "title";
        break;
    case Subtitle:
        pType = "subTitle";
        break;
    default:
        SAL_INFO("sd.eppt", "warning: unhandled placeholder type: " << ePlaceholder);
    }
    bool bUsePlaceholderIndex
        = ePlaceholder == Footer || ePlaceholder == DateAndTime || ePlaceholder == SlideNumber;
    const char* pType = getPlaceholderTypeName(ePlaceholder);

    SAL_INFO("sd.eppt", "write placeholder " << pType);
    mpFS->singleElementNS(XML_p, XML_ph, XML_type, pType);
    if (bUsePlaceholderIndex)
    {
        mpFS->singleElementNS(
            XML_p, XML_ph, XML_type, pType, XML_idx,
            OString::number(
                static_cast<PowerPointExport*>(GetFB())->CreateNewPlaceholderIndex(xShape)));
    }
    else
    {
        mpFS->singleElementNS(XML_p, XML_ph, XML_type, pType);
    }
    mpFS->endElementNS(XML_p, XML_nvPr);
    mpFS->endElementNS(XML_p, XML_nvSpPr);

@@ -2078,6 +2087,12 @@ void PowerPointExport::WriteDiagram(const FSHelperPtr& pFS, PowerPointShapeExpor
    pFS->endElementNS(XML_p, XML_graphicFrame);
}

unsigned PowerPointExport::CreateNewPlaceholderIndex(const css::uno::Reference<XShape> &rXShape)
{
    maPlaceholderShapeToIndexMap.insert({rXShape, mnPlaceholderIndexMax});
    return mnPlaceholderIndexMax++;
}

// UNO component
extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
css_comp_Impress_oox_PowerPointExport(uno::XComponentContext* rxCtxt,