include/oox/drawingml/shape.hxx            |    5 +-
 include/svx/svdobj.hxx                     |    4 +
 include/svx/svdpage.hxx                    |    2 
 offapi/com/sun/star/presentation/Shape.idl |    8 +++
 oox/inc/drawingml/textbody.hxx             |    3 +
 oox/source/drawingml/shape.cxx             |   21 +++++++--
 oox/source/drawingml/shapecontext.cxx      |    2 
 oox/source/drawingml/textbody.cxx          |   15 ++++++
 oox/source/export/shapes.cxx               |    1 
 oox/source/ppt/pptshape.cxx                |   10 +---
 oox/source/token/properties.txt            |    1 
 sd/inc/sdpage.hxx                          |    6 +-
 sd/qa/unit/data/pptx/tdf163239.pptx        |binary
 sd/qa/unit/export-tests-ooxml4.cxx         |   66 ++++++++++++++++++++++++++++-
 sd/source/core/sdpage.cxx                  |   53 ++++++++++++++++++++---
 sd/source/filter/eppt/pptx-epptooxml.cxx   |   24 +++++++++-
 sd/source/ui/inc/unoprnms.hxx              |    1 
 sd/source/ui/unoidl/unoobj.cxx             |   46 ++++++++++++++++++++
 sd/source/ui/unoidl/unoobj.hxx             |    3 +
 sd/source/ui/view/NotesPanelView.cxx       |    2 
 sd/source/ui/view/drawview.cxx             |    2 
 sd/source/ui/view/outlnvsh.cxx             |    4 -
 sd/source/ui/view/outlview.cxx             |    4 -
 sd/source/ui/view/sdview.cxx               |    2 
 svx/source/svdraw/svdobj.cxx               |    5 ++
 svx/source/svdraw/svdpage.cxx              |    6 ++
 26 files changed, 263 insertions(+), 33 deletions(-)

New commits:
commit 6da1b384c70095f1636edb07cf7b1f3304dae025
Author:     Balazs Varga <[email protected]>
AuthorDate: Fri Aug 8 13:06:38 2025 +0200
Commit:     Balazs Varga <[email protected]>
CommitDate: Fri Aug 15 09:37:35 2025 +0200

    tdf#163239 - OOXML sd: fix customized placeholder text in master slide to be
    
    shown as the "prompt" text in the final slides
    
    What should works
     - New sd specific uno api shape property: CustomPromptText
     - With this property, the corresponding master slide SdrObj's
       and their final slide SdrObj's placeholder text can be set.
     - If we have CustomPromptText value it will be used for the
       PresetObj and will be created (CreatePresObj) with those texts
       as a default prompt text. If we do not have the usual default
       ones will be used.
     - OOXML import and export (partly since we have many other problems
       around export) are works
     - Enable to OOXML import of com.sun.star.presentation.SubtitleShape
       (partly, since in the core we handle them as Text objects) to handle them
       a bit better. OOXML export is still not good for different reasons:
       see tdf#112557
     - Unit tests for custom "prompt" text
    
    TODO
     - odf import/export
     - we cannot set in runtime new custom placeholder texts, so the new
       placeholders/presobj will be created with the usual default texts.
    
    Change-Id: Ic2b06a10f7a19f0cfdb2b705645b08a24b3e433b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189185
    Tested-by: Jenkins
    Reviewed-by: Balazs Varga <[email protected]>
    (cherry picked from commit 41c59a730ffce72202083b8ce3438c10ba18f1d1)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189517
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Justin Luth <[email protected]>

diff --git a/include/oox/drawingml/shape.hxx b/include/oox/drawingml/shape.hxx
index 81797757faaf..40c207be2edd 100644
--- a/include/oox/drawingml/shape.hxx
+++ b/include/oox/drawingml/shape.hxx
@@ -244,6 +244,8 @@ public:
     void                setTxbxHasLinkedTxtBox( const bool rhs){ 
mbHasLinkedTxbx = rhs; };
     const LinkedTxbxAttr&     getLinkedTxbxAttributes() const { return 
maLinkedTxbxAttr; };
     bool                isLinkedTxbx() const { return mbHasLinkedTxbx; };
+    void                setCustomPrompt( bool bValue ) { mbHasCustomPrompt = 
bValue; }
+    bool                getCustomPrompt() const { return mbHasCustomPrompt; }
 
     void setZOrder(sal_Int32 nZOrder) { mnZOrder = nZOrder; }
 
@@ -298,7 +300,7 @@ protected:
                             const Theme* pTheme,
                             const css::uno::Reference< css::drawing::XShapes 
>& rxShapes,
                             bool bClearText,
-                            bool bDoNotInsertEmptyTextBody,
+                            const oox::drawingml::ShapePtr& pPlaceholder,
                             basegfx::B2DHomMatrix& aTransformation,
                             const FillProperties& rShapeOrParentShapeFillProps,
                             const oox::drawingml::ShapePtr& pParentGroupShape 
= nullptr
@@ -430,6 +432,7 @@ private:
     bool mbTextBox; ///< This shape has a textbox.
     LinkedTxbxAttr                  maLinkedTxbxAttr;
     bool                            mbHasLinkedTxbx; // this text box has 
linked text box ?
+    bool                            mbHasCustomPrompt; // indicates that it's 
not a generic placeholder
 
     css::uno::Sequence<css::beans::PropertyValue> maDiagramDoms;
 
diff --git a/include/svx/svdobj.hxx b/include/svx/svdobj.hxx
index 621c44e78c4a..524e57e59f44 100644
--- a/include/svx/svdobj.hxx
+++ b/include/svx/svdobj.hxx
@@ -826,6 +826,8 @@ public:
 
     void SetEmptyPresObj(bool bEpt);
     bool IsEmptyPresObj() const { return m_bEmptyPresObj;}
+    void SetCustomPromptText(const OUString& aVal);
+    OUString GetCustomPromptText() const { return m_aCustomPromptText; }
     void SetNotVisibleAsMaster(bool bFlg);
     bool IsNotVisibleAsMaster() const { return m_bNotVisibleAsMaster;}
     void SetUserCall(SdrObjUserCall* pUser);
@@ -915,6 +917,8 @@ protected:
     bool                        mbLineIsOutsideGeometry : 1;
     // #i25616#
     bool                        mbSupportTextIndentingOnLineWidthChange : 1;
