sw/inc/textboxhelper.hxx                     |   14 
 sw/qa/uitest/writer_tests7/tdf143574.py      |    3 
 sw/source/core/doc/DocumentLayoutManager.cxx |   81 +++-
 sw/source/core/doc/docdraw.cxx               |   30 +
 sw/source/core/doc/docfly.cxx                |    4 
 sw/source/core/doc/docfmt.cxx                |    7 
 sw/source/core/doc/textboxhelper.cxx         |  456 ++++++++++++++-------------
 sw/source/core/draw/dcontact.cxx             |   31 +
 sw/source/core/draw/dview.cxx                |   12 
 sw/source/core/frmedt/fecopy.cxx             |    4 
 sw/source/core/frmedt/fefly1.cxx             |   22 +
 sw/source/core/frmedt/feshview.cxx           |    6 
 sw/source/core/layout/atrfrm.cxx             |   15 
 sw/source/core/layout/flycnt.cxx             |    2 
 sw/source/core/text/porfly.cxx               |   13 
 sw/source/core/undo/undraw.cxx               |  110 ++++++
 sw/source/core/unocore/unodraw.cxx           |    7 
 sw/source/uibase/shells/drawsh.cxx           |    4 
 18 files changed, 531 insertions(+), 290 deletions(-)

New commits:
commit ba5156abace2e41ec4d21397c0875f7e1efd2beb
Author:     Attila Bakos (NISZ) <bakos.attilakar...@nisz.hu>
AuthorDate: Wed Sep 1 16:38:07 2021 +0200
Commit:     László Németh <nem...@numbertext.org>
CommitDate: Thu Sep 16 12:56:10 2021 +0200

    tdf#143574 tdf#144271 sw: textboxes in group shapes - part 2
    
    Sync textboxes with group shapes, adding textboxes to
    group shapes, copying textboxes with group shapes,
    grouping/ungrouping group shapes with textboxes, removing
    textboxes from group shapes.
    
    This patch fixes a memory leak (tdf#144271) introduced
    by commit 504d78acb866495fd954fcd6db22ea68f174a5ab
    "tdf#143574 sw: textboxes in group shapes - part 1".
    
    Note: AS_CHAR anchoring is far not the best for group
    shapes and import/export is still missing.
    
    Change-Id: I7dc3b8d36c4a04f792ae4742fe4a45af9227a17e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/121449
    Tested-by: László Németh <nem...@numbertext.org>
    Reviewed-by: László Németh <nem...@numbertext.org>

diff --git a/sw/inc/textboxhelper.hxx b/sw/inc/textboxhelper.hxx
index 3cd442ed7194..978cf77327b9 100644
--- a/sw/inc/textboxhelper.hxx
+++ b/sw/inc/textboxhelper.hxx
@@ -69,10 +69,10 @@ public:
 
     /// Sync property of TextBox with the one of the shape.
     static void syncProperty(SwFrameFormat* pShape, sal_uInt16 nWID, sal_uInt8 
nMemberID,
-                             const css::uno::Any& rValue);
+                             const css::uno::Any& rValue, SdrObject* pObj = 
nullptr);
     /// Does the same, but works on properties which lack an sw-specific WID / 
MemberID.
     static void syncProperty(SwFrameFormat* pShape, std::u16string_view 
rPropertyName,
-                             const css::uno::Any& rValue);
+                             const css::uno::Any& rValue, SdrObject* pObj = 
nullptr);
     /// Get a property of the underlying TextFrame.
     static void getProperty(SwFrameFormat const* pShape, sal_uInt16 nWID, 
sal_uInt8 nMemberID,
                             css::uno::Any& rValue);
@@ -83,7 +83,7 @@ public:
     static css::text::TextContentAnchorType mapAnchorType(const RndStdIds& 
rAnchorID);
 
     /// Similar to syncProperty(), but used by the internal API (e.g. for UI 
purposes).
-    static void syncFlyFrameAttr(SwFrameFormat& rShape, SfxItemSet const& 
rSet);
+    static void syncFlyFrameAttr(SwFrameFormat& rShape, SfxItemSet const& 
rSet, SdrObject* pObj);
 
     /// Copy shape attributes to the text frame
     static void updateTextBoxMargin(SdrObject* pObj);
@@ -94,11 +94,11 @@ public:
 
     /// Sets the anchor of the associated textframe of the given shape, and
     /// returns true on success.
-    static bool changeAnchor(SwFrameFormat* pShape);
+    static bool changeAnchor(SwFrameFormat* pShape, SdrObject* pObj);
 
     /// Does the positioning for the associated textframe of the shape, and
     /// returns true on success.
-    static bool doTextBoxPositioning(SwFrameFormat* pShape);
+    static bool doTextBoxPositioning(SwFrameFormat* pShape, SdrObject* pObj);
 
     /// Returns true if the anchor different for the  given shape, and the
     /// associated textframe of the given shape.
@@ -112,7 +112,7 @@ public:
 
     // Returns true on success. Synchronize z-order of the text frame of the 
given textbox
     // by setting it one level higher than the z-order of the shape of the 
