Related: tdf#70062 keep drawing anchor objects sorted

take attachment from tdf#70062, ungroup the bottom pair,
anchor as char the left one, anchor as char the right one

asserts with debugging stl on unsorted container

Change-Id: I3ae763f6d61445f9118ee573a98c69d7a6ee6e4b
diff --git a/sw/source/core/doc/docfly.cxx b/sw/source/core/doc/docfly.cxx
index 5548ccd..acd472d 100644
--- a/sw/source/core/doc/docfly.cxx
+++ b/sw/source/core/doc/docfly.cxx
@@ -737,7 +737,8 @@ bool SwDoc::ChgAnchor( const SdrMarkList& _rMrkList,
                _eAnchorType = eOldAnchorType;

            SwFmtAnchor aNewAnch( _eAnchorType );
            Rectangle aObjRect( pContact->GetAnchoredObj( pObj )->GetObjRect().SVRect() );
            SwAnchoredObject *pAnchoredObj = pContact->GetAnchoredObj(pObj);
            Rectangle aObjRect(pAnchoredObj->GetObjRect().SVRect());
            const Point aPt( aObjRect.TopLeft() );

            switch ( _eAnchorType )
@@ -894,6 +895,10 @@ bool SwDoc::ChgAnchor( const SdrMarkList& _rMrkList,
                }
            }

            // we have changed the anchoring attributes, and those are used to
            // order the object in its sorted list, so update its position
            pAnchoredObj->UpdateObjInSortedList();

            // #i54336#
            if (xOldAsCharAnchorPos)
            {
diff --git a/sw/source/core/inc/sortedobjs.hxx b/sw/source/core/inc/sortedobjs.hxx
index 9605360..a57ed15 100644
--- a/sw/source/core/inc/sortedobjs.hxx
+++ b/sw/source/core/inc/sortedobjs.hxx
@@ -74,7 +74,8 @@ class SwSortedObjs

            @return boolean, indicating success of the update.
        */
        bool Update( SwAnchoredObject& _rAnchoredObj );
        bool Update(SwAnchoredObject& _rAnchoredObj);
        void UpdateAll();

        /** Position of object <_rAnchoredObj> in sorted list

@@ -85,6 +86,8 @@ class SwSortedObjs
            Number of the list position of object <_rAnchoredObj>
        */
        size_t ListPosOf( const SwAnchoredObject& _rAnchoredObj ) const;

        bool is_sorted() const;
};

#endif
diff --git a/sw/source/core/layout/fly.cxx b/sw/source/core/layout/fly.cxx
index b8b942b..529d194 100644
--- a/sw/source/core/layout/fly.cxx
+++ b/sw/source/core/layout/fly.cxx
@@ -2069,6 +2069,8 @@ void SwFrm::RemoveFly( SwFlyFrm *pToRemove )

void SwFrm::AppendDrawObj( SwAnchoredObject& _rNewObj )
{
    assert(!mpDrawObjs || mpDrawObjs->is_sorted());

    if ( !_rNewObj.ISA(SwAnchoredDrawObject) )
    {
        OSL_FAIL( "SwFrm::AppendDrawObj(..) - anchored object of unexpected type -> object not appended" );
@@ -2078,10 +2080,12 @@ void SwFrm::AppendDrawObj( SwAnchoredObject& _rNewObj )
    if ( !_rNewObj.GetDrawObj()->ISA(SwDrawVirtObj) &&
         _rNewObj.GetAnchorFrm() && _rNewObj.GetAnchorFrm() != this )
    {
        assert(!mpDrawObjs || mpDrawObjs->is_sorted());
        // perform disconnect from layout, if 'master' drawing object is appended
        // to a new frame.
        static_cast<SwDrawContact*>(::GetUserCall( _rNewObj.GetDrawObj() ))->
                                                DisconnectFromLayout( false );
        assert(!mpDrawObjs || mpDrawObjs->is_sorted());
    }

    if ( _rNewObj.GetAnchorFrm() != this )
@@ -2136,6 +2140,8 @@ void SwFrm::AppendDrawObj( SwAnchoredObject& _rNewObj )
        if( pLayout && pLayout->IsAnyShellAccessible() )
        pSh->Imp()->AddAccessibleObj( _rNewObj.GetDrawObj() );
    }

    assert(!mpDrawObjs || mpDrawObjs->is_sorted());
}

void SwFrm::RemoveDrawObj( SwAnchoredObject& _rToRemoveObj )
@@ -2159,6 +2165,8 @@ void SwFrm::RemoveDrawObj( SwAnchoredObject& _rToRemoveObj )
        DELETEZ( mpDrawObjs );

    _rToRemoveObj.ChgAnchorFrm( 0 );

    assert(!mpDrawObjs || mpDrawObjs->is_sorted());
}