+    // custom prompt text for empty presentation object
+    OUString                    m_aCustomPromptText;
 
     std::unique_ptr<sdr::annotation::ObjectAnnotationData> mpAnnotationData;
 
diff --git a/include/svx/svdpage.hxx b/include/svx/svdpage.hxx
index f64af22e1353..4b0a4eb84b51 100644
--- a/include/svx/svdpage.hxx
+++ b/include/svx/svdpage.hxx
@@ -520,6 +520,8 @@ public:
 
     void MakePageObjectsNamesUnique();
 
+    virtual bool RestoreDefaultText(SdrObject* pObj, const OUString& rStr);
+
 protected:
     void TRG_ImpMasterPageRemoved(const SdrPage& rRemovedPage);
 
diff --git a/offapi/com/sun/star/presentation/Shape.idl 
b/offapi/com/sun/star/presentation/Shape.idl
index 0539228e090d..07abc55e8a81 100644
--- a/offapi/com/sun/star/presentation/Shape.idl
+++ b/offapi/com/sun/star/presentation/Shape.idl
@@ -128,6 +128,14 @@ published service Shape
      */
     [property] long Verb;
 
+    /** Determines if the shape has custom placeholder text.
+
+        This is the custom placeholder text for Presentation objects.
+
+        @since LibreOffice 26.2
+    */
+    [optional, property] string CustomPromptText;
+
 };
 
 
diff --git a/oox/inc/drawingml/textbody.hxx b/oox/inc/drawingml/textbody.hxx
index 245589e86ac3..d059ed501306 100644
--- a/oox/inc/drawingml/textbody.hxx
+++ b/oox/inc/drawingml/textbody.hxx
@@ -64,7 +64,10 @@ public:
                             const TextCharacterProperties& 
rTextStyleProperties,
                             const TextListStylePtr& pMasterTextListStyle ) 
const;
     bool isEmpty() const;
+    /// Returns first run of text
     OUString toString() const;