textbox.
-    static bool DoTextBoxZOrderCorrection(SwFrameFormat* pShape);
+    static bool DoTextBoxZOrderCorrection(SwFrameFormat* pShape, SdrObject* 
pObj);
 
     /**
      * If we have an associated TextFrame, then return that.
@@ -134,7 +134,7 @@ public:
     static css::uno::Reference<css::text::XTextFrame>
     getUnoTextFrame(css::uno::Reference<css::drawing::XShape> const& xShape);
     /// Return the textbox rectangle of a draw shape (in twips).
-    static tools::Rectangle getTextRectangle(SwFrameFormat* pShape, bool 
bAbsolute = true);
+    static tools::Rectangle getTextRectangle(SdrObject* pShape, bool bAbsolute 
= true);
 
     /**
      * Is the frame format a text box?
diff --git a/sw/qa/uitest/writer_tests7/tdf143574.py 
b/sw/qa/uitest/writer_tests7/tdf143574.py
index 08e59b7c682a..61265e229f57 100644
--- a/sw/qa/uitest/writer_tests7/tdf143574.py
+++ b/sw/qa/uitest/writer_tests7/tdf143574.py
@@ -33,7 +33,6 @@ class tdf143574(UITestCase):
             # At this point the Writer crashed here before the fix.
             self.xUITest.executeCommand(".uno:AddTextBox");
 
-            #follow up commit will introduce:
-            #self.assertEqual(True, 
document.DrawPage.getByIndex(0).getByIndex(2).TextBox)
+            self.assertEqual(True, 
document.DrawPage.getByIndex(0).getByIndex(2).TextBox)
 
 # vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/sw/source/core/doc/DocumentLayoutManager.cxx 
b/sw/source/core/doc/DocumentLayoutManager.cxx
index 1e071ef3ac5e..4cee8ad7c0b0 100644
--- a/sw/source/core/doc/DocumentLayoutManager.cxx
+++ b/sw/source/core/doc/DocumentLayoutManager.cxx
@@ -41,6 +41,7 @@
 #include <frameformats.hxx>
 #include <com/sun/star/embed/EmbedStates.hpp>
 #include <svx/svdobj.hxx>
+#include <svx/svdpage.hxx>
 #include <osl/diagnose.h>
 
 using namespace ::com::sun::star;
@@ -463,38 +464,64 @@ SwFrameFormat *DocumentLayoutManager::CopyLayoutFormat(
         pDest->MakeFrames();
 
     // If the draw format has a TextBox, then copy its fly format as well.
-    if (SwFrameFormat* pSourceTextBox = 
SwTextBoxHelper::getOtherTextBoxFormat(&rSource, RES_DRAWFRMFMT))
+    if (rSource.Which() == RES_DRAWFRMFMT && rSource.GetOtherTextBoxFormat())
     {
-        SwFormatAnchor boxAnchor(rNewAnchor);
-        if (RndStdIds::FLY_AS_CHAR == boxAnchor.GetAnchorId())
-        {
-            // AS_CHAR *must not* be set on textbox fly-frame
-            boxAnchor.SetType(RndStdIds::FLY_AT_CHAR);
-        }
-        // presumably these anchors are supported though not sure
-        assert(RndStdIds::FLY_AT_CHAR == boxAnchor.GetAnchorId() || 
RndStdIds::FLY_AT_PARA == boxAnchor.GetAnchorId()
-        || boxAnchor.GetAnchorId() == RndStdIds::FLY_AT_PAGE);
+        auto pObj = rSource.FindRealSdrObject();
+        auto pTextBoxNd = new SwTextBoxNode(pDest);
+        pDest->SetOtherTextBoxFormat(pTextBoxNd);
 
-        if (!bMakeFrames && rNewAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR)
+        if (pObj)
         {
-            // If the draw format is as-char, then it will be copied with 
bMakeFrames=false, but
-            // doing the same for the fly format would result in not making 
fly frames at all.
-            bMakeFrames = true;
-        }
-
-        SwFrameFormat* pDestTextBox = CopyLayoutFormat(*pSourceTextBox,
-                boxAnchor, bSetTextFlyAtt, bMakeFrames);
-        SwAttrSet aSet(pDest->GetAttrSet());
-        SwFormatContent 
aContent(pDestTextBox->GetContent().GetContentIdx()->GetNode().GetStartNode());
-        aSet.Put(aContent);
-        pDest->SetFormatAttr(aSet);
+            const bool bIsGroupObj = pObj->getChildrenOfSdrObject();
+            for (size_t it = 0;
+                 it < (bIsGroupObj ? 
pObj->getChildrenOfSdrObject()->GetObjCount() : 1); it++)
+            {
+                auto pChild = bIsGroupObj ? 
pObj->getChildrenOfSdrObject()->GetObj(it)
+                                          : const_cast<SdrObject*>(pObj);
+                if (auto pSourceTextBox
+                    = SwTextBoxHelper::getOtherTextBoxFormat(&rSource, 
RES_DRAWFRMFMT, pChild))
+                {
+                    SwFormatAnchor boxAnchor(rNewAnchor);
+                    if (RndStdIds::FLY_AS_CHAR == boxAnchor.GetAnchorId())
+                    {
+                        // AS_CHAR *must not* be set on textbox fly-frame
+                        boxAnchor.SetType(RndStdIds::FLY_AT_CHAR);
+                    }
+                    // presumably these anchors are supported though not sure
+                    assert(RndStdIds::FLY_AT_CHAR == boxAnchor.GetAnchorId()
+                           || RndStdIds::FLY_AT_PARA == boxAnchor.GetAnchorId()
+                           || boxAnchor.GetAnchorId() == 
RndStdIds::FLY_AT_PAGE);
 
-        // Link FLY and DRAW formats, so it becomes a text box
-        auto pTextBox = new SwTextBoxNode(pDest);
-        pTextBox->AddTextBox(pDest->FindRealSdrObject(), pDestTextBox);
+                    if (!bMakeFrames && rNewAnchor.GetAnchorId() == 
RndStdIds::FLY_AS_CHAR)
+                    {
+                        // If the draw format is as-char, then it will be 
copied with bMakeFrames=false, but
+                        // doing the same for the fly format would result in 
not making fly frames at all.
+                        bMakeFrames = true;
+                    }
+                    SwFrameFormat* pDestTextBox
+                        = CopyLayoutFormat(*pSourceTextBox, boxAnchor, 
bSetTextFlyAtt, bMakeFrames);
+
+                    SwAttrSet aSet(pDest->GetAttrSet());
+                    SwFormatContent aContent(
+                        
pDestTextBox->GetContent().GetContentIdx()->GetNode().GetStartNode());
+                    aSet.Put(aContent);
+                    pDest->SetFormatAttr(aSet);
+
+                    // Link FLY and DRAW formats, so it becomes a text box
+                    SdrObject* pNewObj = pDest->FindRealSdrObject();
+                    if (bIsGroupObj && pDest && pDest->FindRealSdrObject()
+                        && pDest->FindRealSdrObject()->getChildrenOfSdrObject()
+                        && 
(pDest->FindRealSdrObject()->getChildrenOfSdrObject()->GetObjCount() > it)
+                        && 
pDest->FindRealSdrObject()->getChildrenOfSdrObject()->GetObj(it))
+                        pNewObj = 
pDest->FindRealSdrObject()->getChildrenOfSdrObject()->GetObj(it);
+                    pTextBoxNd->AddTextBox(pNewObj, pDestTextBox);
+                    pDestTextBox->SetOtherTextBoxFormat(pTextBoxNd);
+                }
 
-        pDest->SetOtherTextBoxFormat(pTextBox);
-        pDestTextBox->SetOtherTextBoxFormat(pTextBox);
+                if (!bIsGroupObj)
+                    break;
+            }
+        }
     }
 
     if (pDest->GetName().isEmpty())
diff --git a/sw/source/core/doc/docdraw.cxx b/sw/source/core/doc/docdraw.cxx
index 609b174072e0..0aff4b8993ff 100644
--- a/sw/source/core/doc/docdraw.cxx
+++ b/sw/source/core/doc/docdraw.cxx
@@ -208,6 +208,8 @@ SwDrawContact* SwDoc::GroupSelection( SdrView& rDrawView )
                 static_cast<SwAnchoredDrawObject*>(pMyContact->GetAnchoredObj( 
pObj ));
             bGroupMembersNotPositioned = pAnchoredDrawObj->NotYetPositioned();
         }
+
+        std::vector<std::pair<SwFrameFormat*, SdrObject*>> vSavedTextBoxes;
         // Destroy ContactObjects and formats.
         for( size_t i = 0; i < rMrkList.GetMarkCount(); ++i )
         {
@@ -221,6 +223,9 @@ SwDrawContact* SwDoc::GroupSelection( SdrView& rDrawView )
             OSL_ENSURE( bGroupMembersNotPositioned == 
pAnchoredDrawObj->NotYetPositioned(),
                     "<SwDoc::GroupSelection(..)> - group members have 
different positioning status!" );
 #endif
+            // Before the format will be killed, save its textbox for later 
use.
+            if (auto pTextBox = 
SwTextBoxHelper::getOtherTextBoxFormat(pContact->GetFormat(), RES_DRAWFRMFMT, 
pObj))
+                vSavedTextBoxes.push_back(std::pair<SwFrameFormat*, 
SdrObject*>(pTextBox, pObj));
 
             pFormat = static_cast<SwDrawFrameFormat*>(pContact->GetFormat());
             // Deletes itself!
@@ -247,6 +252,16 @@ SwDrawContact* SwDoc::GroupSelection( SdrView& rDrawView )
         pFormat->SetPositionLayoutDir(
             text::PositionLayoutDir::PositionInLayoutDirOfAnchor );
 
+        // Add the saved textboxes to the new format.
+        auto pTextBoxNode = new SwTextBoxNode(pFormat);
+        for (auto& pTextBoxEntry : vSavedTextBoxes)
+        {
+            pTextBoxNode->AddTextBox(pTextBoxEntry.second, 
pTextBoxEntry.first);
+            pTextBoxEntry.first->SetOtherTextBoxFormat(pTextBoxNode);
+        }
+        pFormat->SetOtherTextBoxFormat(pTextBoxNode);
+        vSavedTextBoxes.clear();
+
         rDrawView.GroupMarked();
         OSL_ENSURE( rMrkList.GetMarkCount() == 1, "GroupMarked more or none 
groups." );
 
@@ -311,6 +326,11 @@ void SwDoc::UnGroupSelection( SdrView& rDrawView )
                 if ( auto pObjGroup = dynamic_cast<SdrObjGroup*>(pObj) )
                 {
                     SwDrawContact *pContact = 
static_cast<SwDrawContact*>(GetUserCall(pObj));
+
+                    SwTextBoxNode* pTextBoxNode = nullptr;
+                    if (auto pGroupFormat = pContact->GetFormat())
+                        pTextBoxNode = pGroupFormat->GetOtherTextBoxFormat();
+
                     SwFormatAnchor aAnch( pContact->GetFormat()->GetAnchor() );
                     SdrObjList *pLst = pObjGroup->GetSubList();
 
@@ -327,6 +347,16 @@ void SwDoc::UnGroupSelection( SdrView& rDrawView )
                         SwDrawFrameFormat *pFormat = MakeDrawFrameFormat( 
GetUniqueShapeName(),
                                                             
GetDfltFrameFormat() );
                         pFormat->SetFormatAttr( aAnch );
+
+                        if (pTextBoxNode)
+                            if (auto pTextBoxFormat = 
pTextBoxNode->GetTextBox(pSubObj))
+                            {
+                                auto pNewTextBoxNode = new 
SwTextBoxNode(pFormat);
+                                pNewTextBoxNode->AddTextBox(pSubObj, 
pTextBoxFormat);
+                                
pFormat->SetOtherTextBoxFormat(pNewTextBoxNode);
+                                
pTextBoxFormat->SetOtherTextBoxFormat(pNewTextBoxNode);
+                            }
+
                         // #i36010# - set layout direction of the position
                         pFormat->SetPositionLayoutDir(
                             
text::PositionLayoutDir::PositionInLayoutDirOfAnchor );
diff --git a/sw/source/core/doc/docfly.cxx b/sw/source/core/doc/docfly.cxx
index 6ff9bf910240..d8fe293c7f0a 100644
--- a/sw/source/core/doc/docfly.cxx
+++ b/sw/source/core/doc/docfly.cxx
@@ -577,7 +577,7 @@ bool SwDoc::SetFlyFrameAttr( SwFrameFormat& rFlyFormat, 
SfxItemSet& rSet )
 
     getIDocumentState().SetModified();
 
-    SwTextBoxHelper::syncFlyFrameAttr(rFlyFormat, rSet);
+    //SwTextBoxHelper::syncFlyFrameAttr(rFlyFormat, rSet);
 
     return bRet;
 }
@@ -924,7 +924,7 @@ bool SwDoc::ChgAnchor( const SdrMarkList& _rMrkList,
                                                                RES_DRAWFRMFMT))
                     {
                         
SwTextBoxHelper::syncFlyFrameAttr(*pContact->GetFormat(),
-                                                          
pContact->GetFormat()->GetAttrSet());
+                                                          
pContact->GetFormat()->GetAttrSet(), pObj);
                     }
                 }
                 break;
diff --git a/sw/source/core/doc/docfmt.cxx b/sw/source/core/doc/docfmt.cxx
index 16ad4d8dfcd0..d2ccfaf81544 100644
--- a/sw/source/core/doc/docfmt.cxx
+++ b/sw/source/core/doc/docfmt.cxx
@@ -483,8 +483,11 @@ void SwDoc::SetAttr( const SfxItemSet& rSet, SwFormat& 
rFormat )
     auto pShapeFormat = dynamic_cast<SwFrameFormat*>(&rFormat);
     if (pShapeFormat && SwTextBoxHelper::isTextBox(pShapeFormat, 
RES_DRAWFRMFMT))
     {
-        SwTextBoxHelper::syncFlyFrameAttr(*pShapeFormat, rSet);
-        SwTextBoxHelper::changeAnchor(pShapeFormat);
+        if (auto pObj = pShapeFormat->FindRealSdrObject())
+        {
+            SwTextBoxHelper::syncFlyFrameAttr(*pShapeFormat, rSet, pObj);
+            SwTextBoxHelper::changeAnchor(pShapeFormat, pObj);
+        }
     }
 
     getIDocumentState().SetModified();
diff --git a/sw/source/core/doc/textboxhelper.cxx 
b/sw/source/core/doc/textboxhelper.cxx
index 3858da359a3c..93b9564a59bf 100644
--- a/sw/source/core/doc/textboxhelper.cxx
+++ b/sw/source/core/doc/textboxhelper.cxx
@@ -61,9 +61,10 @@ using namespace com::sun::star;
 
 void SwTextBoxHelper::create(SwFrameFormat* pShape, SdrObject* pObject, bool 
bCopyText)
 {
-    if (dynamic_cast<SdrObjGroup*>(pObject->getParentSdrObjectFromSdrObject()))
-        // The GroupShape Textbox creation method call comes here.
-        return;
+    assert(pShape);
+    assert(pObject);
+
+    const bool bIsGroupObj = 
dynamic_cast<SdrObjGroup*>(pObject->getParentSdrObjectFromSdrObject());
 
     // If TextBox wasn't enabled previously
     if (pShape->GetOtherTextBoxFormat() && 
pShape->GetOtherTextBoxFormat()->GetTextBox(pObject))
@@ -74,9 +75,9 @@ void SwTextBoxHelper::create(SwFrameFormat* pShape, 
SdrObject* pObject, bool bCo
 
     if (bCopyText)
     {
-        if (auto pSdrShape = pShape->FindRealSdrObject())
+        if (pObject)
         {
-            uno::Reference<text::XText> xSrcCnt(pSdrShape->getWeakUnoShape(), 
uno::UNO_QUERY);
+            uno::Reference<text::XText> xSrcCnt(pObject->getWeakUnoShape(), 
uno::UNO_QUERY);
             auto xCur = xSrcCnt->createTextCursor();
             xCur->gotoStart(false);
             xCur->gotoEnd(true);
@@ -94,8 +95,7 @@ void SwTextBoxHelper::create(SwFrameFormat* pShape, 
SdrObject* pObject, bool bCo
                                                                 
uno::UNO_QUERY);
     try
     {
-        SdrObject* pSourceSDRShape = pShape->FindRealSdrObject();
-        uno::Reference<text::XTextContent> 
XSourceShape(pSourceSDRShape->getUnoShape(),
+        uno::Reference<text::XTextContent> XSourceShape(pObject->getUnoShape(),
                                                         uno::UNO_QUERY_THROW);
         xTextContentAppend->insertTextContentWithProperties(
             xTextFrame, uno::Sequence<beans::PropertyValue>(), 
XSourceShape->getAnchor());
@@ -155,45 +155,47 @@ void SwTextBoxHelper::create(SwFrameFormat* pShape, 
SdrObject* pObject, bool bCo
         pShape->SetFormatAttr(aSet);
     }
 
-    DoTextBoxZOrderCorrection(pShape);
+    DoTextBoxZOrderCorrection(pShape, pObject);
+
     // Also initialize the properties, which are not constant, but inherited 
from the shape's ones.
-    uno::Reference<drawing::XShape> 
xShape(pShape->FindRealSdrObject()->getUnoShape(),
-                                           uno::UNO_QUERY);
-    syncProperty(pShape, RES_FRM_SIZE, MID_FRMSIZE_SIZE, 
uno::makeAny(xShape->getSize()));
+    uno::Reference<drawing::XShape> xShape(pObject->getUnoShape(), 
uno::UNO_QUERY);
+    syncProperty(pShape, RES_FRM_SIZE, MID_FRMSIZE_SIZE, 
uno::makeAny(xShape->getSize()), pObject);
 
     uno::Reference<beans::XPropertySet> xShapePropertySet(xShape, 
uno::UNO_QUERY);
     syncProperty(pShape, RES_FOLLOW_TEXT_FLOW, MID_FOLLOW_TEXT_FLOW,
-                 
xShapePropertySet->getPropertyValue(UNO_NAME_IS_FOLLOWING_TEXT_FLOW));
+                 
xShapePropertySet->getPropertyValue(UNO_NAME_IS_FOLLOWING_TEXT_FLOW), pObject);
     syncProperty(pShape, RES_ANCHOR, MID_ANCHOR_ANCHORTYPE,
-                 xShapePropertySet->getPropertyValue(UNO_NAME_ANCHOR_TYPE));
+                 xShapePropertySet->getPropertyValue(UNO_NAME_ANCHOR_TYPE), 
pObject);
     syncProperty(pShape, RES_HORI_ORIENT, MID_HORIORIENT_ORIENT,
-                 xShapePropertySet->getPropertyValue(UNO_NAME_HORI_ORIENT));
+                 xShapePropertySet->getPropertyValue(UNO_NAME_HORI_ORIENT), 
pObject);
     syncProperty(pShape, RES_HORI_ORIENT, MID_HORIORIENT_RELATION,
-                 
xShapePropertySet->getPropertyValue(UNO_NAME_HORI_ORIENT_RELATION));
+                 
xShapePropertySet->getPropertyValue(UNO_NAME_HORI_ORIENT_RELATION), pObject);
     syncProperty(pShape, RES_VERT_ORIENT, MID_VERTORIENT_ORIENT,
-                 xShapePropertySet->getPropertyValue(UNO_NAME_VERT_ORIENT));
+                 xShapePropertySet->getPropertyValue(UNO_NAME_VERT_ORIENT), 
pObject);
     syncProperty(pShape, RES_VERT_ORIENT, MID_VERTORIENT_RELATION,
-                 
xShapePropertySet->getPropertyValue(UNO_NAME_VERT_ORIENT_RELATION));
+                 
xShapePropertySet->getPropertyValue(UNO_NAME_VERT_ORIENT_RELATION), pObject);
     syncProperty(pShape, RES_HORI_ORIENT, MID_HORIORIENT_POSITION,
-                 
xShapePropertySet->getPropertyValue(UNO_NAME_HORI_ORIENT_POSITION));
+                 
xShapePropertySet->getPropertyValue(UNO_NAME_HORI_ORIENT_POSITION), pObject);
     syncProperty(pShape, RES_VERT_ORIENT, MID_VERTORIENT_POSITION,
-                 
xShapePropertySet->getPropertyValue(UNO_NAME_VERT_ORIENT_POSITION));
+                 
xShapePropertySet->getPropertyValue(UNO_NAME_VERT_ORIENT_POSITION), pObject);
     syncProperty(pShape, RES_FRM_SIZE, MID_FRMSIZE_IS_AUTO_HEIGHT,
-                 
xShapePropertySet->getPropertyValue(UNO_NAME_TEXT_AUTOGROWHEIGHT));
+                 
xShapePropertySet->getPropertyValue(UNO_NAME_TEXT_AUTOGROWHEIGHT), pObject);
     syncProperty(pShape, RES_TEXT_VERT_ADJUST, 0,
-                 
xShapePropertySet->getPropertyValue(UNO_NAME_TEXT_VERT_ADJUST));
+                 
xShapePropertySet->getPropertyValue(UNO_NAME_TEXT_VERT_ADJUST), pObject);
     text::WritingMode eMode;
     if (xShapePropertySet->getPropertyValue(UNO_NAME_TEXT_WRITINGMODE) >>= 
eMode)
-        syncProperty(pShape, RES_FRAMEDIR, 0, uno::makeAny(sal_Int16(eMode)));
+        syncProperty(pShape, RES_FRAMEDIR, 0, uno::makeAny(sal_Int16(eMode)), 
pObject);
+
+    if (bIsGroupObj)
+        doTextBoxPositioning(pShape, pObject);
 
     // Check if the shape had text before and move it to the new textframe
     if (!bCopyText || sCopyableText.isEmpty())
         return;
 
-    auto pSdrShape = pShape->FindRealSdrObject();
-    if (pSdrShape)
+    if (pObject)
     {
-        auto pSourceText = dynamic_cast<SdrTextObj*>(pSdrShape);
+        auto pSourceText = dynamic_cast<SdrTextObj*>(pObject);
         uno::Reference<text::XTextRange> xDestText(xRealTextFrame, 
uno::UNO_QUERY);
 
         xDestText->setString(sCopyableText);
@@ -415,12 +417,14 @@ uno::Any SwTextBoxHelper::queryInterface(const 
SwFrameFormat* pShape, const uno:
     return aRet;
 }
 
-tools::Rectangle SwTextBoxHelper::getTextRectangle(SwFrameFormat* pShape, bool 
bAbsolute)
+tools::Rectangle SwTextBoxHelper::getTextRectangle(SdrObject* pShape, bool 
bAbsolute)
 {
     tools::Rectangle aRet;
     aRet.SetEmpty();
-    auto pSdrShape = pShape->FindRealSdrObject();
-    auto pCustomShape = dynamic_cast<SdrObjCustomShape*>(pSdrShape);
+
+    assert(pShape);
+
+    auto pCustomShape = dynamic_cast<SdrObjCustomShape*>(pShape);
     if (pCustomShape)
     {
         // Need to temporarily release the lock acquired in
@@ -435,17 +439,17 @@ tools::Rectangle 
SwTextBoxHelper::getTextRectangle(SwFrameFormat* pShape, bool b
         if (nLocks)
             xLockable->setActionLocks(nLocks);
     }
-    else if (pSdrShape)
+    else if (pShape)
     {
         // fallback - get *any* bound rect we can possibly get hold of
-        aRet = pSdrShape->GetCurrentBoundRect();
+        aRet = pShape->GetCurrentBoundRect();
     }
 
-    if (!bAbsolute && pSdrShape)
+    if (!bAbsolute && pShape)
     {
         // Relative, so count the logic (reference) rectangle, see the 
EnhancedCustomShape2d ctor.
-        Point aPoint(pSdrShape->GetSnapRect().Center());
-        Size aSize(pSdrShape->GetLogicRect().GetSize());
+        Point aPoint(pShape->GetSnapRect().Center());
+        Size aSize(pShape->GetLogicRect().GetSize());
         aPoint.AdjustX(-(aSize.Width() / 2));
         aPoint.AdjustY(-(aSize.Height() / 2));
         tools::Rectangle aLogicRect(aPoint, aSize);
@@ -456,12 +460,12 @@ tools::Rectangle 
SwTextBoxHelper::getTextRectangle(SwFrameFormat* pShape, bool b
 }
 
 void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, std::u16string_view 
rPropertyName,
-                                   const css::uno::Any& rValue)
+                                   const css::uno::Any& rValue, SdrObject* 
pObj)
 {
     // Textframes does not have valid horizontal adjust property, so map it to 
paragraph adjust property
     if (rPropertyName == UNO_NAME_TEXT_HORZADJUST)
     {
-        SwFrameFormat* pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT);
+        SwFrameFormat* pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT, 
pObj);
         if (!pFormat)
             return;
 
@@ -506,7 +510,7 @@ void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, 
std::u16string_view rP
         // CustomShapeGeometry changes the textbox position offset and size, 
so adjust both.
         syncProperty(pShape, RES_FRM_SIZE, MID_FRMSIZE_SIZE, uno::Any());
 
-        SdrObject* pObject = pShape->FindRealSdrObject();
+        SdrObject* pObject = pObj ? pObj : pShape->FindRealSdrObject();
         if (pObject)
         {
             tools::Rectangle aRectangle(pObject->GetSnapRect());
@@ -518,7 +522,7 @@ void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, 
std::u16string_view rP
                 
uno::makeAny(static_cast<sal_Int32>(convertTwipToMm100(aRectangle.Top()))));
         }
 
-        SwFrameFormat* pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT);
+        SwFrameFormat* pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT, 
pObj);
         if (!pFormat)
             return;
 
@@ -555,30 +559,30 @@ void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, 
std::u16string_view rP
 
             if (nDirection)
             {
-                syncProperty(pShape, RES_FRAMEDIR, 0, 
uno::makeAny(nDirection));
+                syncProperty(pShape, RES_FRAMEDIR, 0, 
uno::makeAny(nDirection), pObj);
             }
         }
     }
     else if (rPropertyName == UNO_NAME_TEXT_VERT_ADJUST)
-        syncProperty(pShape, RES_TEXT_VERT_ADJUST, 0, rValue);
+        syncProperty(pShape, RES_TEXT_VERT_ADJUST, 0, rValue, pObj);
     else if (rPropertyName == UNO_NAME_TEXT_AUTOGROWHEIGHT)
-        syncProperty(pShape, RES_FRM_SIZE, MID_FRMSIZE_IS_AUTO_HEIGHT, rValue);
+        syncProperty(pShape, RES_FRM_SIZE, MID_FRMSIZE_IS_AUTO_HEIGHT, rValue, 
pObj);
     else if (rPropertyName == UNO_NAME_TEXT_LEFTDIST)
-        syncProperty(pShape, RES_BOX, LEFT_BORDER_DISTANCE, rValue);
+        syncProperty(pShape, RES_BOX, LEFT_BORDER_DISTANCE, rValue, pObj);
     else if (rPropertyName == UNO_NAME_TEXT_RIGHTDIST)
-        syncProperty(pShape, RES_BOX, RIGHT_BORDER_DISTANCE, rValue);
+        syncProperty(pShape, RES_BOX, RIGHT_BORDER_DISTANCE, rValue, pObj);
     else if (rPropertyName == UNO_NAME_TEXT_UPPERDIST)
-        syncProperty(pShape, RES_BOX, TOP_BORDER_DISTANCE, rValue);
+        syncProperty(pShape, RES_BOX, TOP_BORDER_DISTANCE, rValue, pObj);
     else if (rPropertyName == UNO_NAME_TEXT_LOWERDIST)
-        syncProperty(pShape, RES_BOX, BOTTOM_BORDER_DISTANCE, rValue);
+        syncProperty(pShape, RES_BOX, BOTTOM_BORDER_DISTANCE, rValue, pObj);
     else if (rPropertyName == UNO_NAME_TEXT_WRITINGMODE)
     {
         text::WritingMode eMode;
         sal_Int16 eMode2;
         if (rValue >>= eMode)
-            syncProperty(pShape, RES_FRAMEDIR, 0, 
uno::makeAny(sal_Int16(eMode)));
+            syncProperty(pShape, RES_FRAMEDIR, 0, 
uno::makeAny(sal_Int16(eMode)), pObj);
         else if (rValue >>= eMode2)
-            syncProperty(pShape, RES_FRAMEDIR, 0, uno::makeAny(eMode2));
+            syncProperty(pShape, RES_FRAMEDIR, 0, uno::makeAny(eMode2), pObj);
     }
     else
         SAL_INFO("sw.core", "SwTextBoxHelper::syncProperty: unhandled 
property: "
@@ -635,7 +639,7 @@ css::uno::Any SwTextBoxHelper::getProperty(SwFrameFormat 
const* pShape, const OU
 }
 
 void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, sal_uInt16 nWID, 
sal_uInt8 nMemberID,
-                                   const css::uno::Any& rValue)
+                                   const css::uno::Any& rValue, SdrObject* 
pObj)
 {
     // No shape yet? Then nothing to do, initial properties are set by 
create().
     if (!pShape)
@@ -644,7 +648,7 @@ void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, 
sal_uInt16 nWID, sal_u
     uno::Any aValue(rValue);
     nMemberID &= ~CONVERT_TWIPS;
 
-    SwFrameFormat* pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT);
+    SwFrameFormat* pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT, 
pObj);
     if (!pFormat)
         return;
 
@@ -745,8 +749,8 @@ void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, 
sal_uInt16 nWID, sal_u
                 case MID_ANCHOR_ANCHORTYPE:
                 {
                     setWrapThrough(pShape);
-                    changeAnchor(pShape);
-                    doTextBoxPositioning(pShape);
+                    changeAnchor(pShape, pObj);
+                    doTextBoxPositioning(pShape, pObj);
 
                     return;
                 }
@@ -844,7 +848,9 @@ void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, 
sal_uInt16 nWID, sal_u
     // Position/size should be the text position/size, not the shape one as-is.
     if (bAdjustX || bAdjustY || bAdjustSize)
     {
-        tools::Rectangle aRect = getTextRectangle(pShape, /*bAbsolute=*/false);
+        changeAnchor(pShape, pObj);
+        tools::Rectangle aRect
+            = getTextRectangle(pObj ? pObj : pShape->FindRealSdrObject(), 
/*bAbsolute=*/false);
         if (!aRect.IsEmpty())
         {
             if (bAdjustX || bAdjustY)
@@ -929,9 +935,10 @@ text::TextContentAnchorType 
SwTextBoxHelper::mapAnchorType(const RndStdIds& rAnc
     return aAnchorType;
 }
 
-void SwTextBoxHelper::syncFlyFrameAttr(SwFrameFormat& rShape, SfxItemSet 
const& rSet)
+void SwTextBoxHelper::syncFlyFrameAttr(SwFrameFormat& rShape, SfxItemSet 
const& rSet,
+                                       SdrObject* pObj)
 {
-    SwFrameFormat* pFormat = getOtherTextBoxFormat(&rShape, RES_DRAWFRMFMT);
+    SwFrameFormat* pFormat = getOtherTextBoxFormat(&rShape, RES_DRAWFRMFMT, 
pObj);
     if (!pFormat)
         return;
 
@@ -950,12 +957,14 @@ void SwTextBoxHelper::syncFlyFrameAttr(SwFrameFormat& 
rShape, SfxItemSet const&
                 // The new position can be with anchor changing so sync it!
                 const text::TextContentAnchorType aNewAnchorType
                     = mapAnchorType(rShape.GetAnchor().GetAnchorId());
-                syncProperty(&rShape, RES_ANCHOR, MID_ANCHOR_ANCHORTYPE, 
uno::Any(aNewAnchorType));
+                syncProperty(&rShape, RES_ANCHOR, MID_ANCHOR_ANCHORTYPE, 
uno::Any(aNewAnchorType),
+                             pObj);
                 if (bInlineAnchored)
                     return;
                 SwFormatVertOrient 
aOrient(pItem->StaticWhichCast(RES_VERT_ORIENT));
 
-                tools::Rectangle aRect = getTextRectangle(&rShape, 
/*bAbsolute=*/false);
+                tools::Rectangle aRect = getTextRectangle(pObj ? pObj : 
rShape.FindRealSdrObject(),
+                                                          /*bAbsolute=*/false);
                 if (!aRect.IsEmpty())
                     aOrient.SetPos(aOrient.GetPos() + aRect.Top());
 
@@ -978,12 +987,14 @@ void SwTextBoxHelper::syncFlyFrameAttr(SwFrameFormat& 
rShape, SfxItemSet const&
                 // The new position can be with anchor changing so sync it!
                 const text::TextContentAnchorType aNewAnchorType
                     = mapAnchorType(rShape.GetAnchor().GetAnchorId());
-                syncProperty(&rShape, RES_ANCHOR, MID_ANCHOR_ANCHORTYPE, 
uno::Any(aNewAnchorType));
+                syncProperty(&rShape, RES_ANCHOR, MID_ANCHOR_ANCHORTYPE, 
uno::Any(aNewAnchorType),
+                             pObj);
                 if (bInlineAnchored)
                     return;
                 SwFormatHoriOrient 
aOrient(pItem->StaticWhichCast(RES_HORI_ORIENT));
 
-                tools::Rectangle aRect = getTextRectangle(&rShape, 
/*bAbsolute=*/false);
+                tools::Rectangle aRect = getTextRectangle(pObj ? pObj : 
rShape.FindRealSdrObject(),
+                                                          /*bAbsolute=*/false);
                 if (!aRect.IsEmpty())
                     aOrient.SetPos(aOrient.GetPos() + aRect.Left());
 
@@ -1003,13 +1014,18 @@ void SwTextBoxHelper::syncFlyFrameAttr(SwFrameFormat& 
rShape, SfxItemSet const&
                 SwFormatHoriOrient aHoriOrient(rShape.GetHoriOrient());
                 SwFormatFrameSize aSize(pFormat->GetFrameSize());
 
-                tools::Rectangle aRect = getTextRectangle(&rShape, 
/*bAbsolute=*/false);
+                tools::Rectangle aRect = getTextRectangle(pObj ? pObj : 
rShape.FindRealSdrObject(),
+                                                          /*bAbsolute=*/false);
                 if (!aRect.IsEmpty())
                 {
                     if (!bInlineAnchored)
                     {
-                        aVertOrient.SetPos(aVertOrient.GetPos() + aRect.Top());
-                        aHoriOrient.SetPos(aHoriOrient.GetPos() + 
aRect.Left());
+                        aVertOrient.SetPos(
+                            (pObj ? pObj->GetRelativePos().getX() : 
aVertOrient.GetPos())
+                            + aRect.Top());
+                        aHoriOrient.SetPos(
+                            (pObj ? pObj->GetRelativePos().getY() : 
aHoriOrient.GetPos())
+                            + aRect.Left());
 
                         aTextBoxSet.Put(aVertOrient);
                         aTextBoxSet.Put(aHoriOrient);
@@ -1029,7 +1045,7 @@ void SwTextBoxHelper::syncFlyFrameAttr(SwFrameFormat& 
rShape, SfxItemSet const&
                     const text::TextContentAnchorType aNewAnchorType
                         = mapAnchorType(rShape.GetAnchor().GetAnchorId());
                     syncProperty(&rShape, RES_ANCHOR, MID_ANCHOR_ANCHORTYPE,
-                                 uno::Any(aNewAnchorType));
+                                 uno::Any(aNewAnchorType), pObj);
                 }
                 else
                 {
@@ -1048,9 +1064,10 @@ void SwTextBoxHelper::syncFlyFrameAttr(SwFrameFormat& 
rShape, SfxItemSet const&
     } while (pItem && (0 != pItem->Which()));
 
     if (aTextBoxSet.Count())
-        pFormat->GetDoc()->SetFlyFrameAttr(*pFormat, aTextBoxSet);
+        pFormat->SetFormatAttr(aTextBoxSet);
+    //pFormat->GetDoc()->SetFlyFrameAttr(*pFormat, aTextBoxSet);
 
-    DoTextBoxZOrderCorrection(&rShape);
+    DoTextBoxZOrderCorrection(&rShape, pObj);
 }
 
 void SwTextBoxHelper::updateTextBoxMargin(SdrObject* pObj)
@@ -1092,8 +1109,8 @@ void SwTextBoxHelper::updateTextBoxMargin(SdrObject* pObj)
     syncProperty(pParentFormat, RES_FRM_SIZE, MID_FRMSIZE_WIDTH_TYPE,
                  uno::Any(bIsAutoWrap ? text::SizeType::FIX : 
text::SizeType::MIN));
 
-    changeAnchor(pParentFormat);
-    DoTextBoxZOrderCorrection(pParentFormat);
+    changeAnchor(pParentFormat, pObj);
+    DoTextBoxZOrderCorrection(pParentFormat, pObj);
 }
 
 bool SwTextBoxHelper::setWrapThrough(SwFrameFormat* pShape)
@@ -1129,147 +1146,147 @@ bool SwTextBoxHelper::setWrapThrough(SwFrameFormat* 
pShape)
     return false;
 }
 
-bool SwTextBoxHelper::changeAnchor(SwFrameFormat* pShape)
+bool SwTextBoxHelper::changeAnchor(SwFrameFormat* pShape, SdrObject* pObj)
 {
-    if (isTextBoxShapeHasValidTextFrame(pShape))
+    if (auto pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT, pObj))
     {
-        if (auto pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT))
-        {
-            const SwFormatAnchor& rOldAnch = pFormat->GetAnchor();
-            const SwFormatAnchor& rNewAnch = pShape->GetAnchor();
+        const SwFormatAnchor& rOldAnch = pFormat->GetAnchor();
+        const SwFormatAnchor& rNewAnch = pShape->GetAnchor();
 
-            const auto pOldCnt = rOldAnch.GetContentAnchor();
-            const auto pNewCnt = rNewAnch.GetContentAnchor();
+        const auto pOldCnt = rOldAnch.GetContentAnchor();
+        const auto pNewCnt = rNewAnch.GetContentAnchor();
 
-            const uno::Any aShapeHorRelOrient
-                = uno::makeAny(pShape->GetHoriOrient().GetRelationOrient());
+        const uno::Any aShapeHorRelOrient
+            = uno::makeAny(pShape->GetHoriOrient().GetRelationOrient());
 
-            if (isAnchorTypeDifferent(pShape))
+        if (isAnchorTypeDifferent(pShape) || (pObj && pObj != 
pShape->FindRealSdrObject()))
+        {
+            try
             {
-                try
+                ::sw::UndoGuard const 
UndoGuard(pShape->GetDoc()->GetIDocumentUndoRedo());
+                uno::Reference<beans::XPropertySet> const xPropertySet(
+                    SwXTextFrame::CreateXTextFrame(*pFormat->GetDoc(), 
pFormat), uno::UNO_QUERY);
+                if (pOldCnt && rNewAnch.GetAnchorId() == RndStdIds::FLY_AT_PAGE
+                    && rNewAnch.GetPageNum())
                 {
-                    ::sw::UndoGuard const 
UndoGuard(pShape->GetDoc()->GetIDocumentUndoRedo());
-                    uno::Reference<beans::XPropertySet> const xPropertySet(
-                        SwXTextFrame::CreateXTextFrame(*pFormat->GetDoc(), 
pFormat),
-                        uno::UNO_QUERY);
-                    if (pOldCnt && rNewAnch.GetAnchorId() == 
RndStdIds::FLY_AT_PAGE
-                        && rNewAnch.GetPageNum())
+                    uno::Any aValue(text::TextContentAnchorType_AT_PAGE);
+                    
xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION,
+                                                   aShapeHorRelOrient);
+                    xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, 
aValue);
+                    xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_PAGE_NO,
+                                                   
uno::Any(rNewAnch.GetPageNum()));
+                }
+                else if (rOldAnch.GetAnchorId() == RndStdIds::FLY_AT_PAGE && 
pNewCnt)
+                {
+                    if (rNewAnch.GetAnchorId() == RndStdIds::FLY_AS_CHAR)
+                    {
+                        uno::Any 
aValue(text::TextContentAnchorType_AT_CHARACTER);
+                        xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, 
aValue);
+                        
xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION,
+                                                       
uno::Any(text::RelOrientation::CHAR));
+                        
xPropertySet->setPropertyValue(UNO_NAME_VERT_ORIENT_RELATION,
+                                                       
uno::Any(text::RelOrientation::PRINT_AREA));
+                        SwFormatAnchor aPos(pFormat->GetAnchor());
+                        aPos.SetAnchor(pNewCnt);
+                        pFormat->SetFormatAttr(aPos);
+                    }
+                    else
                     {
-                        uno::Any aValue(text::TextContentAnchorType_AT_PAGE);
+                        uno::Any aValue(mapAnchorType(rNewAnch.GetAnchorId()));
                         
xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION,
                                                        aShapeHorRelOrient);
                         xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, 
aValue);
-                        xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_PAGE_NO,
-                                                       
uno::Any(rNewAnch.GetPageNum()));
+                        pFormat->SetFormatAttr(rNewAnch);
                     }