void SwFrm::InvalidateObjs( const bool _bInvaPosOnly,
diff --git a/sw/source/core/layout/sortedobjs.cxx b/sw/source/core/layout/sortedobjs.cxx
index 0fef218..5893a48 100644
--- a/sw/source/core/layout/sortedobjs.cxx
+++ b/sw/source/core/layout/sortedobjs.cxx
@@ -60,6 +60,18 @@ SwAnchoredObject* SwSortedObjs::operator[]( size_t _nIndex ) const
    return pAnchoredObj;
}

namespace
{
    int GetAnchorWeight(RndStdIds eAnchor)
    {
        if (eAnchor == FLY_AT_CHAR)
            return 0;
        if (eAnchor == FLY_AS_CHAR)
            return 1;
        return 2;
    }
}

struct ObjAnchorOrder
{
    bool operator()( const SwAnchoredObject* _pListedAnchoredObj,
@@ -122,24 +134,23 @@ struct ObjAnchorOrder
        // --> OD 2006-11-29 #???# - objects have to be ordered by anchor node position
        // Thus, compare content anchor node positions and anchor type,
        // if not anchored at-paragraph
        if ((pAnchorListed->GetAnchorId() != FLY_AT_PARA) &&
            (pAnchorNew   ->GetAnchorId() != FLY_AT_PARA) &&
             pCntntAnchorListed && pCntntAnchorNew )
        if (pCntntAnchorListed && pCntntAnchorNew)
        {
            if ( pCntntAnchorListed->nContent != pCntntAnchorNew->nContent )
            sal_Int32 nListedIndex = pAnchorListed->GetAnchorId() != FLY_AT_PARA ?
                pCntntAnchorListed->nContent.GetIndex() : 0;
            sal_Int32 nNewIndex = pAnchorNew->GetAnchorId() != FLY_AT_PARA ?
                pCntntAnchorNew->nContent.GetIndex() : 0;
            if (nListedIndex != nNewIndex)
            {
                return pCntntAnchorListed->nContent < pCntntAnchorNew->nContent;
                return nListedIndex < nNewIndex;
            }
            else if ((pAnchorListed->GetAnchorId() == FLY_AT_CHAR) &&
                     (pAnchorNew   ->GetAnchorId() == FLY_AS_CHAR))
            {
                return true;
            }
            else if ((pAnchorListed->GetAnchorId() == FLY_AS_CHAR) &&
                     (pAnchorNew   ->GetAnchorId() == FLY_AT_CHAR))
            {
                return false;
            }
        }

        int nAnchorListedWeight = GetAnchorWeight(pAnchorListed->GetAnchorId());
        int nAnchorNewWeight = GetAnchorWeight(pAnchorNew->GetAnchorId());
        if (nAnchorListedWeight != nAnchorNewWeight)
        {
            return nAnchorListedWeight < nAnchorNewWeight;
        }

        // objects anchored at the same content and at the same content anchor
@@ -193,6 +204,11 @@ struct ObjAnchorOrder
    }
};

bool SwSortedObjs::is_sorted() const
{
    return std::is_sorted(maSortedObjLst.begin(), maSortedObjLst.end(), ObjAnchorOrder());
}

bool SwSortedObjs::Insert( SwAnchoredObject& _rAnchoredObj )
{
    // #i51941#
@@ -264,6 +280,11 @@ bool SwSortedObjs::Update( SwAnchoredObject& _rAnchoredObj )
    return Contains( _rAnchoredObj );
}

void SwSortedObjs::UpdateAll()
{
    std::stable_sort(maSortedObjLst.begin(), maSortedObjLst.end(), ObjAnchorOrder());
}

size_t SwSortedObjs::ListPosOf( const SwAnchoredObject& _rAnchoredObj ) const
{
    std::vector< SwAnchoredObject* >::const_iterator aIter =
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index 18da646..9b1b4a2 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -82,6 +82,7 @@
#include <SwNodeNum.hxx>
#include <svl/intitem.hxx>
#include <list.hxx>
#include <sortedobjs.hxx>
#include <switerator.hxx>
#include <attrhint.hxx>
#include <boost/scoped_ptr.hpp>
@@ -1178,6 +1179,13 @@ void SwTxtNode::Update(
    {
        getIDocumentMarkAccess()->assureSortedMarkContainers();
    }

    //Any drawing objects anchored into this text node may be sorted by their
    //anchor position which may have changed here, so resort them
    SwCntntFrm* pCntntFrm = getLayoutFrm(GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout());
    SwSortedObjs* pSortedObjs = pCntntFrm ? pCntntFrm->GetDrawObjs() : NULL;
    if (pSortedObjs)
        pSortedObjs->UpdateAll();
}

void SwTxtNode::_ChgTxtCollUpdateNum( const SwTxtFmtColl *pOldColl,