+    /// Returns first paragraph of text
+    OUString firstParatoString() const;
 
     /** Returns whether the textbody had a rPr tag in it that alters it 
visually
      *
diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx
index 4cb0160facee..54b8d91ba663 100644
--- a/oox/source/drawingml/shape.cxx
+++ b/oox/source/drawingml/shape.cxx
@@ -153,6 +153,7 @@ Shape::Shape()
 , mbWps( false )
 , mbTextBox( false )
 , mbHasLinkedTxbx( false )
+, mbHasCustomPrompt( false )
 , maDiagramDoms( 0 )
 , mpDiagramHelper( nullptr )
 {
@@ -186,6 +187,7 @@ Shape::Shape( const OUString& rServiceName, bool 
bDefaultHeight )
 , mbWps( false )
 , mbTextBox( false )
 , mbHasLinkedTxbx( false )
+, mbHasCustomPrompt( false )
 , maDiagramDoms( 0 )
 , mpDiagramHelper( nullptr )
 {
@@ -230,6 +232,7 @@ Shape::Shape( const ShapePtr& pSourceShape )
 , mbWps( pSourceShape->mbWps )
 , mbTextBox( pSourceShape->mbTextBox )
 , mbHasLinkedTxbx(false)
+, mbHasCustomPrompt( pSourceShape->mbHasCustomPrompt )
 , maDiagramDoms( pSourceShape->maDiagramDoms )
 , mnZOrder(pSourceShape->mnZOrder)
 , mnZOrderOff(pSourceShape->mnZOrderOff)
@@ -394,7 +397,7 @@ void Shape::addShape(
         if( !sServiceName.isEmpty() )
         {
             basegfx::B2DHomMatrix aMatrix( aTransformation );
-            Reference< XShape > xShape( createAndInsert( rFilterBase, 
sServiceName, pTheme, rxShapes, false, false, aMatrix, 
rShapeOrParentShapeFillProps, pParentGroupShape) );
+            Reference< XShape > xShape( createAndInsert( rFilterBase, 
sServiceName, pTheme, rxShapes, false, nullptr, aMatrix, 
rShapeOrParentShapeFillProps, pParentGroupShape) );
 
             if( pShapeMap && !msId.isEmpty() )
             {
@@ -916,7 +919,7 @@ Reference< XShape > const & Shape::createAndInsert(
         const Theme* pTheme,
         const css::uno::Reference< css::drawing::XShapes >& rxShapes,
         bool bClearText,
-        bool bDoNotInsertEmptyTextBody,
+        const oox::drawingml::ShapePtr& pPlaceholder,
         basegfx::B2DHomMatrix& aParentTransformation,
         const FillProperties& rShapeOrParentShapeFillProps,
         const oox::drawingml::ShapePtr& pParentGroupShape)
@@ -1816,6 +1819,16 @@ Reference< XShape > const & Shape::createAndInsert(
                 
propertySet->setPropertyValue(u"InteropGrabBag"_ustr,uno::Any(aGrabBag));
             }
 
+            // set custom prompt text if available
+            if (getCustomPrompt() && getTextBody() && 
!getTextBody()->isEmpty())
+            {
+                aShapeProps.setProperty(PROP_CustomPromptText, 
getTextBody()->firstParatoString());
+            }
+            else if (pPlaceholder && pPlaceholder->getCustomPrompt() && 
pPlaceholder->getTextBody() && !pPlaceholder->getTextBody()->isEmpty())
+            {
+                aShapeProps.setProperty(PROP_CustomPromptText, 
pPlaceholder->getTextBody()->firstParatoString());
+            }
+
             PropertySet( xSet ).setProperties( aShapeProps );
 
             if (mpTablePropertiesPtr && aServiceName == 
"com.sun.star.drawing.TableShape")
@@ -2132,7 +2145,7 @@ Reference< XShape > const & Shape::createAndInsert(
             mpTextBody.reset();
 
         // in some cases, we don't have any text body.
-        if( mpTextBody && ( !bDoNotInsertEmptyTextBody || 
!mpTextBody->isEmpty() ) )
+        if( mpTextBody && ( !pPlaceholder || !mpTextBody->isEmpty() ) )
         {
             Reference < XText > xText( mxShape, UNO_QUERY );
             if ( xText.is() )   // not every shape is supporting an XText 
interface (e.g. GroupShape)
@@ -2223,7 +2236,7 @@ Reference< XShape > const & Shape::createAndInsert(
         }
 
         // Set text glow effect for shapes
-        if (mpTextBody && (!bDoNotInsertEmptyTextBody || 
!mpTextBody->isEmpty()))
+        if (mpTextBody && (!pPlaceholder || !mpTextBody->isEmpty()))
         {
             const TextParagraphVector& rParagraphs = 
mpTextBody->getParagraphs();
             if (!rParagraphs.empty())
diff --git a/oox/source/drawingml/shapecontext.cxx 
b/oox/source/drawingml/shapecontext.cxx
index 1cd22c7cd422..2dc77a0e676f 100644
--- a/oox/source/drawingml/shapecontext.cxx
+++ b/oox/source/drawingml/shapecontext.cxx
@@ -86,6 +86,8 @@ ContextHandlerRef ShapeContext::onCreateContext( sal_Int32 
aElementToken, const
         mpShapePtr->setSubType( rAttribs.getToken( XML_type, XML_obj ) );
         if( rAttribs.hasAttribute( XML_idx ) )
             mpShapePtr->setSubTypeIndex( rAttribs.getInteger( XML_idx, 0 ) );
+        if( rAttribs.hasAttribute( XML_hasCustomPrompt ) )
+            mpShapePtr->setCustomPrompt( rAttribs.getBool( 
XML_hasCustomPrompt, false ) );
         break;
     // nvSpPr CT_ShapeNonVisual end
 
diff --git a/oox/source/drawingml/textbody.cxx 
b/oox/source/drawingml/textbody.cxx
index 1d9e45f505f5..9e1c68b5206f 100644
--- a/oox/source/drawingml/textbody.cxx
+++ b/oox/source/drawingml/textbody.cxx
@@ -95,6 +95,21 @@ OUString TextBody::toString() const
     return OUString();
 }
 
+OUString TextBody::firstParatoString() const
+{
+    OUStringBuffer aRet;
+    if (!isEmpty())
+    {
+        const TextRunVector& rRuns = maParagraphs.front()->getRuns();
+        for (TextRunVector::const_iterator aRIt = rRuns.begin(), aREnd = 
rRuns.end(); aRIt != aREnd; ++aRIt)
+        {
+            const TextRun& rTextRun = **aRIt;
+            aRet.append(rTextRun.getText());
+        }
+    }
+    return aRet.makeStringAndClear();
+}
+
 bool TextBody::hasVisualRunProperties() const
 {
     for ( auto& pTextParagraph : getParagraphs() )
diff --git a/oox/source/export/shapes.cxx b/oox/source/export/shapes.cxx
index d8c396382217..b4062cda91f5 100644
--- a/oox/source/export/shapes.cxx
+++ b/oox/source/export/shapes.cxx
@@ -2185,6 +2185,7 @@ constexpr auto constMap = 
frozen::make_unordered_map<std::u16string_view, ShapeC
     { u"com.sun.star.presentation.OutlinerShape", &ShapeExport::WriteTextShape 
},
     { u"com.sun.star.presentation.SlideNumberShape", 
&ShapeExport::WriteTextShape },
     { u"com.sun.star.presentation.TitleTextShape", 
&ShapeExport::WriteTextShape },
+    //{ u"com.sun.star.presentation.SubtitleShape", 
&ShapeExport::WriteTextShape }, TODO: handle subtitle shape: see tdf#112557 
workaround
 });
 
 } // end anonymous namespace
diff --git a/oox/source/ppt/pptshape.cxx b/oox/source/ppt/pptshape.cxx
index 634c46dc5255..61adfbd87512 100644
--- a/oox/source/ppt/pptshape.cxx
+++ b/oox/source/ppt/pptshape.cxx
@@ -195,12 +195,8 @@ void PPTShape::addShape(
                 break;
                 case XML_subTitle :
                 {
-                    if ((meShapeLocation == Master) || (meShapeLocation == 
Layout))
-                        sServiceName = OUString();
-                    else {
-                        sServiceName = 
"com.sun.star.presentation.SubtitleShape";
-                        aMasterTextListStyle = 
rSlidePersist.getMasterPersist() ? 
rSlidePersist.getMasterPersist()->getBodyTextStyle() : 
rSlidePersist.getBodyTextStyle();
-                    }
+                    sServiceName = "com.sun.star.presentation.SubtitleShape";
+                    aMasterTextListStyle = rSlidePersist.getMasterPersist() ? 
rSlidePersist.getMasterPersist()->getBodyTextStyle() : 
rSlidePersist.getBodyTextStyle();
                 }
                 break;
                    case XML_obj :
@@ -454,7 +450,7 @@ void PPTShape::addShape(
             } else
                 setMasterTextListStyle( aMasterTextListStyle );
 
-            Reference< XShape > xShape( createAndInsert( rFilterBase, 
sServiceName, pTheme, rxShapes, bClearText, bool(mpPlaceholder), 
aTransformation, getFillProperties() ) );
+            Reference< XShape > xShape( createAndInsert( rFilterBase, 
sServiceName, pTheme, rxShapes, bClearText, mpPlaceholder, aTransformation, 
getFillProperties() ) );
 
             // Apply text properties on placeholder text inside this 
placeholder shape
             if (meShapeLocation == Slide && mpPlaceholder && getTextBody() && 
getTextBody()->isEmpty())
diff --git a/oox/source/token/properties.txt b/oox/source/token/properties.txt
index d73008a80539..36e9a16991ef 100644
--- a/oox/source/token/properties.txt
+++ b/oox/source/token/properties.txt
@@ -125,6 +125,7 @@ CurveName
 CurveStyle
 CustomLabelPosition
 CustomLabelSize
+CustomPromptText
 CustomShapeGeometry
 D3DSceneAmbientColor
 D3DSceneLightColor2
diff --git a/sd/inc/sdpage.hxx b/sd/inc/sdpage.hxx
index 71b47e4b7cc9..1b2cafc550c9 100644
--- a/sd/inc/sdpage.hxx
+++ b/sd/inc/sdpage.hxx
@@ -167,7 +167,7 @@ public:
     sd::ShapeList&  GetPresentationShapeList() { return 
maPresentationShapeList; }
 
     void EnsureMasterPageDefaultBackground();
-    SD_DLLPUBLIC SdrObject* CreatePresObj(PresObjKind eObjKind, bool 
bVertical, const ::tools::Rectangle& rRect);
+    SD_DLLPUBLIC SdrObject* CreatePresObj(PresObjKind eObjKind, bool 
bVertical, const ::tools::Rectangle& rRect, const OUString& rCustomPrompt = 
OUString());
     SD_DLLPUBLIC rtl::Reference<SdrObject> CreateDefaultPresObj(PresObjKind 
eObjKind);
     SD_DLLPUBLIC void DestroyDefaultPresObj(PresObjKind eObjKind);
     SD_DLLPUBLIC SdrObject* GetPresObj(PresObjKind eObjKind, int nIndex = 1, 
bool bFuzzySearch = false );
@@ -177,7 +177,7 @@ public:
     SfxStyleSheet*  GetStyleSheetForPresObj(PresObjKind eObjKind) const;
     void            GetPageInfo(::tools::JsonWriter& jsonWriter);
     void            NotifyPagePropertyChanges();
-    bool            RestoreDefaultText( SdrObject* pObj );
+    bool            RestoreDefaultText( SdrObject* pObj, const OUString& rStr 
) override;
 
     /** @return true if the given SdrObject is inside the presentation object 
list */
     bool            IsPresObj(const SdrObject* pObj);