-                    else if (rOldAnch.GetAnchorId() == RndStdIds::FLY_AT_PAGE 
&& pNewCnt)
+                }
+                else
+                {
+                    if (rNewAnch.GetAnchorId() == RndStdIds::FLY_AS_CHAR)
                     {
-                        if (rNewAnch.GetAnchorId() == RndStdIds::FLY_AS_CHAR)
-                        {
-                            uno::Any 
aValue(text::TextContentAnchorType_AT_CHARACTER);
-                            
xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, aValue);
-                            
xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION,
-                                                           
uno::Any(text::RelOrientation::CHAR));
-                            xPropertySet->setPropertyValue(
-                                UNO_NAME_VERT_ORIENT_RELATION,
-                                uno::Any(text::RelOrientation::PRINT_AREA));
-                            SwFormatAnchor aPos(pFormat->GetAnchor());
-                            aPos.SetAnchor(pNewCnt);
-                            pFormat->SetFormatAttr(aPos);
-                        }
-                        else
-                        {
-                            uno::Any 
aValue(mapAnchorType(rNewAnch.GetAnchorId()));
-                            
xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION,
-                                                           aShapeHorRelOrient);
-                            
xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, aValue);
-                            pFormat->SetFormatAttr(rNewAnch);
-                        }
+                        uno::Any 
aValue(text::TextContentAnchorType_AT_CHARACTER);
+                        xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, 
aValue);
+                        
xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION,
+                                                       
uno::Any(text::RelOrientation::CHAR));
+                        
xPropertySet->setPropertyValue(UNO_NAME_VERT_ORIENT_RELATION,
+                                                       
uno::Any(text::RelOrientation::PRINT_AREA));
+                        SwFormatAnchor aPos(pFormat->GetAnchor());
+                        aPos.SetAnchor(pNewCnt);
+                        pFormat->SetFormatAttr(aPos);
                     }
                     else
                     {
-                        if (rNewAnch.GetAnchorId() == RndStdIds::FLY_AS_CHAR)
-                        {
-                            uno::Any 
aValue(text::TextContentAnchorType_AT_CHARACTER);
-                            
xPropertySet->setPropertyValue(UNO_NAME_ANCHOR_TYPE, aValue);
-                            
xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION,
-                                                           
uno::Any(text::RelOrientation::CHAR));
-                            xPropertySet->setPropertyValue(
-                                UNO_NAME_VERT_ORIENT_RELATION,
-                                uno::Any(text::RelOrientation::PRINT_AREA));
-                            SwFormatAnchor aPos(pFormat->GetAnchor());
-                            aPos.SetAnchor(pNewCnt);
-                            pFormat->SetFormatAttr(aPos);
-                        }
-                        else
-                        {
-                            
xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION,
-                                                           aShapeHorRelOrient);
-                            pFormat->SetFormatAttr(pShape->GetAnchor());
-                        }
+                        
xPropertySet->setPropertyValue(UNO_NAME_HORI_ORIENT_RELATION,
+                                                       aShapeHorRelOrient);
+                        pFormat->SetFormatAttr(pShape->GetAnchor());
                     }
                 }
-                catch (uno::Exception& e)
-                {
-                    SAL_WARN("sw.core", "SwTextBoxHelper::changeAnchor(): " << 
e.Message);
-                }
             }
-
-            return doTextBoxPositioning(pShape) && 
DoTextBoxZOrderCorrection(pShape);
+            catch (uno::Exception& e)
+            {
+                SAL_WARN("sw.core", "SwTextBoxHelper::changeAnchor(): " << 
e.Message);
+            }
         }
+
+        return doTextBoxPositioning(pShape, pObj) && 
DoTextBoxZOrderCorrection(pShape, pObj);
     }
+
     return false;
 }
 
-bool SwTextBoxHelper::doTextBoxPositioning(SwFrameFormat* pShape)
+bool SwTextBoxHelper::doTextBoxPositioning(SwFrameFormat* pShape, SdrObject* 
pObj)
 {
-    if (isTextBoxShapeHasValidTextFrame(pShape))
+    const bool bIsGroupObj = (pObj != pShape->FindRealSdrObject()) && pObj;
+    if (auto pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT, pObj))
     {
-        if (auto pFormat = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT))
+        ::sw::UndoGuard const 
UndoGuard(pShape->GetDoc()->GetIDocumentUndoRedo());
+        if (pShape->GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR)
         {
-            ::sw::UndoGuard const 
UndoGuard(pShape->GetDoc()->GetIDocumentUndoRedo());
-            if (pShape->GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR)
-            {
-                tools::Rectangle aRect(getTextRectangle(pShape, false));
+            tools::Rectangle aRect(
+                getTextRectangle(pObj ? pObj : pShape->FindRealSdrObject(), 
false));
 
-                auto nLeftSpace = pShape->GetLRSpace().GetLeft();
+            auto nLeftSpace = pShape->GetLRSpace().GetLeft();
 
-                SwFormatHoriOrient aNewHOri(pFormat->GetHoriOrient());
-                aNewHOri.SetPos(aRect.Left() + nLeftSpace);
+            SwFormatHoriOrient aNewHOri(pFormat->GetHoriOrient());
+            aNewHOri.SetPos(aRect.Left() + nLeftSpace);
 
-                SwFormatVertOrient aNewVOri(pFormat->GetVertOrient());
-                aNewVOri.SetPos(aRect.Top() + 
pShape->GetVertOrient().GetPos());
+            SwFormatVertOrient aNewVOri(pFormat->GetVertOrient());
+            aNewVOri.SetPos(aRect.Top() + pShape->GetVertOrient().GetPos());
 
-                // tdf#140598: Do not apply wrong rectangle position.
-                if (aRect.TopLeft() != Point(0, 0))
-                {
-                    pFormat->SetFormatAttr(aNewHOri);
-                    pFormat->SetFormatAttr(aNewVOri);
-                }
-                else
-                    SAL_WARN("sw.core", "SwTextBoxHelper::syncProperty: 
Repositioning failed!");
+            // tdf#140598: Do not apply wrong rectangle position.
+            if (aRect.TopLeft() != Point(0, 0))
+            {
+                pFormat->SetFormatAttr(aNewHOri);
+                pFormat->SetFormatAttr(aNewVOri);
             }
             else
-            {
-                tools::Rectangle aRect(getTextRectangle(pShape, false));
-
-                // tdf#140598: Do not apply wrong rectangle position.
-                if (aRect.TopLeft() != Point(0, 0))
-                {
-                    SwFormatHoriOrient aNewHOri(pShape->GetHoriOrient());
-                    aNewHOri.SetPos(aNewHOri.GetPos() + aRect.Left());
-                    SwFormatVertOrient aNewVOri(pShape->GetVertOrient());
-                    aNewVOri.SetPos(aNewVOri.GetPos() + aRect.Top());
+                SAL_WARN("sw.core", "SwTextBoxHelper::syncProperty: 
Repositioning failed!");
+        }
+        else
+        {
+            tools::Rectangle aRect(
+                getTextRectangle(pObj ? pObj : pShape->FindRealSdrObject(), 
false));
 
-                    pFormat->SetFormatAttr(aNewHOri);
-                    pFormat->SetFormatAttr(aNewVOri);
-                }
-                else
-                    SAL_WARN("sw.core", "SwTextBoxHelper::syncProperty: 
Repositioning failed!");
+            // tdf#140598: Do not apply wrong rectangle position.
+            if (aRect.TopLeft() != Point(0, 0) || bIsGroupObj)
+            {
+                SwFormatHoriOrient aNewHOri(pShape->GetHoriOrient());
+                aNewHOri.SetPos(
+                    (bIsGroupObj && pObj ? pObj->GetRelativePos().getX() : 
aNewHOri.GetPos())
+                    + aRect.Left());
+                SwFormatVertOrient aNewVOri(pShape->GetVertOrient());
+                aNewVOri.SetPos(
+                    (bIsGroupObj && pObj ? pObj->GetRelativePos().getY() : 
aNewVOri.GetPos())
+                    + aRect.Top());
+
+                pFormat->SetFormatAttr(aNewHOri);
+                pFormat->SetFormatAttr(aNewVOri);
             }
-            return true;
+            else
+                SAL_WARN("sw.core", "SwTextBoxHelper::syncProperty: 
Repositioning failed!");
         }
+        return true;
     }
+
     return false;
 }
 
@@ -1307,52 +1324,59 @@ bool 
SwTextBoxHelper::isTextBoxShapeHasValidTextFrame(const SwFrameFormat* pShap
     return false;
 }
 
-bool SwTextBoxHelper::DoTextBoxZOrderCorrection(SwFrameFormat* pShape)
+bool SwTextBoxHelper::DoTextBoxZOrderCorrection(SwFrameFormat* pShape, 
SdrObject* pObj)
 {
-    if (isTextBoxShapeHasValidTextFrame(pShape))
+    // TODO: do this with group shape textboxes.
+    SdrObject* pShpObj = nullptr;
+    //if (pObj)
+    //    pShpObj = pObj;
+    //else
+    pShpObj = pShape->FindRealSdrObject();
+
+    if (pShpObj)
     {
-        if (SdrObject* pShpObj = pShape->FindRealSdrObject())
+        if (SdrObject* pFrmObj
+            = getOtherTextBoxFormat(pShape, RES_DRAWFRMFMT, 
pObj)->FindRealSdrObject())
         {
-            if (SdrObject* pFrmObj
-                = getOtherTextBoxFormat(pShape, 
RES_DRAWFRMFMT)->FindRealSdrObject())
+            // Get the draw model from the doc
+            SwDrawModel* pDrawModel
+                = 
pShape->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel();
+            if (pDrawModel)
             {
-                // Get the draw model from the doc
-                SwDrawModel* pDrawModel
-                    = 
pShape->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel();
-                if (pDrawModel)
-                {
-                    // Not really sure this will work all page, but it seems 
it will.
-                    auto pPage = pDrawModel->GetPage(0);
-                    // Recalc all Zorders
-                    pPage->RecalcObjOrdNums();
-                    // If the shape is behind the frame, is good, but if there 
are some objects
-                    // between of them that is wrong so put the frame exactly 
one level higher
-                    // than the shape.
-                    if (pFrmObj->GetOrdNum() > pShpObj->GetOrdNum())
-                        pPage->SetObjectOrdNum(pFrmObj->GetOrdNum(), 
pShpObj->GetOrdNum() + 1);
-                    else
-                        // Else, if the frame is behind the shape, bring to 
the front of it.
-                        while (pFrmObj->GetOrdNum() <= pShpObj->GetOrdNum())
-                        {
-                            pPage->SetObjectOrdNum(pFrmObj->GetOrdNum(), 
pFrmObj->GetOrdNum() + 1);
-                            // If there is any problem with the indexes, do 
not run over the infinity
-                            if (pPage->GetObjCount() == pFrmObj->GetOrdNum())
-                                break;
-                        }
-                    pPage->RecalcObjOrdNums();
-                    return true; // Success
-                }
-                SAL_WARN("sw.core", 
"SwTextBoxHelper::DoTextBoxZOrderCorrection(): "
-                                    "No Valid Draw model for SdrObject for the 
shape!");
+                // Not really sure this will work all page, but it seems it 
will.
+                auto pPage = pDrawModel->GetPage(0);
+                // Recalc all Zorders
+                pPage->RecalcObjOrdNums();
+                // Here is a counter avoiding running to in infinity:
+                sal_uInt16 nIterator = 0;
+                // If the shape is behind the frame, is good, but if there are 
some objects
+                // between of them that is wrong so put the frame exactly one 
level higher
+                // than the shape.
+                if (pFrmObj->GetOrdNum() > pShpObj->GetOrdNum())
+                    pPage->SetObjectOrdNum(pFrmObj->GetOrdNum(), 
pShpObj->GetOrdNum() + 1);
+                else
+                    // Else, if the frame is behind the shape, bring to the 
front of it.
+                    while (pFrmObj->GetOrdNum() <= pShpObj->GetOrdNum())
+                    {
+                        pPage->SetObjectOrdNum(pFrmObj->GetOrdNum(), 
pFrmObj->GetOrdNum() + 1);
+                        // If there is any problem with the indexes, do not 
run over the infinity
+                        if (pPage->GetObjCount() == pFrmObj->GetOrdNum())
+                            break;
+                        ++nIterator;
+                        if (nIterator > 300)
+                            break; // Do not run to infinity
+                    }
+                pPage->RecalcObjOrdNums();
+                return true; // Success
             }
             SAL_WARN("sw.core", "SwTextBoxHelper::DoTextBoxZOrderCorrection(): 
"
-                                "No Valid SdrObject for the frame!");
+                                "No Valid Draw model for SdrObject for the 
shape!");
         }
         SAL_WARN("sw.core", "SwTextBoxHelper::DoTextBoxZOrderCorrection(): "
-                            "No Valid SdrObject for the shape!");
+                            "No Valid SdrObject for the frame!");
     }
     SAL_WARN("sw.core", "SwTextBoxHelper::DoTextBoxZOrderCorrection(): "
-                        "No Valid TextFrame!");
+                        "No Valid SdrObject for the shape!");
 
     return false;
 }
@@ -1369,14 +1393,10 @@ SwTextBoxNode::SwTextBoxNode(SwFrameFormat* pOwnerShape)
 
 SwTextBoxNode::~SwTextBoxNode()
 {
-    // This only happens if the shape or the doc is in dtor.
-    for (auto& rTextBoxEntry : m_pTextBoxes)
-    {
-        rTextBoxEntry.m_pDrawObject = nullptr;
-        
m_pOwnerShapeFormat->GetDoc()->getIDocumentLayoutAccess().DelLayoutFormat(
-            rTextBoxEntry.m_pTextBoxFormat);
-    }
-    m_pOwnerShapeFormat->SetOtherTextBoxFormat(nullptr);
+    m_pTextBoxes.clear();
+
+    if (m_pOwnerShapeFormat && m_pOwnerShapeFormat->GetOtherTextBoxFormat())
+        m_pOwnerShapeFormat->SetOtherTextBoxFormat(nullptr);
 }
 
 void SwTextBoxNode::AddTextBox(SdrObject* pDrawObject, SwFrameFormat* 
pNewTextBox)
@@ -1403,21 +1423,19 @@ void SwTextBoxNode::DelTextBox(SdrObject* pDrawObject)
     assert(pDrawObject);
     if (m_pTextBoxes.size())
     {
-        for (auto it = m_pTextBoxes.begin(); it != m_pTextBoxes.end(); it++)
+        for (auto it = m_pTextBoxes.begin(); it != m_pTextBoxes.end();)
         {
             if (it->m_pDrawObject == pDrawObject)
             {
                 
m_pOwnerShapeFormat->GetDoc()->getIDocumentLayoutAccess().DelLayoutFormat(
                     it->m_pTextBoxFormat);
-                m_pTextBoxes.erase(it);
+                it = m_pTextBoxes.erase(it);
                 break;
             }
+            else
+                ++it;
         }
     }
-    if (!m_pTextBoxes.size())
-    {
-        m_pOwnerShapeFormat->SetOtherTextBoxFormat(nullptr);
-    }
 }
 
 SwFrameFormat* SwTextBoxNode::GetTextBox(const SdrObject* pDrawObject) const
diff --git a/sw/source/core/draw/dcontact.cxx b/sw/source/core/draw/dcontact.cxx
index 383be2c56f51..7cd60ce197d0 100644
--- a/sw/source/core/draw/dcontact.cxx
+++ b/sw/source/core/draw/dcontact.cxx
@@ -1091,7 +1091,7 @@ static void lcl_textBoxSizeNotify(SwFrameFormat* pFormat)
         SfxItemSet aResizeSet(pFormat->GetDoc()->GetAttrPool(), 
svl::Items<RES_FRM_SIZE, RES_FRM_SIZE>);
         SwFormatFrameSize aSize;
         aResizeSet.Put(aSize);
-        SwTextBoxHelper::syncFlyFrameAttr(*pFormat, aResizeSet);
+        SwTextBoxHelper::syncFlyFrameAttr(*pFormat, aResizeSet, 
pFormat->FindRealSdrObject());
     }
 }
 