@@ -191,7 +191,7 @@ public:
     SD_DLLPUBLIC void SetAutoLayout(AutoLayout eLayout, bool bInit=false, bool 
bCreate=false);
     AutoLayout      GetAutoLayout() const { return meAutoLayout; }
     void            CreateTitleAndLayout(bool bInit=false, bool bCreate=false);
-    SdrObject*      InsertAutoLayoutShape(SdrObject* pObj, PresObjKind 
eObjKind, bool bVertical, const ::tools::Rectangle& rRect, bool bInit);
+    SdrObject*      InsertAutoLayoutShape(SdrObject* pObj, PresObjKind 
eObjKind, bool bVertical, const ::tools::Rectangle& rRect, const OUString& 
rCustomPrompt, bool bInit);
 
     virtual void       NbcInsertObject(SdrObject* pObj, size_t 
nPos=SAL_MAX_SIZE) override;
     virtual rtl::Reference<SdrObject> NbcRemoveObject(size_t nObjNum) override;
diff --git a/sd/qa/unit/data/pptx/tdf163239.pptx 
b/sd/qa/unit/data/pptx/tdf163239.pptx
new file mode 100644
index 000000000000..7dbc2e2a9862
Binary files /dev/null and b/sd/qa/unit/data/pptx/tdf163239.pptx differ
diff --git a/sd/qa/unit/export-tests-ooxml4.cxx 
b/sd/qa/unit/export-tests-ooxml4.cxx
index d9bea30c1334..c88f71db7db4 100644
--- a/sd/qa/unit/export-tests-ooxml4.cxx
+++ b/sd/qa/unit/export-tests-ooxml4.cxx
@@ -797,7 +797,7 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, 
testTdf140912_PicturePlaceholder)
     CPPUNIT_ASSERT(isEmptyPresentationObject);
 
     // If we supported custom prompt text, here we would also test "String" 
property,
-    // which would be equal to "Insert Image".
+    // which would be equal to "Insert Image". See first tests: 
testCustomPromptTexts
 }
 
 CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testEnhancedPathViewBox)
@@ -1374,6 +1374,70 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, 
testTdf165261HorzAnchor)
     
CPPUNIT_ASSERT_EQUAL(drawing::TextHorizontalAdjust::TextHorizontalAdjust_CENTER,
 eHori);
 }
 
+CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testCustomPromptTexts)
+{
+    createSdImpressDoc("pptx/tdf163239.pptx");
+    saveAndReload(u"Impress Office Open XML"_ustr);
+
+    const SdrPage* pPage1 = GetPage(1);
+    {
+        // subtitle placeholder text
+        SdrTextObj* pTxtObj = DynCastSdrTextObj(pPage1->GetObj(0));
+        CPPUNIT_ASSERT_MESSAGE("no text object", pTxtObj != nullptr);
+        CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong object type!", SdrObjKind::Text,
+                                     pTxtObj->GetObjIdentifier());
+        const EditTextObject& aEdit = 
pTxtObj->GetOutlinerParaObject()->GetTextObject();
+        OUString aText = aEdit.GetText(0);
+        CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong placeholder text!", aText, u"Click 
to add Text"_ustr);
+        /* TODO: handle subtitle shape: see tdf#112557 workaround
+            - Expected: Click to edit customized Master Subtitle style
+            - Actual : Click to add Text
+            - Wrong placeholder text!
+        */
+
+        auto xShapeProps(getShapeFromPage(0, 0));
+        CPPUNIT_ASSERT(xShapeProps->getPropertyValue(u"CustomPromptText"_ustr) 
>>= aText);
+        CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong placeholder text was set!", aText, 
u""_ustr);
+        /* TODO: handle subtitle shape: see tdf#112557 workaround
+            - Expected: Click to edit customized Master Subtitle style
+            - Actual :
+            - Wrong placeholder text was set!
+        */
+    }
+
+    {
+        SdrTextObj* pTxtObj = DynCastSdrTextObj(pPage1->GetObj(1));
+        CPPUNIT_ASSERT_MESSAGE("no text object", pTxtObj != nullptr);
+        CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong object type!", 
SdrObjKind::TitleText,
+                                     pTxtObj->GetObjIdentifier());
+        const EditTextObject& aEdit = 
pTxtObj->GetOutlinerParaObject()->GetTextObject();
+        OUString aText = aEdit.GetText(0);
+        CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong placeholder text!", aText, 
u"Custom Title 1"_ustr);
+
+        auto xShapeProps(getShapeFromPage(1, 0));
+        CPPUNIT_ASSERT(xShapeProps->getPropertyValue(u"CustomPromptText"_ustr) 
>>= aText);
+        CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong placeholder text was set!", aText,
+                                     u"Custom Title 1"_ustr);
+    }
+
+    const SdrPage* pPage2 = GetPage(3);
+    {
+        // body placeholder text
+        SdrTextObj* pTxtObj = DynCastSdrTextObj(pPage2->GetObj(0));
+        CPPUNIT_ASSERT_MESSAGE("no text object", pTxtObj != nullptr);
+        CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong object type!", 
SdrObjKind::OutlineText,
+                                     pTxtObj->GetObjIdentifier());
+        const EditTextObject& aEdit = 
pTxtObj->GetOutlinerParaObject()->GetTextObject();
+        OUString aText = aEdit.GetText(0);
+        CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong placeholder text!", aText, u"Text 
placeholder"_ustr);
+
+        auto xShapeProps(getShapeFromPage(0, 1));
+        CPPUNIT_ASSERT(xShapeProps->getPropertyValue(u"CustomPromptText"_ustr) 
>>= aText);
+        CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong placeholder text was set!", aText,
+                                     u"Text placeholder"_ustr);
+    }
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/core/sdpage.cxx b/sd/source/core/sdpage.cxx
index 76ab8e4b42cd..0d8d5aeebd6c 100644
--- a/sd/source/core/sdpage.cxx
+++ b/sd/source/core/sdpage.cxx
@@ -284,7 +284,7 @@ void SdPage::EnsureMasterPageDefaultBackground()
 
 /** creates a presentation object with the given PresObjKind on this page. A 
user call will be set
 */