@@ -1249,6 +1249,12 @@ void SwDrawContact::Changed_( const SdrObject& rObj,
                     }
                     // use geometry of drawing object
                     aObjRect = pGroupObj->GetSnapRect();
+
+                    for (size_t i = 0; i < 
pGroupObj->getChildrenOfSdrObject()->GetObjCount(); ++i )
+                    {
+                        SwTextBoxHelper::doTextBoxPositioning(GetFormat(), 
pGroupObj->getChildrenOfSdrObject()->GetObj(i));
+                    }
+
                 }
                 SwTwips nXPosDiff(0);
                 SwTwips nYPosDiff(0);
@@ -1338,7 +1344,7 @@ void SwDrawContact::Changed_( const SdrObject& rObj,
             // tdf#135198: keep text box together with its shape
             SwRect aObjRect(rObj.GetSnapRect());
             const SwPageFrame* rPageFrame = pAnchoredDrawObj->GetPageFrame();
-            if (rPageFrame && rPageFrame->isFrameAreaPositionValid())
+            if (rPageFrame && rPageFrame->isFrameAreaPositionValid() && 
!rObj.getChildrenOfSdrObject())
             {
                 SwDoc* const pDoc = GetFormat()->GetDoc();
 
@@ -1349,14 +1355,29 @@ void SwDrawContact::Changed_( const SdrObject& rObj,
                 const bool bEnableSetModified = 
pDoc->getIDocumentState().IsEnableSetModified();
                 pDoc->getIDocumentState().SetEnableSetModified(false);
 
-                SfxItemSet aSyncSet(pDoc->GetAttrPool(),
-                                    svl::Items<RES_VERT_ORIENT, RES_ANCHOR>);
+                SfxItemSet aSyncSet(
+                    pDoc->GetAttrPool(),
+                    svl::Items<RES_VERT_ORIENT, RES_HORI_ORIENT, RES_ANCHOR, 
RES_ANCHOR>);
+                aSyncSet.Put(GetFormat()->GetHoriOrient());
                 aSyncSet.Put(SwFormatVertOrient(aObjRect.Top() - 
rPageFrame->getFrameArea().Top(),
                                                 text::VertOrientation::NONE,
                                                 
text::RelOrientation::PAGE_FRAME));
                 aSyncSet.Put(SwFormatAnchor(RndStdIds::FLY_AT_PAGE, 
pAnchoredDrawObj->GetPageFrame()->GetPhyPageNum()));
 
-                SwTextBoxHelper::syncFlyFrameAttr(*GetFormat(), aSyncSet);
+                auto pSdrObj = const_cast<SdrObject*>(&rObj);
+                if (pSdrObj != GetFormat()->FindRealSdrObject())
+                {
+                    SfxItemSet aSet(
+                        pDoc->GetAttrPool(),
+                        svl::Items<RES_FRM_SIZE, RES_FRM_SIZE>);
+
+                    aSet.Put(aSyncSet);
+                    aSet.Put(pSdrObj->GetMergedItem(RES_FRM_SIZE));
+                    SwTextBoxHelper::syncFlyFrameAttr(*GetFormat(), aSet, 
pSdrObj);
+                    SwTextBoxHelper::changeAnchor(GetFormat(), pSdrObj);
+                }
+                else
+                    SwTextBoxHelper::syncFlyFrameAttr(*GetFormat(), aSyncSet, 
GetFormat()->FindRealSdrObject());
 
                 
pDoc->getIDocumentState().SetEnableSetModified(bEnableSetModified);
             }
diff --git a/sw/source/core/draw/dview.cxx b/sw/source/core/draw/dview.cxx
index fb0e1f9c8294..33d6a83fb1f8 100644
--- a/sw/source/core/draw/dview.cxx
+++ b/sw/source/core/draw/dview.cxx
@@ -967,8 +967,16 @@ void SwDrawView::DeleteMarked()
         SdrObject *pObject = rMarkList.GetMark(i)->GetMarkedSdrObj();
         SwContact* pContact = GetUserCall(pObject);
         SwFrameFormat* pFormat = pContact->GetFormat();
-        if (SwFrameFormat* pTextBox = 
SwTextBoxHelper::getOtherTextBoxFormat(pFormat, RES_DRAWFRMFMT))
-            aTextBoxesToDelete.push_back(pTextBox);
+        if (auto pChildren = pObject->getChildrenOfSdrObject())
+        {
+            for (size_t it = 0; it < pChildren->GetObjCount(); ++it)
+                if (SwFrameFormat* pTextBox = 
SwTextBoxHelper::getOtherTextBoxFormat(
+                        pFormat, RES_DRAWFRMFMT, pChildren->GetObj(it)))
+                    aTextBoxesToDelete.push_back(pTextBox);
+        }
+        else
+            if (SwFrameFormat* pTextBox = 
SwTextBoxHelper::getOtherTextBoxFormat(pFormat, RES_DRAWFRMFMT))
+                aTextBoxesToDelete.push_back(pTextBox);
     }
 
     if ( pDoc->DeleteSelection( *this ) )
diff --git a/sw/source/core/frmedt/fecopy.cxx b/sw/source/core/frmedt/fecopy.cxx
index 1394c7b7469b..6e3792eb9f29 100644
--- a/sw/source/core/frmedt/fecopy.cxx
+++ b/sw/source/core/frmedt/fecopy.cxx
@@ -400,9 +400,9 @@ bool SwFEShell::CopyDrawSel( SwFEShell& rDestShell, const 
Point& rSttPt,
                         if (SwDrawFrameFormat *pDrawFormat = 
dynamic_cast<SwDrawFrameFormat*>(pFormat))
                             pDrawFormat->PosAttrSet();
                     }
-                    if (SwTextBoxHelper::getOtherTextBoxFormat(pFormat, 
RES_DRAWFRMFMT))
+                    if (SwTextBoxHelper::getOtherTextBoxFormat(pFormat, 
RES_DRAWFRMFMT, pObj))
                     {
-                        SwTextBoxHelper::syncFlyFrameAttr(*pFormat, 
pFormat->GetAttrSet());
+                        SwTextBoxHelper::syncFlyFrameAttr(*pFormat, 
pFormat->GetAttrSet(), pObj);
                     }
 
                     if( bSelectInsert )
diff --git a/sw/source/core/frmedt/fefly1.cxx b/sw/source/core/frmedt/fefly1.cxx
index c8fdf46bb185..a453e9906c65 100644
--- a/sw/source/core/frmedt/fefly1.cxx
+++ b/sw/source/core/frmedt/fefly1.cxx
@@ -446,7 +446,7 @@ Point SwFEShell::FindAnchorPos( const Point& rAbsPos, bool 
bMoveIt )
     bool bTextBox = false;
     if (rFormat.Which() == RES_DRAWFRMFMT)
     {
-        bTextBox = SwTextBoxHelper::isTextBox(&rFormat, RES_DRAWFRMFMT);
+        bTextBox = SwTextBoxHelper::isTextBox(&rFormat, RES_DRAWFRMFMT, pObj);
     }
 
     SwFlyFrame* pFly = nullptr;
@@ -471,8 +471,9 @@ Point SwFEShell::FindAnchorPos( const Point& rAbsPos, bool 
bMoveIt )
     }
     else if (bTextBox)
     {
-        auto pFlyFormat = dynamic_cast<const SwFlyFrameFormat*>(
-            SwTextBoxHelper::getOtherTextBoxFormat(&rFormat, RES_DRAWFRMFMT));
+        auto pFlyFormat
+            = dynamic_cast<const 
SwFlyFrameFormat*>(SwTextBoxHelper::getOtherTextBoxFormat(
+                &rFormat, RES_DRAWFRMFMT, pObj ? pObj : 
rFormat.FindRealSdrObject()));
         if (pFlyFormat)
         {
             pFly = pFlyFormat->GetFrame();
@@ -612,9 +613,20 @@ Point SwFEShell::FindAnchorPos( const Point& rAbsPos, bool 
bMoveIt )
                                 new SwHandleAnchorNodeChg( *pFlyFrameFormat, 
aAnch ));
                         }
                         rFormat.GetDoc()->SetAttr( aAnch, rFormat );
-                        if (SwTextBoxHelper::getOtherTextBoxFormat(&rFormat, 
RES_DRAWFRMFMT))
+                        if (SwTextBoxHelper::getOtherTextBoxFormat(&rFormat, 
RES_DRAWFRMFMT,
+                            pObj ? pObj : rFormat.FindRealSdrObject()))
                         {
-                            SwTextBoxHelper::syncFlyFrameAttr(rFormat, 
rFormat.GetAttrSet());
+                            if (pObj->getChildrenOfSdrObject())
+                            {
+                                for (size_t i = 0;
+                                     i < 
pObj->getChildrenOfSdrObject()->GetObjCount(); ++i)
+                                    SwTextBoxHelper::changeAnchor(
+                                        &rFormat, 
pObj->getChildrenOfSdrObject()->GetObj(i));
+                            }
+                            else
+                                SwTextBoxHelper::syncFlyFrameAttr(
+                                    rFormat, rFormat.GetAttrSet(),
+                                    pObj ? pObj : rFormat.FindRealSdrObject());
                         }
                     }
                     // #i28701# - no call of method
diff --git a/sw/source/core/frmedt/feshview.cxx 
b/sw/source/core/frmedt/feshview.cxx
index 2041bc4e7451..c55324d48150 100644
--- a/sw/source/core/frmedt/feshview.cxx
+++ b/sw/source/core/frmedt/feshview.cxx
@@ -1102,7 +1102,7 @@ void SwFEShell::SelectionToTop( bool bTop )
                         pPage->SetObjectOrdNum(pObj->GetOrdNum(), 
pObj->GetOrdNum() + nShift);
                     }
                 // The shape is on the right level, correct the layer of the 