-SdrObject* SdPage::CreatePresObj(PresObjKind eObjKind, bool bVertical, const 
::tools::Rectangle& rRect )
+SdrObject* SdPage::CreatePresObj(PresObjKind eObjKind, bool bVertical, const 
::tools::Rectangle& rRect, const OUString& rCustomPrompt)
 {
     SfxUndoManager* pUndoManager(static_cast< SdDrawDocument& 
>(getSdrModelFromSdrPage()).GetUndoManager());
     const bool bUndo = pUndoManager && pUndoManager->IsInListAction() && 
IsInserted();
@@ -498,7 +498,15 @@ SdrObject* SdPage::CreatePresObj(PresObjKind eObjKind, 
bool bVertical, const ::t
             pSdrObj->SetLogicRect(rRect);
         }
 
-        OUString aString = GetPresObjText(eObjKind);
+        OUString aString;
+        if (!rCustomPrompt.isEmpty())
+        {
+            pSdrObj->SetCustomPromptText(rCustomPrompt);
+            aString = rCustomPrompt;
+        }
+        else
+            aString = GetPresObjText(eObjKind);
+
         if(!aString.isEmpty() || bForceText)
             if (auto pTextObj = DynCastSdrTextObj( pSdrObj.get() ) )
             {
@@ -1479,6 +1487,32 @@ static void CalcAutoLayoutRectangles( SdPage const & 
rPage,::tools::Rectangle* r
     }
 }
 
+static void GetAutoLayoutCustomPromptTexts( SdPage& rPage, const 
LayoutDescriptor& rDescriptor, std::array<OUString, MAX_PRESOBJS>& 
rCustomPrompts )
+{
+    // init layout shapes with their corresponding prompt text (if they have)
+    // for each presentation shape kind
+    if (rPage.GetPageKind() == PageKind::Handout || !rPage.TRG_HasMasterPage())
+        return;
+
+    SdPage& rMasterPage = static_cast<SdPage&>(rPage.TRG_GetMasterPage());
+
+    o3tl::enumarray<PresObjKind,int> PresObjIndex;
+    PresObjIndex.fill(1);
+
+    // for each entry in the layoutdescriptor, arrange a presentation shape
+    for (int i = 0; (i < MAX_PRESOBJS) && (rDescriptor.meKind[i] != 
PresObjKind::NONE); i++)
+    {
+        PresObjKind eKind = rDescriptor.meKind[i];
+        SdrObject* pObj = nullptr;
+        while( (pObj = rMasterPage.GetPresObj( eKind, PresObjIndex[eKind], 
true )) != nullptr )
+        {
+            PresObjIndex[eKind]++; // on next search for eKind, find next 
shape with same eKind
+            rCustomPrompts[i] = pObj->GetCustomPromptText();
+            break;
+        }
+    }
+}
+
 static void findAutoLayoutShapesImpl( SdPage& rPage, const LayoutDescriptor& 
rDescriptor, std::array<SdrObject*, MAX_PRESOBJS>& rShapes, bool bInit, bool 
bSwitchLayout )
 {
     // init list of indexes for each presentation shape kind
@@ -1662,6 +1696,9 @@ void SdPage::SetAutoLayout(AutoLayout eLayout, bool 
bInit, bool bCreate )
     OUString sLayoutName( enumtoString(meAutoLayout) );
     CalcAutoLayoutRectangles( *this, aRectangle, sLayoutName);
 
+    std::array<OUString, MAX_PRESOBJS > aCustomPromptTexts;
+    GetAutoLayoutCustomPromptTexts( *this, aDescriptor, aCustomPromptTexts );
+
     o3tl::sorted_vector< SdrObject* > aUsedPresentationObjects;
 
     std::array<SdrObject*, MAX_PRESOBJS > aLayoutShapes;
@@ -1672,7 +1709,7 @@ void SdPage::SetAutoLayout(AutoLayout eLayout, bool 
bInit, bool bCreate )
     for (int i = 0; (i < MAX_PRESOBJS) && (aDescriptor.meKind[i] != 
PresObjKind::NONE); i++)
     {
         PresObjKind eKind = aDescriptor.meKind[i];
-        SdrObject* pObj = InsertAutoLayoutShape( aLayoutShapes[i], eKind, 
aDescriptor.mbVertical[i], aRectangle[i], bInit );
+        SdrObject* pObj = InsertAutoLayoutShape( aLayoutShapes[i], eKind, 
aDescriptor.mbVertical[i], aRectangle[i], aCustomPromptTexts[i], bInit );
         if( pObj )
             aUsedPresentationObjects.insert(pObj); // remember that we used 
this empty shape
     }
@@ -2247,12 +2284,14 @@ static rtl::Reference<SdrObject> 
convertPresentationObjectImpl(SdPage& rPage, Sd
         If true, the shape is created vertical if bInit is true
     @param  rRect
         The rectangle that should be used to transform the shape
+    @param  rCustomPrompt
+        The custom prompt text for placeholder text in presObj's, if its empty 
the default is used
     @param  bInit
         If true the shape is created if not found
     @returns
         A presentation shape that was either found or created with the given 
parameters
 */
-SdrObject* SdPage::InsertAutoLayoutShape(SdrObject* pObj1, PresObjKind 
eObjKind, bool bVertical, const ::tools::Rectangle& rRect, bool bInit)
+SdrObject* SdPage::InsertAutoLayoutShape(SdrObject* pObj1, PresObjKind 
eObjKind, bool bVertical, const ::tools::Rectangle& rRect, const OUString& 
rCustomPrompt, bool bInit)
 {
     rtl::Reference<SdrObject> pObj = pObj1;
     SfxUndoManager* pUndoManager(static_cast< SdDrawDocument& 
>(getSdrModelFromSdrPage()).GetUndoManager());
@@ -2260,7 +2299,7 @@ SdrObject* SdPage::InsertAutoLayoutShape(SdrObject* 
pObj1, PresObjKind eObjKind,
 
     if (!pObj && bInit)
     {
-        pObj = CreatePresObj(eObjKind, bVertical, rRect);
+        pObj = CreatePresObj(eObjKind, bVertical, rRect, rCustomPrompt);
     }
     else if ( pObj && (pObj->GetUserCall() || bInit) )
     {
@@ -2922,7 +2961,7 @@ bool SdPage::checkVisibility(
     return true;
 }
 
-bool SdPage::RestoreDefaultText( SdrObject* pObj )
+bool SdPage::RestoreDefaultText( SdrObject* pObj, const OUString& rStr )
 {
     bool bRet = false;
 
@@ -2939,7 +2978,7 @@ bool SdPage::RestoreDefaultText( SdrObject* pObj )
         {
             sd::ModifyGuard 
aGuard(static_cast<SdDrawDocument*>(&getSdrModelFromSdrPage()));
 
-            OUString aString( GetPresObjText(ePresObjKind) );
+            OUString aString = rStr.isEmpty() ? GetPresObjText(ePresObjKind) : 
rStr;
 
             if (!aString.isEmpty())
             {
diff --git a/sd/source/filter/eppt/pptx-epptooxml.cxx 
b/sd/source/filter/eppt/pptx-epptooxml.cxx
index 7ae6bab8c189..212a10c8f519 100644
--- a/sd/source/filter/eppt/pptx-epptooxml.cxx
+++ b/sd/source/filter/eppt/pptx-epptooxml.cxx
@@ -345,6 +345,12 @@ ShapeExport& PowerPointShapeExport::WriteTextShape(const 
Reference< XShape >& xS
         if (!WritePlaceholder(xShape, Title, mbMaster))
             ShapeExport::WriteTextShape(xShape);
     }
+    /*else if (sShapeType == "com.sun.star.presentation.SubtitleShape")
+    {
+        TODO: handle subtitle shape: see tdf#112557 workaround
+        if (!WritePlaceholder(xShape, Subtitle, mbMaster))
+            ShapeExport::WriteTextShape(xShape);
+    }*/
     else
         SAL_WARN("sd.eppt", "PowerPointShapeExport::WriteTextShape: shape of 
type '" << sShapeType << "' is ignored");
 
@@ -2420,20 +2426,32 @@ ShapeExport& 
PowerPointShapeExport::WritePlaceholderShape(const Reference< XShap
     const char* pType = getPlaceholderTypeName(ePlaceholder);
 
     SAL_INFO("sd.eppt", "write placeholder " << pType);
+
+    // export Custom Prompt
+    bool bUseCustomPrompt(false);
+    if (xProps.is() && 
xProps->getPropertySetInfo()->hasPropertyByName(u"CustomPromptText"_ustr))
+    {
+        OUString aCustomPromptText;
+        xProps->getPropertyValue(u"CustomPromptText"_ustr) >>= 
aCustomPromptText;
+        if (!aCustomPromptText.isEmpty())
+            bUseCustomPrompt = true;
+    }
+
     if (bUsePlaceholderIndex)
     {
         mpFS->singleElementNS(
             XML_p, XML_ph, XML_type, pType, XML_idx,
             OString::number(
-                
static_cast<PowerPointExport*>(GetFB())->CreateNewPlaceholderIndex(xShape)));
+                
static_cast<PowerPointExport*>(GetFB())->CreateNewPlaceholderIndex(xShape)),
+                    XML_hasCustomPrompt, sax_fastparser::UseIf("1", 
bUseCustomPrompt));
     }
     else
     {
         if ((mePageType == PageType::LAYOUT || mePageType == PageType::NORMAL)
             && ePlaceholder == Outliner)
-            mpFS->singleElementNS(XML_p, XML_ph);
+            mpFS->singleElementNS(XML_p, XML_ph, XML_hasCustomPrompt, 
sax_fastparser::UseIf("1", bUseCustomPrompt));
         else
-            mpFS->singleElementNS(XML_p, XML_ph, XML_type, pType);
+            mpFS->singleElementNS(XML_p, XML_ph, XML_type, pType, 
XML_hasCustomPrompt, sax_fastparser::UseIf("1", bUseCustomPrompt));
     }
     mpFS->endElementNS(XML_p, XML_nvPr);
     mpFS->endElementNS(XML_p, XML_nvSpPr);
diff --git a/sd/source/ui/inc/unoprnms.hxx b/sd/source/ui/inc/unoprnms.hxx
index 9753c1a2871a..062d898f4992 100644
--- a/sd/source/ui/inc/unoprnms.hxx
+++ b/sd/source/ui/inc/unoprnms.hxx
@@ -59,6 +59,7 @@
 #define UNO_NAME_OBJ_MASTERDEPENDENT    "IsPlaceholderDependent"
 #define UNO_NAME_OBJ_ANIMATIONPATH      "AnimationPath"
 #define UNO_NAME_OBJ_LEGACYFRAGMENT     "LegacyFragment"
+#define UNO_NAME_OBJ_CUSTOMPROMPT       "CustomPromptText"
 
 #define UNO_NAME_LAYER_LOCKED           "IsLocked"
 #define UNO_NAME_LAYER_PRINTABLE        "IsPrintable"
diff --git a/sd/source/ui/unoidl/unoobj.cxx b/sd/source/ui/unoidl/unoobj.cxx
index 49633f61bc30..2dd93e58097d 100644
--- a/sd/source/ui/unoidl/unoobj.cxx
+++ b/sd/source/ui/unoidl/unoobj.cxx
@@ -104,6 +104,8 @@ using ::com::sun::star::drawing::XShape;
 #define WID_PLACEHOLDERTEXT 24
 #define WID_LEGACYFRAGMENT  25
 
+#define WID_CUSTOMPROMPT    26
+
 #define IMPRESS_MAP_ENTRIES \
         { u"" UNO_NAME_OBJ_LEGACYFRAGMENT ""_ustr,WID_LEGACYFRAGMENT, 
cppu::UnoType<drawing::XShape>::get(),                 0, 0},\
         { u"" UNO_NAME_OBJ_ANIMATIONPATH ""_ustr, WID_ANIMPATH, 
cppu::UnoType<drawing::XShape>::get(),                 0, 0},\
@@ -128,6 +130,7 @@ using ::com::sun::star::drawing::XShape;
         { u"IsAnimation"_ustr,         WID_ISANIMATION,     
cppu::UnoType<bool>::get(),                            0, 0},\
         { u"NavigationOrder"_ustr,     WID_NAVORDER,        
cppu::UnoType<sal_Int32>::get(),                       0, 0},\
         { u"PlaceholderText"_ustr,     WID_PLACEHOLDERTEXT, 
cppu::UnoType<OUString>::get(),                        0, 0},\
+        { u"" UNO_NAME_OBJ_CUSTOMPROMPT ""_ustr, WID_CUSTOMPROMPT, 
cppu::UnoType<OUString>::get(),                        0, 0},\
 
     static std::span<const SfxItemPropertyMapEntry> 
lcl_GetImpress_SdXShapePropertyGraphicMap_Impl()
     {
@@ -574,6 +577,14 @@ void SAL_CALL SdXShape::setPropertyValue( const OUString& 
aPropertyName, const c
                 case WID_ISEMPTYPRESOBJ:
                     SetEmptyPresObj( ::cppu::any2bool(aValue) );
                     break;
+                case WID_CUSTOMPROMPT:
+                {
+                    OUString aString;
+                    if (!(aValue >>= aString))
+                        throw lang::IllegalArgumentException();
+                    SetCustomPromptText(aString);
+                    break;
+                }
                 case WID_MASTERDEPEND:
                     SetMasterDepend( ::cppu::any2bool(aValue) );
                     break;
@@ -672,6 +683,9 @@ css::uno::Any SAL_CALL SdXShape::getPropertyValue( const 
OUString& PropertyName
         case WID_ISEMPTYPRESOBJ:
             aRet <<= IsEmptyPresObj();
             break;
+        case WID_CUSTOMPROMPT:
+            aRet <<= GetCustomPromptText();
+            break;
         case WID_MASTERDEPEND:
             aRet <<= IsMasterDepend();
             break;
@@ -948,6 +962,38 @@ void SdXShape::SetEmptyPresObj(bool bEmpty)
     pObj->SetEmptyPresObj(bEmpty);
 }
 
+OUString SdXShape::GetCustomPromptText() const
+{
+    if (!IsPresObj())
+        return OUString();
+
+    SdrObject* pObj = mpShape->GetSdrObject();
+    if (pObj == nullptr)
+        return OUString();
+
+    return pObj->GetCustomPromptText();
+}
+
+void SdXShape::SetCustomPromptText(const OUString& aVal)
+{
+    if (!IsPresObj() || aVal.isEmpty())
+        return;
+
+    SdrObject* pObj = mpShape->GetSdrObject();
+    if (pObj == nullptr)
+        return;
+
+    if (!pObj->getSdrPageFromSdrObject()->IsMasterPage())
+    {
+        if (pObj->getSdrPageFromSdrObject()->RestoreDefaultText(pObj, aVal))
+            pObj->SetCustomPromptText(aVal);
+    }
+    else
+    {
+        pObj->SetCustomPromptText(aVal);
+    }
+}
+
 bool SdXShape::IsMasterDepend() const noexcept
 {
     SdrObject* pObj = mpShape->GetSdrObject();
diff --git a/sd/source/ui/unoidl/unoobj.hxx b/sd/source/ui/unoidl/unoobj.hxx
index 7c78bc520dcd..52206ea21a4a 100644
--- a/sd/source/ui/unoidl/unoobj.hxx
+++ b/sd/source/ui/unoidl/unoobj.hxx
@@ -57,6 +57,9 @@ private:
     bool IsEmptyPresObj() const;
     void SetEmptyPresObj(bool bEmpty);
 
+    OUString GetCustomPromptText() const;
+    void SetCustomPromptText(const OUString& aVal);
+
     bool IsMasterDepend() const noexcept;
     void SetMasterDepend( bool bDepend ) noexcept;
 
diff --git a/sd/source/ui/view/NotesPanelView.cxx 
b/sd/source/ui/view/NotesPanelView.cxx
index 42562275b70f..3ed6d4690f6b 100644
--- a/sd/source/ui/view/NotesPanelView.cxx
+++ b/sd/source/ui/view/NotesPanelView.cxx
@@ -219,7 +219,7 @@ void NotesPanelView::onLoseFocus()
             // if the notes are empty restore the placeholder text and state.
             SdPage* pPage = 
dynamic_cast<SdPage*>(pNotesTextObj->getSdrPageFromSdrObject());
             if (pPage)
-                pPage->RestoreDefaultText(pNotesTextObj);
+                pPage->RestoreDefaultText(pNotesTextObj, 
pNotesTextObj->GetCustomPromptText());
         }
         else
             setNotesToDoc();
diff --git a/sd/source/ui/view/drawview.cxx b/sd/source/ui/view/drawview.cxx
index c6da08c44f29..5f139cb620b4 100644
--- a/sd/source/ui/view/drawview.cxx
+++ b/sd/source/ui/view/drawview.cxx
@@ -592,7 +592,7 @@ void DrawView::DeleteMarked()
                     SdrTextObj* pTextObj = DynCastSdrTextObj( pObj );
                     bool bVertical = pTextObj && pTextObj->IsVerticalWriting();
                     ::tools::Rectangle aRect( pObj->GetLogicRect() );
-                    SdrObject* pNewObj = pPage->InsertAutoLayoutShape( 
nullptr, ePresObjKind, bVertical, aRect, true );
+                    SdrObject* pNewObj = pPage->InsertAutoLayoutShape(nullptr, 
ePresObjKind, bVertical, aRect, OUString(), true);
 
                     // pUndoManager should not be NULL (see assert above)
                     // but since we have defensive code
diff --git a/sd/source/ui/view/outlnvsh.cxx b/sd/source/ui/view/outlnvsh.cxx
index e6e66c77558d..ea1347ccc42b 100644
--- a/sd/source/ui/view/outlnvsh.cxx
+++ b/sd/source/ui/view/outlnvsh.cxx
@@ -1620,7 +1620,7 @@ void OutlineViewShell::UpdateTitleObject( SdPage* pPage, 
Paragraph const * pPara
                 // make it empty
                 if( pOlView->isRecordingUndo() )
                     
pOlView->AddUndo(GetDoc()->GetSdrUndoFactory().CreateUndoObjectSetText(*pTO,0));
-                pPage->RestoreDefaultText( pTO );
+                pPage->RestoreDefaultText( pTO, pTO->GetCustomPromptText() );
                 pTO->SetEmptyPresObj(true);
                 pTO->ActionChanged();
             }
@@ -1720,7 +1720,7 @@ void OutlineViewShell::UpdateOutlineObject( SdPage* 
pPage, Paragraph* pPara )
                 // delete old OutlinerParaObject, too
                 if( pOlView->isRecordingUndo() )
                     
pOlView->AddUndo(GetDoc()->GetSdrUndoFactory().CreateUndoObjectSetText(*pTO,0));
-                pPage->RestoreDefaultText( pTO );
+                pPage->RestoreDefaultText( pTO, pTO->GetCustomPromptText() );
                 pTO->SetEmptyPresObj(true);
                 pTO->ActionChanged();
             }
diff --git a/sd/source/ui/view/outlview.cxx b/sd/source/ui/view/outlview.cxx
index cf5d0e081ae6..256a505dd9e6 100644
--- a/sd/source/ui/view/outlview.cxx
+++ b/sd/source/ui/view/outlview.cxx
@@ -908,7 +908,7 @@ SdrTextObj* OutlineView::CreateTitleTextObject(SdPage* 
pPage)
     {
         // we already have a layout with a title but the title
         // object was deleted, create a new one
-        pPage->InsertAutoLayoutShape( nullptr, PresObjKind::Title, false, 
pPage->GetTitleRect(), true );
+        pPage->InsertAutoLayoutShape( nullptr, PresObjKind::Title, false, 
pPage->GetTitleRect(), OUString(), true );
     }
 
     return GetTitleTextObject(pPage);
@@ -944,7 +944,7 @@ SdrTextObj* OutlineView::CreateOutlineTextObject(SdPage* 
pPage)
         // object was deleted, create a new one
         pPage->InsertAutoLayoutShape( nullptr,
                                       PresObjKind::Outline,
-                                      false, pPage->GetLayoutRect(), true );
+                                      false, pPage->GetLayoutRect(), 
OUString(), true );
     }
 
     return GetOutlineTextObject(pPage);
diff --git a/sd/source/ui/view/sdview.cxx b/sd/source/ui/view/sdview.cxx
index 5a6be3034fb8..4ae79b48177e 100644
--- a/sd/source/ui/view/sdview.cxx
+++ b/sd/source/ui/view/sdview.cxx
@@ -853,7 +853,7 @@ bool View::RestoreDefaultText( SdrTextObj* pTextObj )
 
             if(pPage)
             {
-                bRestored = pPage->RestoreDefaultText( pTextObj );
+                bRestored = pPage->RestoreDefaultText( pTextObj, 
pTextObj->GetCustomPromptText() );
                 if( bRestored )
                 {
                     SdrOutliner* pOutliner = GetTextEditOutliner();
diff --git a/svx/source/svdraw/svdobj.cxx b/svx/source/svdraw/svdobj.cxx
index 4eb5146a0c0e..88226a6bfa1a 100644
--- a/svx/source/svdraw/svdobj.cxx
+++ b/svx/source/svdraw/svdobj.cxx
@@ -1779,6 +1779,7 @@ bool SdrObject::Equals(const SdrObject& rOtherObj) const
     return (m_aAnchor.X() == rOtherObj.m_aAnchor.X() && m_aAnchor.Y() == 
rOtherObj.m_aAnchor.Y() &&
             m_nOrdNum == rOtherObj.m_nOrdNum && mnNavigationPosition == 
rOtherObj.mnNavigationPosition &&
             mbSupportTextIndentingOnLineWidthChange == 
rOtherObj.mbSupportTextIndentingOnLineWidthChange &&
+            m_aCustomPromptText == rOtherObj.m_aCustomPromptText &&
             mbLineIsOutsideGeometry == rOtherObj.mbLineIsOutsideGeometry && 
m_bMarkProt == rOtherObj.m_bMarkProt &&
             m_bIs3DObj == rOtherObj.m_bIs3DObj && m_bIsEdge == 
rOtherObj.m_bIsEdge && m_bClosedObj == rOtherObj.m_bClosedObj &&
             m_bNotVisibleAsMaster == rOtherObj.m_bNotVisibleAsMaster && 
m_bEmptyPresObj == rOtherObj.m_bEmptyPresObj &&
@@ -2578,6 +2579,10 @@ void SdrObject::SetEmptyPresObj(bool bEpt)
     m_bEmptyPresObj = bEpt;
 }
 
+void SdrObject::SetCustomPromptText(const OUString& rVal)
+{
+    m_aCustomPromptText = rVal;
+}
 
 void SdrObject::SetNotVisibleAsMaster(bool bFlg)
 {
diff --git a/svx/source/svdraw/svdpage.cxx b/svx/source/svdraw/svdpage.cxx
index 672f89b2bb87..755b95c284f2 100644
--- a/svx/source/svdraw/svdpage.cxx
+++ b/svx/source/svdraw/svdpage.cxx
@@ -1726,6 +1726,12 @@ void SdrPage::MakePageObjectsNamesUnique()
     }
 }
 
+bool SdrPage::RestoreDefaultText(SdrObject* /*pObj*/, const OUString& /*rStr*/)
+{
+    assert(false);
+    return false;
+}
+
 const SdrPageGridFrameList* SdrPage::GetGridFrameList(const SdrPageView* 
/*pPV*/, const tools::Rectangle* /*pRect*/) const
 {
     return nullptr;

Reply via email to