frame
-                SwTextBoxHelper::DoTextBoxZOrderCorrection(pFormat);
+                SwTextBoxHelper::DoTextBoxZOrderCorrection(pFormat, pObj);
             }
 
     GetDoc()->getIDocumentState().SetModified();
@@ -1152,7 +1152,7 @@ void SwFEShell::SelectionToBottom( bool bBottom )
                         }
                     }
                 // And set correct layer for the selected textbox.
-                SwTextBoxHelper::DoTextBoxZOrderCorrection(pFormat);
+                SwTextBoxHelper::DoTextBoxZOrderCorrection(pFormat, pObj);
             }
 
     GetDoc()->getIDocumentState().SetModified();
@@ -1220,7 +1220,7 @@ void SwFEShell::ChangeOpaque( SdrLayerID nLayerId )
                 pFormat->SetFormatAttr( aOpa );
                 // If pObj has textframe, put its textframe to the right level
                 if (auto pTextBx = FindFrameFormat(pObj))
-                    SwTextBoxHelper::DoTextBoxZOrderCorrection(pTextBx);
+                    SwTextBoxHelper::DoTextBoxZOrderCorrection(pTextBx, pObj);
             }
         }
     }
diff --git a/sw/source/core/layout/atrfrm.cxx b/sw/source/core/layout/atrfrm.cxx
index adcc38806465..76c961168110 100644
--- a/sw/source/core/layout/atrfrm.cxx
+++ b/sw/source/core/layout/atrfrm.cxx
@@ -90,6 +90,7 @@
 #include <hints.hxx>
 #include <frameformats.hxx>
 #include <unoprnms.hxx>
+#include <svx/svdpage.hxx>
 
 #include <ndtxt.hxx>
 
@@ -2551,16 +2552,18 @@ SwFrameFormat::~SwFrameFormat()
         auto pObj = FindRealSdrObject();
         if (Which() == RES_FLYFRMFMT && pObj)
         {
-            // This is a fly-frame-format just del this
+            // This is a fly-frame-format just delete this
             // textbox entry from the draw-frame-format.
             m_pOtherTextBoxFormat->DelTextBox(pObj);
-
-            // delete format after deleting the last textbox
-            if (!m_pOtherTextBoxFormat->GetTextBoxCount())
-                delete m_pOtherTextBoxFormat;
         }
 
-        m_pOtherTextBoxFormat = nullptr;
+        if (Which() == RES_DRAWFRMFMT)
+        {
+            // This format is the owner shape, so its time
+            // to del the textbox node.
+            delete m_pOtherTextBoxFormat;
+            m_pOtherTextBoxFormat = nullptr;
+        }
     }
 }
 
diff --git a/sw/source/core/layout/flycnt.cxx b/sw/source/core/layout/flycnt.cxx
index 33b539949917..9f3bf54debb0 100644
--- a/sw/source/core/layout/flycnt.cxx
+++ b/sw/source/core/layout/flycnt.cxx
@@ -535,7 +535,7 @@ void SwFlyAtContentFrame::MakeAll(vcl::RenderContext* 
pRenderContext)
     {
         // get the text area of the shape
         const tools::Rectangle aTextRectangle
-            = SwTextBoxHelper::getTextRectangle(pShapeFormat, false);
+            = 
SwTextBoxHelper::getTextRectangle(pShapeFormat->FindRealSdrObject(), false);
         // get the original textframe position
         SwFormatHoriOrient aHOri = pShapeFormat->GetHoriOrient();
         SwFormatVertOrient aVOri = pShapeFormat->GetVertOrient();
diff --git a/sw/source/core/text/porfly.cxx b/sw/source/core/text/porfly.cxx
index 260a1860d375..de72a0ec6076 100644
--- a/sw/source/core/text/porfly.cxx
+++ b/sw/source/core/text/porfly.cxx
@@ -375,8 +375,7 @@ void SwFlyCntPortion::SetBase( const SwTextFrame& rFrame, 
const Point &rBase,
             // of the textbox accordingly.
             // Both rectangles are absolute, SwFormatHori/VertOrient's position
             // is relative to the print area of the anchor text frame.
-            tools::Rectangle aTextRectangle = 
SwTextBoxHelper::getTextRectangle(pShape);
-            tools::Long nXoffs  = SwTextBoxHelper::getTextRectangle(pShape, 
false).Left();
+            tools::Rectangle aTextRectangle = 
SwTextBoxHelper::getTextRectangle(pSdrObj);
 
             const auto aPos(pShape->GetAnchor().GetContentAnchor());
             SwFormatVertOrient aVert(pTextBox->GetVertOrient());
@@ -385,7 +384,13 @@ void SwFlyCntPortion::SetBase( const SwTextFrame& rFrame, 
const Point &rBase,
             // tdf#138598 Replace vertical alignment of As_char textboxes in 
footer
             // tdf#140158 Remove horizontal positioning of As_char textboxes, 
because
             // the anchor moving does the same for it.
-            if (!aPos->nNode.GetNode().FindFooterStartNode())
+            const bool bIsInHeaderFooter = 
aPos->nNode.GetNode().FindFooterStartNode();
+            // TODO: Find solution for Group Shapes in Header/Footer.
+            tools::Long nXoffs
+                = SwTextBoxHelper::getTextRectangle(
+                      bIsInHeaderFooter ? pShape->FindRealSdrObject() : 
pSdrObj, false)
+                      .Left();
+            if (!bIsInHeaderFooter)
             {
                 aVert.SetVertOrient(css::text::VertOrientation::NONE);
                 aVert.SetRelationOrient(css::text::RelOrientation::FRAME);
@@ -396,7 +401,7 @@ void SwFlyCntPortion::SetBase( const SwTextFrame& rFrame, 
const Point &rBase,
             else
             {
                 aVert.SetVertOrient(css::text::VertOrientation::NONE);
-                aVert.SetPos(SwTextBoxHelper::getTextRectangle(pShape, 
false).Top());
+                
aVert.SetPos(SwTextBoxHelper::getTextRectangle(pShape->FindRealSdrObject(), 
false).Top());
             }
 
             SwFormatAnchor aNewTxBxAnchor(pTextBox->GetAnchor());
diff --git a/sw/source/core/undo/undraw.cxx b/sw/source/core/undo/undraw.cxx
index fc7efcdfec70..8fd748dda95e 100644
--- a/sw/source/core/undo/undraw.cxx
+++ b/sw/source/core/undo/undraw.cxx
@@ -41,6 +41,7 @@
 #include <dcontact.hxx>
 #include <viewsh.hxx>
 #include <frameformats.hxx>
+#include <textboxhelper.hxx>
 
 struct SwUndoGroupObjImpl
 {
@@ -196,6 +197,22 @@ void SwUndoDrawGroup::UndoImpl(::sw::UndoRedoContext &)
     auto pObj = m_pObjArray[0].pObj;
     pObj->SetUserCall(nullptr);
 
+    // This will store the textboxes what were owned by this group
+    std::vector<std::pair<SdrObject*, SwFrameFormat*>> vTextBoxes;
+    if (auto pOldTextBoxNode = pFormat->GetOtherTextBoxFormat())
+    {
+        if (auto pChildren = pObj->getChildrenOfSdrObject())
+        {
+            for (size_t idx = 0; idx < pChildren->GetObjCount(); idx++)
+            {
+                auto pChild = pChildren->GetObj(idx);
+
+                if (auto pTextBox = pOldTextBoxNode->GetTextBox(pChild))
+                    vTextBoxes.push_back(std::pair(pChild, pTextBox));
+            }
+        }
+    }
+
     ::lcl_SaveAnchor( pFormat, m_pObjArray[0].nNodeIdx );
 
     pFormat->RemoveAllUnos();
@@ -219,6 +236,18 @@ void SwUndoDrawGroup::UndoImpl(::sw::UndoRedoContext &)
         // #i45718# - follow-up of #i35635# move object to visible layer
         pContact->MoveObjToVisibleLayer( pObj );
 
+        for (auto& rElem : vTextBoxes)
+        {
+            if (rElem.first == pObj)
+            {
+                auto pNewTextBoxNode = new SwTextBoxNode(rSave.pFormat);
+                rSave.pFormat->SetOtherTextBoxFormat(pNewTextBoxNode);
+                pNewTextBoxNode->AddTextBox(rElem.first, rElem.second);
+                rElem.second->SetOtherTextBoxFormat(pNewTextBoxNode);
+                break;
+            }
+        }
+
         SwDrawFrameFormat* pDrawFrameFormat = rSave.pFormat;
 
         // #i45952# - notify that position attributes are already set
@@ -237,6 +266,9 @@ void SwUndoDrawGroup::RedoImpl(::sw::UndoRedoContext &)
     SwDoc* pDoc = m_pObjArray[0].pFormat->GetDoc();
     SwFrameFormats& rFlyFormats = *pDoc->GetSpzFrameFormats();
 
+    // This will store the textboxes from the ex-group-shapes
+    std::vector<std::pair<SdrObject*, SwFrameFormat*>> vTextBoxes;
+
     for( sal_uInt16 n = 1; n < m_nSize; ++n )
     {
         SwUndoGroupObjImpl& rSave = m_pObjArray[n];
@@ -245,6 +277,13 @@ void SwUndoDrawGroup::RedoImpl(::sw::UndoRedoContext &)
 
         SwDrawContact *pContact = 
static_cast<SwDrawContact*>(GetUserCall(pObj));
 
+        // Save the textboxes
+        if (auto pOldTextBoxNode = rSave.pFormat->GetOtherTextBoxFormat())
+        {
+            if (auto pTextBox = pOldTextBoxNode->GetTextBox(pObj))
+                vTextBoxes.push_back(std::pair(pObj, pTextBox));
+        }
+
         // object will destroy itself
         pContact->Changed( *pObj, SdrUserCallType::Delete, 
pObj->GetLastBoundRect() );
         pObj->SetUserCall( nullptr );
@@ -268,6 +307,18 @@ void SwUndoDrawGroup::RedoImpl(::sw::UndoRedoContext &)
 
     SwDrawFrameFormat* pDrawFrameFormat = m_pObjArray[0].pFormat;
 
+    // Restore the textboxes
+    if (vTextBoxes.size())
+    {
+        auto pNewTextBoxNode = new SwTextBoxNode(m_pObjArray[0].pFormat);
+        for (auto& rElem : vTextBoxes)
+        {
+            pNewTextBoxNode->AddTextBox(rElem.first, rElem.second);
+            rElem.second->SetOtherTextBoxFormat(pNewTextBoxNode);
+        }
+        m_pObjArray[0].pFormat->SetOtherTextBoxFormat(pNewTextBoxNode);
+    }
+
     // #i45952# - notify that position attributes are already set
     OSL_ENSURE(pDrawFrameFormat,
             "<SwUndoDrawGroup::Undo(..)> - wrong type of frame format for 
drawing object");
@@ -339,6 +390,9 @@ void SwUndoDrawUnGroup::UndoImpl(::sw::UndoRedoContext & 
rContext)
     SwDoc *const pDoc = & rContext.GetDoc();
     SwFrameFormats& rFlyFormats = *pDoc->GetSpzFrameFormats();
 
+    // This will store the textboxes what were owned by this group
+    std::vector<std::pair<SdrObject*, SwFrameFormat*>> vTextBoxes;
+
     // remove from array
     for( sal_uInt16 n = 1; n < m_nSize; ++n )
     {
@@ -346,6 +400,23 @@ void SwUndoDrawUnGroup::UndoImpl(::sw::UndoRedoContext & 
rContext)
 
         ::lcl_SaveAnchor( rSave.pFormat, rSave.nNodeIdx );
 
+        // copy the textboxes for later use to this vector
+        if (auto pTxBxNd = rSave.pFormat->GetOtherTextBoxFormat())
+        {
+            if (auto pGroupObj = m_pObjArray[0].pObj)
+            {
+                if (auto pChildren = pGroupObj->getChildrenOfSdrObject())
+                {
+                    for (size_t idx = 0; idx < pChildren->GetObjCount(); idx++)
+                    {
+                        auto pChild = pChildren->GetObj(idx);
+                        if (auto pTextBox = pTxBxNd->GetTextBox(pChild))
+                            vTextBoxes.push_back(std::pair(pChild, pTextBox));
+                    }
+                }
+            }
+        }
+
         rSave.pFormat->RemoveAllUnos();
 
         rFlyFormats.erase( std::find( rFlyFormats.begin(), rFlyFormats.end(), 
rSave.pFormat ));
@@ -362,6 +433,19 @@ void SwUndoDrawUnGroup::UndoImpl(::sw::UndoRedoContext & 
rContext)
 
     SwDrawFrameFormat* pDrawFrameFormat = m_pObjArray[0].pFormat;
 
+    // Restore the vector content for the new formats
+    if (vTextBoxes.size())
+    {
+        auto pNewTxBxNd = new SwTextBoxNode(m_pObjArray[0].pFormat);
+        for (auto& rElem : vTextBoxes)
+        {
+            pNewTxBxNd->AddTextBox(rElem.first, rElem.second);
+            rElem.second->SetOtherTextBoxFormat(pNewTxBxNd);
+        }
+        m_pObjArray[0].pFormat->SetOtherTextBoxFormat(pNewTxBxNd);
+    }
+
+
     // #i45952# - notify that position attributes are already set
     OSL_ENSURE(pDrawFrameFormat,
             "<SwUndoDrawGroup::Undo(..)> - wrong type of frame format for 
drawing object");
@@ -380,6 +464,19 @@ void SwUndoDrawUnGroup::RedoImpl(::sw::UndoRedoContext &)
 
     ::lcl_SaveAnchor( pFormat, m_pObjArray[0].nNodeIdx );
 
+    // Store the textboxes in this vector for later use.
+    std::vector<std::pair<SdrObject*, SwFrameFormat*>> vTextBoxes;
+    if (auto pTextBoxNode = pFormat->GetOtherTextBoxFormat())
+    {
+        auto pMasterObj = m_pObjArray[0].pObj;
+
+        if (auto pObjList = pMasterObj->getChildrenOfSdrObject())
+            for (size_t idx = 0; idx < pObjList->GetObjCount(); idx++)
+            {
+                vTextBoxes.push_back(std::pair(pObjList->GetObj(idx), 
pTextBoxNode->GetTextBox(pObjList->GetObj(idx))));
+            }
+    }
+
     pFormat->RemoveAllUnos();
 
     // remove from array
@@ -396,6 +493,19 @@ void SwUndoDrawUnGroup::RedoImpl(::sw::UndoRedoContext &)
 
         SwDrawFrameFormat* pDrawFrameFormat = rSave.pFormat;
 
+        // Restore the textboxes for the restored group shape.
+        for (auto& pElem : vTextBoxes)
+        {
+            if (pElem.first == rSave.pObj)
+            {
+                auto pTmpTxBxNd = new SwTextBoxNode(rSave.pFormat);
+                pTmpTxBxNd->AddTextBox(rSave.pObj, pElem.second);
+                pFormat->SetOtherTextBoxFormat(pTmpTxBxNd);
+                pElem.second->SetOtherTextBoxFormat(pTmpTxBxNd);
+                break;
+            }
+        }
+
         // #i45952# - notify that position attributes are already set
         OSL_ENSURE(pDrawFrameFormat,
                 "<SwUndoDrawGroup::Undo(..)> - wrong type of frame format for 
drawing object" );
diff --git a/sw/source/core/unocore/unodraw.cxx 
b/sw/source/core/unocore/unodraw.cxx
index 1ed8ec3a5d2e..580553dbf8a2 100644
--- a/sw/source/core/unocore/unodraw.cxx
+++ b/sw/source/core/unocore/unodraw.cxx
@@ -949,6 +949,7 @@ void SwXShape::AddExistingShapeToFormat( SdrObject const & 
_rObj )
 SwXShape::~SwXShape()
 {
     SolarMutexGuard aGuard;
+
     if (m_xShapeAgg.is())
     {
         uno::Reference< uno::XInterface >  xRef;
@@ -1505,7 +1506,11 @@ uno::Any SwXShape::getPropertyValue(const OUString& 
rPropertyName)
                 }
                 else if (pEntry->nWID == FN_TEXT_BOX)
                 {
-                    bool bValue = SwTextBoxHelper::isTextBox(pFormat, 
RES_DRAWFRMFMT);
+                    auto pSvxShape = GetSvxShape();
+                    bool bValue = SwTextBoxHelper::isTextBox(
+                        pFormat, RES_DRAWFRMFMT,
+                        ((pSvxShape && pSvxShape->GetSdrObject()) ? 
pSvxShape->GetSdrObject()
+                                                                  : 
pFormat->FindRealSdrObject()));
                     aRet <<= bValue;
                 }
                 else if (pEntry->nWID == RES_CHAIN)
diff --git a/sw/source/uibase/shells/drawsh.cxx 
b/sw/source/uibase/shells/drawsh.cxx
index beb197c87fa9..52a3b0d02beb 100644
--- a/sw/source/uibase/shells/drawsh.cxx
+++ b/sw/source/uibase/shells/drawsh.cxx
@@ -498,7 +498,7 @@ void SwDrawShell::GetState(SfxItemSet& rSet)
                 {
                     SwFrameFormat* pFrameFormat = ::FindFrameFormat(pObj);
                     // Allow creating a TextBox only in case this is a draw 
format without a TextBox so far.
-                    if (pFrameFormat && pFrameFormat->Which() == 
RES_DRAWFRMFMT && !SwTextBoxHelper::isTextBox(pFrameFormat, RES_DRAWFRMFMT))
+                    if (pFrameFormat && pFrameFormat->Which() == 
RES_DRAWFRMFMT && !SwTextBoxHelper::isTextBox(pFrameFormat, RES_DRAWFRMFMT, 
pObj))
                     {
                         if (SdrObjCustomShape* pCustomShape = 
dynamic_cast<SdrObjCustomShape*>( pObj) )
                         {
@@ -521,7 +521,7 @@ void SwDrawShell::GetState(SfxItemSet& rSet)
                 {
                     SwFrameFormat* pFrameFormat = ::FindFrameFormat(pObj);
                     // Allow removing a TextBox only in case it has one.
-                    if (pFrameFormat && 
SwTextBoxHelper::isTextBox(pFrameFormat, RES_DRAWFRMFMT))
+                    if (pFrameFormat && 
SwTextBoxHelper::isTextBox(pFrameFormat, RES_DRAWFRMFMT, pObj))
                         bDisable = false;
                 }
 

Reply via email to