/*************************************************************************
 *
 *  $RCSfile: svdoattr.cxx,v $
 *
 *  $Revision: 1.33 $
 *
 *  last change: $Author: cl $ $Date: 2001-11-22 13:55:22 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "svdoattr.hxx"
#include "xpool.hxx"
#include "svditext.hxx"
#include "svdtouch.hxx"
#include "svdio.hxx"
#include "svdmodel.hxx"
#include "svdxout.hxx"
#include "svdpage.hxx"
#include "svdattr.hxx"
#include "svdattrx.hxx"
#include "svdpool.hxx"
#include "svdotext.hxx"
#include "svdocapt.hxx"
#include "svdograf.hxx"
#include "svdoole2.hxx"
#include "svdorect.hxx"
#include "svdocirc.hxx"
#include "svdomeas.hxx"

#ifndef _SFXSMPLHINT_HXX //autogen
#include <svtools/smplhint.hxx>
#endif

#ifndef _SFXITEMITER_HXX //autogen
#include <svtools/itemiter.hxx>
#endif

#ifndef _XENUM_HXX //autogen
#include "xenum.hxx"
#endif

#ifndef _SVX_XLINEIT0_HXX //autogen
#include "xlineit0.hxx"
#endif

#ifndef _SVX_XLNSTWIT_HXX //autogen
#include "xlnstwit.hxx"
#endif

#ifndef _SVX_XLNEDWIT_HXX //autogen
#include "xlnedwit.hxx"
#endif

#ifndef SVX_XFILLIT0_HXX //autogen
#include "xfillit0.hxx"
#endif

#ifndef _SVX_XFLBMTIT_HXX //autogen
#include "xflbmtit.hxx"
#endif

#ifndef _SVX_TEXTIT0_HXX //autogen
#include "xtextit0.hxx"
#endif

#ifndef _SVX_XFLBSTIT_HXX //autogen
#include "xflbstit.hxx"
#endif

#ifndef _SVX_XFLBTOXY_HXX //autogen
#include "xflbtoxy.hxx"
#endif

#ifndef _SVX_XFTSHIT_HXX //autogen
#include "xftshit.hxx"
#endif

#ifndef _EEITEMID_HXX
#include <eeitemid.hxx>
#endif

#ifndef _SVX_COLRITEM_HXX //autogen
#include "colritem.hxx"
#endif

#ifndef _SVX_FONTITEM_HXX //autogen
#include "fontitem.hxx"
#endif

#ifndef _SVX_FHGTITEM_HXX //autogen
#include "fhgtitem.hxx"
#endif

//#include <charscaleitem.hxx>

#ifndef _SVX_XLNSTCIT_HXX //autogen
#include <xlnstcit.hxx>
#endif

#ifndef _SVX_XLNWTIT_HXX //autogen
#include <xlnwtit.hxx>
#endif

#ifndef _SFXSTYLE_HXX //autogen
#include <svtools/style.hxx>
#endif

#ifndef _SFXSTYLE_HXX //autogen
#include <svtools/style.hxx>
#endif

#ifndef _SFX_WHITER_HXX //autogen
#include <svtools/whiter.hxx>
#endif

#ifndef _SVX_XLNCLIT_HXX //autogen
#include <xlnclit.hxx>
#endif

#ifndef _SVX_XFLCLIT_HXX //autogen
#include <xflclit.hxx>
#endif

#ifndef _SVX_XLNTRIT_HXX //autogen
#include <xlntrit.hxx>
#endif

#ifndef _SVX_XFLTRIT_HXX //autogen
#include <xfltrit.hxx>
#endif

#ifndef _SVX_XFLHTIT_HXX //autogen
#include <xflhtit.hxx>
#endif

#ifndef _SVX_XLNEDIT_HXX //autogen
#include <xlnedit.hxx>
#endif

#ifndef _SVX_XLNEDCIT_HXX //autogen
#include <xlnedcit.hxx>
#endif

#ifndef _SVX_XLNSTIT_HXX //autogen
#include <xlnstit.hxx>
#endif

#ifndef _SVX_ADJITEM_HXX
#include <adjitem.hxx>
#endif

#ifndef _SVX_XFLBCKIT_HXX
#include "xflbckit.hxx"
#endif

#ifndef _SVX_XBTMPIT_HXX
#include "xbtmpit.hxx"
#endif

#ifndef _XTABLE_HXX
#include "xtable.hxx"
#endif

#ifndef _SVX_XLNDSIT_HXX
#include "xlndsit.hxx"
#endif

#ifndef _SVX_XFLGRIT_HXX
#include "xflgrit.hxx"
#endif

#ifndef _SVX_XFLFTRIT_HXX
#include "xflftrit.hxx"
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////

TYPEINIT1(SdrAttrObj,SdrObject);

SdrAttrObj::SdrAttrObj()
:   mpStyleSheet(NULL),
    mpObjectItemSet(NULL)
{
}

SdrAttrObj::~SdrAttrObj()
{
    ImpDeleteItemSet();
}

void SdrAttrObj::ImpDeleteItemSet()
{
    if(mpObjectItemSet)
    {
        if(GetStyleSheet())
            RemoveStyleSheet();

        delete mpObjectItemSet;
        mpObjectItemSet = 0L;
    }
}

void SdrAttrObj::ImpForceItemSet()
{
    if(!mpObjectItemSet)
    {
        SfxItemPool* pPool = GetItemPool();
        mpObjectItemSet = CreateNewItemSet(*pPool);
        ForceDefaultAttr();
    }
}

const Rectangle& SdrAttrObj::GetSnapRect() const
{
    if(bSnapRectDirty)
    {
        ((SdrAttrObj*)this)->RecalcSnapRect();
        ((SdrAttrObj*)this)->bSnapRectDirty = FALSE;
    }
    return maSnapRect;
}

void SdrAttrObj::operator=(const SdrObject& rObj)
{
    // call parent
    SdrObject::operator=(rObj);

    SdrAttrObj* pAO = PTR_CAST(SdrAttrObj, (SdrObject*)&rObj);
    if(pAO)
    {
        ImpDeleteItemSet();

        if(pAO->mpObjectItemSet)
            mpObjectItemSet = pAO->mpObjectItemSet->Clone(TRUE);

        if(pAO->GetStyleSheet())
            AddStyleSheet(pAO->GetStyleSheet(), TRUE);
    }
}

void SdrAttrObj::ReadData(const SdrObjIOHeader& rHead, SvStream& rIn)
{
    if(rIn.GetError())
        return;

    // call parent
    SdrObject::ReadData(rHead, rIn);

    SdrDownCompat aCompat(rIn, STREAM_READ);
#ifdef DBG_UTIL
    aCompat.SetID("SdrAttrObj");
#endif
    SfxItemPool* pPool = GetItemPool();

    if(pPool)
    {
        sal_uInt16 nSetID;

        // #89025# if mpObjectItemSet is set and contains items, it is because of ForceDefaultAttr()
        // and the items need to be deleted.
        if(mpObjectItemSet && mpObjectItemSet->Count())
            mpObjectItemSet->ClearItem(0);

        // Do this initialization AFTER the above fix
        SfxItemSet aNewSet(GetItemSet());

        if(rHead.GetVersion() < 11)
            { sal_uInt16 nWhichDum; rIn >> nWhichDum; }
        nSetID = XATTRSET_LINE;
        const XLineAttrSetItem* pLineAttr = (const XLineAttrSetItem*)pPool->LoadSurrogate(rIn, nSetID, 0);
        if(pLineAttr)
            aNewSet.Put(pLineAttr->GetItemSet());

        if(rHead.GetVersion() < 11)
            { sal_uInt16 nWhichDum; rIn >> nWhichDum; }
        nSetID = XATTRSET_FILL;
        const XFillAttrSetItem* pFillAttr = (const XFillAttrSetItem*)pPool->LoadSurrogate(rIn, nSetID, 0);
        if(pFillAttr)
            aNewSet.Put(pFillAttr->GetItemSet());

        if(rHead.GetVersion() < 11)
            { sal_uInt16 nWhichDum; rIn >> nWhichDum; }
        nSetID = XATTRSET_TEXT;
        const XTextAttrSetItem* pTextAttr = (const XTextAttrSetItem*)pPool->LoadSurrogate(rIn, nSetID, 0);
        if(pTextAttr)
            aNewSet.Put(pTextAttr->GetItemSet());

        if(rHead.GetVersion() < 11)
            { sal_uInt16 nWhichDum; rIn >> nWhichDum; }
        nSetID = SDRATTRSET_SHADOW;
        const SdrShadowSetItem* pShadAttr = (const SdrShadowSetItem*)pPool->LoadSurrogate(rIn, nSetID, 0);
        if(pShadAttr)
            aNewSet.Put(pShadAttr->GetItemSet());

        if(rHead.GetVersion() >= 5)
        {
            if(rHead.GetVersion() < 11)
                { sal_uInt16 nWhichDum; rIn >> nWhichDum; }
            nSetID = SDRATTRSET_OUTLINER;
            const SdrOutlinerSetItem* pOutlAttr = (const SdrOutlinerSetItem*)pPool->LoadSurrogate(rIn, nSetID, 0);
            if(pOutlAttr)
                aNewSet.Put(pOutlAttr->GetItemSet());
        }

        if(rHead.GetVersion() >= 6)
        {
            if(rHead.GetVersion() < 11)
                { sal_uInt16 nWhichDum; rIn >> nWhichDum; }
            nSetID = SDRATTRSET_MISC;
            const SdrMiscSetItem* pMiscAttr = (const SdrMiscSetItem*)pPool->LoadSurrogate(rIn, nSetID, 0);
            if(pMiscAttr)
                aNewSet.Put(pMiscAttr->GetItemSet());
        }

        SetItemSet(aNewSet);
    }
    else
    {
        // an den Surrogaten und ggf. auch Whiches vorbeiseeken
        // ganz zu anfang waren es 4 SetItems
        sal_uInt16 nAnz(4);

        if(rHead.GetVersion() >= 5)
            nAnz++;

        if(rHead.GetVersion() >= 6)
            nAnz++;

        nAnz *= sizeof(sal_uInt16);

        if(rHead.GetVersion() < 11)
            nAnz *= 2;

        rIn.SeekRel(nAnz);
    }

    // TextToContour: altes Format(Flag) in neues Format(Item) wandeln
    if(rHead.GetVersion() <= 4 && pPool)
    {
        SetItem(XFormTextStyleItem(XFT_NONE));
    }

    // Fuer die StyleSheetgeschichte gehoert eigentlich auch noch eine
    // Versionsabfrage hierher.
    // Name und Familie des StyleSheet einlesen, in Pointer auf StyleSheet
    // umwandeln lassen (SB)
    XubString aStyleSheetName;
    SfxStyleFamily eFamily;
    sal_uInt16 nRead;

    // UNICODE: rIn>>aStyleSheetName;
    rIn.ReadByteString(aStyleSheetName);

    if(aStyleSheetName.Len())
    {
        rIn >> nRead;
        eFamily = (SfxStyleFamily)(int)nRead;

        // ab Version 1 wird der CharacterSet gelesen, ab V11 nicht mehr
        if(rHead.GetVersion() > 0 && rHead.GetVersion() < 11)
        {
            sal_Int16 nCharSet;
            rIn >> nCharSet;
            //aStyleSheetName.Convert((CharSet)nCharSet);
            // nicht mehr noetig, da ab Vers 11 der CharSet bereits am
            // Stream gesetzt wird.
        }

        DBG_ASSERT(pModel, "SdrAttrObj::ReadData(): pModel=NULL, StyleSheet kann nicht gesetzt werden!");
        if(pModel)
        {
            SfxStyleSheetBasePool *pPool = pModel->GetStyleSheetPool();
            if(pPool)
            {
                SfxStyleSheet *pTmpStyleSheet = (SfxStyleSheet*)pPool->Find(aStyleSheetName, eFamily);
                DBG_ASSERT(pTmpStyleSheet, "SdrAttrObj::ReadData(): StyleSheet nicht gefunden");

                if(pTmpStyleSheet)
                    AddStyleSheet(pTmpStyleSheet, TRUE);
            }
        }
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// pre- and postprocessing for objects for saving

void SdrAttrObj::PreSave()
{
    // call parent
    SdrObject::PreSave();

    // prepare SetItems for storage
    const SfxItemSet& rSet = GetUnmergedItemSet();
    const SfxItemSet* pParent = GetStyleSheet() ? &GetStyleSheet()->GetItemSet() : 0L;

    XLineAttrSetItem aLineAttr(rSet.GetPool());
    aLineAttr.GetItemSet().Put(rSet);
    aLineAttr.GetItemSet().SetParent(pParent);
    mpObjectItemSet->Put(aLineAttr);

    XFillAttrSetItem aFillAttr(rSet.GetPool());
    aFillAttr.GetItemSet().Put(rSet);
    aFillAttr.GetItemSet().SetParent(pParent);
    mpObjectItemSet->Put(aFillAttr);

    XTextAttrSetItem aTextAttr(rSet.GetPool());
    aTextAttr.GetItemSet().Put(rSet);
    aTextAttr.GetItemSet().SetParent(pParent);
    mpObjectItemSet->Put(aTextAttr);

    SdrShadowSetItem aShadAttr(rSet.GetPool());
    aShadAttr.GetItemSet().Put(rSet);
    aShadAttr.GetItemSet().SetParent(pParent);
    mpObjectItemSet->Put(aShadAttr);

    SdrOutlinerSetItem aOutlAttr(rSet.GetPool());
    aOutlAttr.GetItemSet().Put(rSet);
    aOutlAttr.GetItemSet().SetParent(pParent);
    mpObjectItemSet->Put(aOutlAttr);

    SdrMiscSetItem aMiscAttr(rSet.GetPool());
    aMiscAttr.GetItemSet().Put(rSet);
    aMiscAttr.GetItemSet().SetParent(pParent);
    mpObjectItemSet->Put(aMiscAttr);
}

void SdrAttrObj::PostSave()
{
    // call parent
    SdrObject::PostSave();

    // remove SetItems from local itemset
    ((SdrAttrObj*)this)->ImpForceItemSet();
    mpObjectItemSet->ClearItem(XATTRSET_LINE);
    mpObjectItemSet->ClearItem(XATTRSET_FILL);
    mpObjectItemSet->ClearItem(XATTRSET_TEXT);
    mpObjectItemSet->ClearItem(SDRATTRSET_SHADOW);
    mpObjectItemSet->ClearItem(SDRATTRSET_OUTLINER);
    mpObjectItemSet->ClearItem(SDRATTRSET_MISC);
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void SdrAttrObj::WriteData(SvStream& rOut) const
{
    // call parent
    SdrObject::WriteData(rOut);

    // Fuer Abwaertskompatibilitaet (Lesen neuer Daten mit altem Code)
    SdrDownCompat aCompat(rOut, STREAM_WRITE);
#ifdef DBG_UTIL
    aCompat.SetID("SdrAttrObj");
#endif
    SfxItemPool* pPool = GetItemPool();

    if(pPool)
    {
        const SfxItemSet& rSet = GetUnmergedItemSet();

        pPool->StoreSurrogate(rOut, &rSet.Get(XATTRSET_LINE));
        pPool->StoreSurrogate(rOut, &rSet.Get(XATTRSET_FILL));
        pPool->StoreSurrogate(rOut, &rSet.Get(XATTRSET_TEXT));
        pPool->StoreSurrogate(rOut, &rSet.Get(SDRATTRSET_SHADOW));
        pPool->StoreSurrogate(rOut, &rSet.Get(SDRATTRSET_OUTLINER));
        pPool->StoreSurrogate(rOut, &rSet.Get(SDRATTRSET_MISC));
    }
    else
    {
        rOut << sal_uInt16(SFX_ITEMS_NULL);
        rOut << sal_uInt16(SFX_ITEMS_NULL);
        rOut << sal_uInt16(SFX_ITEMS_NULL);
        rOut << sal_uInt16(SFX_ITEMS_NULL);
        rOut << sal_uInt16(SFX_ITEMS_NULL);
        rOut << sal_uInt16(SFX_ITEMS_NULL);
    }

    // StyleSheet-Pointer als Name, Familie abspeichern
    // wenn kein StyleSheet vorhanden: leeren String speichern
    if(GetStyleSheet())
    {
        // UNICODE: rOut << pStyleSheet->GetName();
        rOut.WriteByteString(GetStyleSheet()->GetName());
        rOut << (sal_uInt16)(int)(GetStyleSheet()->GetFamily());
    }
    else
    {
        // UNICODE: rOut << String();
        rOut.WriteByteString(String());
    }
}

static void ImpScaleItemSet(SfxItemSet& rSet, const Fraction& rScale)
{
    sal_Int32 nMul(rScale.GetNumerator());
    sal_Int32 nDiv(rScale.GetDenominator());

    if(!rScale.IsValid() || !nDiv)
        return;

    SfxWhichIter aIter(rSet);
    sal_uInt16 nWhich(aIter.FirstWhich());
    const SfxPoolItem *pItem = NULL;

    while(nWhich)
    {
        if(SFX_ITEM_SET == rSet.GetItemState(nWhich, FALSE, &pItem))
        {
            if(pItem->HasMetrics())
            {
                SfxPoolItem* pNewItem = pItem->Clone();
                pNewItem->ScaleMetrics(nMul, nDiv);
                rSet.Put(*pNewItem);
            }
        }
        nWhich = aIter.NextWhich();
    }
}

void SdrAttrObj::SetModel(SdrModel* pNewModel)
{
    SdrModel* pOldModel = pModel;

    // test for correct pool in ItemSet; move to new pool if necessary
    if(pNewModel && mpObjectItemSet && mpObjectItemSet->GetPool() != &pNewModel->GetItemPool())
        MigrateItemPool(mpObjectItemSet->GetPool(), &pNewModel->GetItemPool());

    // call parent
    SdrObject::SetModel(pNewModel);

    if(pOldModel != pNewModel && pNewModel && !pNewModel->IsLoading())
    {

        // fuer ein bereits "lebendes" Model die Attribute von einem Pool in den anderen schieben
        if(pOldModel)
        {
            // Checken, ob sich die ScaleUnit geaendert hat.
            // Denn dann muessen naemlich alle MetrikItems umgerechnet werden.
            MapUnit aOldUnit(pOldModel->GetScaleUnit());
            MapUnit aNewUnit(pNewModel->GetScaleUnit());
            BOOL bScaleUnitChanged(aNewUnit != aOldUnit);
            Fraction aMetricFactor;

            if(bScaleUnitChanged)
            {
                aMetricFactor = GetMapFactor(aOldUnit, aNewUnit).X();

                if(mpObjectItemSet)
                {
                    // #75371# To have a notify on scaling, do it on a copy of the
                    // local ItemSet and set this one then
                    SfxItemSet aItemSet(*mpObjectItemSet);
                    ImpScaleItemSet(aItemSet, aMetricFactor);
                    SetItemSet(aItemSet);
                }
            }

            // Und nun alle Items auf die das Obj verweisst aus
            // dem alten Pools raus und in den neuen rein.
            SfxStyleSheet* pOldStyleSheet = GetStyleSheet();

            // ***** StyleSheets Anfang *****
            // ggfs. StyleSheet und dessen Parents kopieren
            // Follows werden nicht beruecksichtigt (ganz wie im Writer)
            if(pOldStyleSheet)
            {
                SfxStyleSheetBase* pSheet = pOldStyleSheet;
                SfxStyleSheetBasePool* pOldPool = pOldModel->GetStyleSheetPool();
                SfxStyleSheetBasePool* pNewPool = pModel->GetStyleSheetPool();
                DBG_ASSERT(pOldPool, "SdrAttrObj::SetModel(): Objekt hat StyleSheet aber keinen StyleSheetPool am SdrModel");

                if(pOldPool && pNewPool)
                {
                    // Liste der zu kopierenden Vorlagen
                    List aList;
                    SfxStyleSheetBase* pAnchor = NULL;

                    while(pSheet)
                    {
                        pAnchor = pNewPool->Find(pSheet->GetName(), pSheet->GetFamily());

                        if(!pAnchor)
                        {
                            aList.Insert(pSheet, LIST_APPEND);
                            pSheet = pOldPool->Find(pSheet->GetParent(), pSheet->GetFamily());
                        }
                        else
                        {
                            // die gesuchte Vorlage gibt's schon
                            pSheet = NULL;
                        }
                    }

                    // kopieren und Parents der Kopien setzen
                    pSheet = (SfxStyleSheetBase*)aList.First();
                    SfxStyleSheetBase* pNewSheet = NULL;
                    SfxStyleSheetBase* pLastSheet = NULL;
                    SfxStyleSheetBase* pForThisObject = NULL;

                    while(pSheet)
                    {
                        pNewSheet = &pNewPool->Make(pSheet->GetName(), pSheet->GetFamily(), pSheet->GetMask());
                        pNewSheet->GetItemSet().Put(pSheet->GetItemSet(), FALSE);

                        if(bScaleUnitChanged)
                            ImpScaleItemSet(pNewSheet->GetItemSet(), aMetricFactor);

                        if(pLastSheet)
                            pLastSheet->SetParent(pNewSheet->GetName());

                        if(!pForThisObject)
                            pForThisObject = pNewSheet;

                        pLastSheet = pNewSheet;
                        pSheet = (SfxStyleSheetBase*)aList.Next();
                    }

                    // Veknuepfung mit der im Zielpool gefundenen Vorlage
                    if(pAnchor && pLastSheet)
                        pLastSheet->SetParent(pAnchor->GetName());

                    // falls die Liste leer war (alle Vorlagen schon im Zielpool
                    // vorhanden) ist pForThisObject noch nicht gesetzt
                    if(!pForThisObject && pAnchor)
                        pForThisObject = pAnchor;

                    // am alten StyleSheet ab- und am neuen anmelden
                    if(GetStyleSheet() != pForThisObject)
                    {
                        RemoveStyleSheet();
                        AddStyleSheet((SfxStyleSheet*)pForThisObject, TRUE);
                    }
                }
                else
                {
                    // Aha, im neuen Model gibt's also kein StyleSheetPool
                    // also setzte ich "einfach" alle Attribute des alten StyleSheets hart
                    List aList;
                    const SfxItemSet* pItemSet = &pOldStyleSheet->GetItemSet();

                    while(pItemSet)
                    {
                        aList.Insert((void*)pItemSet, CONTAINER_APPEND);
                        pItemSet = pItemSet->GetParent();
                    }

                    SfxItemSet* pNewSet = CreateNewItemSet(pNewModel->GetItemPool());
                    pItemSet = (SfxItemSet*)aList.Last();

                    while(pItemSet)
                    {
                        pNewSet->Put(*pItemSet);
                        pItemSet = (SfxItemSet*)aList.Prev();
                    }

                    // Attribute, die schon vorher hart gesetzt
                    // waren muessen aber erhalten bleiben:
                    if(mpObjectItemSet)
                    {
                        SfxWhichIter aIter(*mpObjectItemSet);
                        sal_uInt16 nWhich = aIter.FirstWhich();

                        while(nWhich)
                        {
                            if(mpObjectItemSet->GetItemState(nWhich, FALSE) == SFX_ITEM_SET)
                                pNewSet->Put(mpObjectItemSet->Get(nWhich));

                            nWhich = aIter.NextWhich();
                        }
                    }

                    if(bScaleUnitChanged)
                        ImpScaleItemSet(*pNewSet, aMetricFactor);

                    ImpDeleteItemSet();
                    mpObjectItemSet = pNewSet;
                }
            }
            // ***** StyleSheets Ende *****
        }

        // Jedes Objekt bekommt initial den DefaultStyleSheet
        // des Model, falls noch kein StyleSheet gesetzt.
        if(mpObjectItemSet && !GetStyleSheet() && pModel && !pModel->IsLoading())
            NbcSetStyleSheet(pModel->GetDefaultStyleSheet(), TRUE);

/* this code was removed because NbcSetStyleSheet called with TRUE does not
   alter the hard attributes. So they don't need to be restored, a useless
   process that cost us up to 20% for xml import. Also there is a memory
   leek with aSet.Put( *pItem->Clone() );
        {
            SfxStyleSheet* pDefSS = pModel->GetDefaultStyleSheet();

            if(pDefSS)
            {
                SfxItemPool* pPool = GetItemPool();
                if ( pPool )
                {
                    // Take hard attributes
                    SfxItemSet aSet(*pPool,
                        SDRATTR_START,SDRATTR_NOTPERSIST_FIRST-1,
                        SDRATTR_NOTPERSIST_LAST+1, SDRATTR_END,
                        EE_ITEMS_START,EE_ITEMS_END,
                        0,0);

                    const SfxItemSet& rItemSet = GetItemSet();

                    SfxWhichIter aIter( rItemSet );
                    sal_uInt16 nWhich( aIter.FirstWhich() );
                    const SfxPoolItem* pItem = NULL;

                    while( nWhich )
                    {
                        if( SFX_ITEM_SET == rItemSet.GetItemState( nWhich, FALSE, &pItem ) )
                            aSet.Put( *pItem->Clone() );
                        nWhich = aIter.NextWhich();
                    }
                    // Set the StyleSheet
                    NbcSetStyleSheet(pDefSS, TRUE);

                    // Set the hard attributes
                    SetItemSet( aSet );
                  }
                else
                    NbcSetStyleSheet(pDefSS, TRUE);
            }
        }
*/
    }
}

void SdrAttrObj::ForceDefaultAttr()
{
    SdrTextObj* pText = PTR_CAST(SdrTextObj, this);
    BOOL bTextFrame(pText && pText->IsTextFrame());

    ImpForceItemSet();
    if(bTextFrame)
    {
        SdrCaptionObj* pCapt = PTR_CAST(SdrCaptionObj, this);
        BOOL bCaption(pCapt != 0L);

        if(!bCaption)
             mpObjectItemSet->Put(XLineStyleItem(XLINE_NONE));

        mpObjectItemSet->Put(XFillColorItem(String(), Color(COL_WHITE)));
        mpObjectItemSet->Put(XFillStyleItem(XFILL_NONE));
    }
    else
    {
        mpObjectItemSet->Put(SvxAdjustItem(SVX_ADJUST_CENTER));
        mpObjectItemSet->Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_CENTER));
        mpObjectItemSet->Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER));
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// ItemSet access

const SfxItemSet& SdrAttrObj::GetItemSet() const
{
    ((SdrAttrObj*)this)->ImpForceItemSet();
    return *mpObjectItemSet;
}

SfxItemSet* SdrAttrObj::CreateNewItemSet(SfxItemPool& rPool)
{
    // include ALL items, 2D and 3D
    return new SfxItemSet(rPool,
        // ranges from SdrAttrObj
        SDRATTR_START, SDRATTRSET_SHADOW,
        SDRATTRSET_OUTLINER, SDRATTRSET_MISC,
        SDRATTR_TEXTDIRECTION_LEFT_TO_RIGHT, SDRATTR_TEXTDIRECTION_TOP_TO_BOTTOM,

        // outliner and end
        EE_ITEMS_START, EE_ITEMS_END,
        0, 0);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// syntactical sugar for ItemSet accesses

const SfxItemSet& SdrAttrObj::GetUnmergedItemSet() const
{
    return SdrAttrObj::GetItemSet();
}

void SdrAttrObj::ItemChange(const sal_uInt16 nWhich, const SfxPoolItem* pNewItem)
{
    if(pNewItem)
    {
#ifdef SVX_LIGHT
        // set item
        ((SdrAttrObj*)this)->ImpForceItemSet();
        mpObjectItemSet->Put(*pNewItem);
#else
        const SfxPoolItem* pItem = pNewItem;

        switch( nWhich )
        {
        case XATTR_FILLBITMAP:
            pItem = ((XFillBitmapItem*)pItem)->checkForUniqueItem( pModel );
            break;
        case XATTR_LINEDASH:
            pItem = ((XLineDashItem*)pItem)->checkForUniqueItem( pModel );
            break;
        case XATTR_LINESTART:
            pItem = ((XLineStartItem*)pItem)->checkForUniqueItem( pModel );
            break;
        case XATTR_LINEEND:
            pItem = ((XLineEndItem*)pItem)->checkForUniqueItem( pModel );
            break;
        case XATTR_FILLGRADIENT:
            pItem = ((XFillGradientItem*)pItem)->checkForUniqueItem( pModel );
            break;
        case XATTR_FILLFLOATTRANSPARENCE:
            // #85953# allow all kinds of XFillFloatTransparenceItem to be set
            pItem = ((XFillFloatTransparenceItem*)pItem)->checkForUniqueItem( pModel );
            break;
        case XATTR_FILLHATCH:
            pItem = ((XFillHatchItem*)pItem)->checkForUniqueItem( pModel );
            break;
        }

        // set item
        if( pItem )
        {
            ((SdrAttrObj*)this)->ImpForceItemSet();
            mpObjectItemSet->Put(*pItem);

            // delete item if it was a generated one
            if( pItem != pNewItem)
                delete (SfxPoolItem*)pItem;
        }
#endif
    }
    else
    {
        // clear item
        if(mpObjectItemSet)
        {
            mpObjectItemSet->ClearItem(nWhich);
        }
    }
}

void SdrAttrObj::ItemSetChanged(const SfxItemSet& rSet)
{
    // call parent
    SdrObject::ItemSetChanged(rSet);

    // own modifications
    bBoundRectDirty = TRUE;
    SetRectsDirty(TRUE);
    SetChanged();
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void __EXPORT SdrAttrObj::SFX_NOTIFY(SfxBroadcaster& rBC, const TypeId& rBCType,
    const SfxHint& rHint, const TypeId& rHintType)
{
    SfxSimpleHint *pSimple = PTR_CAST(SfxSimpleHint, &rHint);
    BOOL bDataChg(pSimple && SFX_HINT_DATACHANGED == pSimple->GetId());
    SfxStyleSheetHint *pStyleHint = PTR_CAST(SfxStyleSheetHint, &rHint);
    BOOL bDying(pStyleHint
                && pStyleHint->GetStyleSheet() == GetStyleSheet()
                && ( SFX_STYLESHEET_INDESTRUCTION == pStyleHint->GetHint() ||
                     SFX_STYLESHEET_ERASED == pStyleHint->GetHint() ));

    if(bDataChg || bDying)
    {
        Rectangle aBoundRect0;

        if(pUserCall)
            aBoundRect0 = GetBoundRect();

        SfxStyleSheet* pNewStSh = NULL;
        BOOL bBoundRectDirty0 = bBoundRectDirty;

        if(bDying)
        {
            // wenn es einen Parent gibt, wird jetzt der genommen
            if(pModel && HAS_BASE(SfxStyleSheet, GetStyleSheet()))
            {
                // Sonst ist pStyleSheet schon zu weit weggestorben
                pNewStSh = (SfxStyleSheet*)pModel->GetStyleSheetPool()->Find(
                    GetStyleSheet()->GetParent(), GetStyleSheet()->GetFamily());
            }

            // wenn es keinen Parent gibt, nehmen wir die Standardvorlage
            if(!pNewStSh && pModel)
                pNewStSh = pModel->GetDefaultStyleSheet();

            // alten StyleSheet vor SendRepaintBroadcast entfernen #42276#
            RemoveStyleSheet(); // setzt bBoundRectDirty=TRUE
        }

        if(!bBoundRectDirty0)
        {
            bBoundRectDirty = FALSE;  // fuer Broadcast mit dem alten Rect

            if(pPage && pPage->IsInserted())
                SendRepaintBroadcast(); // Erstmal mit dem alten Rect

            bBoundRectDirty = TRUE;
            SetRectsDirty(TRUE);    // Durch Vorlagenloeschung evtl. andere Linienbreite
        }

        if(pNewStSh && !bDying)
            AddStyleSheet(pNewStSh, TRUE);

        if(pPage && pPage->IsInserted())
            SendRepaintBroadcast();

        SendUserCall(SDRUSERCALL_CHGATTR, aBoundRect0);
    }
}

SfxStyleSheet* SdrAttrObj::GetStyleSheet() const
{
    return mpStyleSheet;
}

void SdrAttrObj::RemoveStyleSheet()
{
    // Typ checken, weil bei dying sich der Typ abbaut (bis zum Broadcaster runter)
    if(GetStyleSheet() && HAS_BASE(SfxStyleSheet, mpStyleSheet))
    {
        EndListening(*mpStyleSheet);
        EndListening(mpStyleSheet->GetPool());

        // das ItemSet der Vorlage ist jetzt nicht mehr Parent der
        // eigenen ItemSets
        if(mpObjectItemSet)
            mpObjectItemSet->SetParent(NULL);

        bBoundRectDirty = TRUE;
        SetRectsDirty(TRUE);
    }
    mpStyleSheet = NULL;
}

void SdrAttrObj::AddStyleSheet(SfxStyleSheet* pNewStyleSheet, FASTBOOL bDontRemoveHardAttr)
{
    // old StyleSheet is deleted
    DBG_ASSERT(!mpStyleSheet, "Old style sheet not deleted before setting new one (?)");

    if(pNewStyleSheet)
    {
        mpStyleSheet = pNewStyleSheet;

        // ItemSet is needed here, force it
        ImpForceItemSet();

        // als Listener anmelden
        StartListening(pNewStyleSheet->GetPool());
        StartListening(*pNewStyleSheet);

        // harte Attributierung dort loeschen, wo was in der Vorlage steht
        if(!bDontRemoveHardAttr)
        {
            const SfxItemSet& rStyle = pNewStyleSheet->GetItemSet();
            SfxWhichIter aIter(rStyle);
            sal_uInt16 nWhich = aIter.FirstWhich();

            while(nWhich)
            {
                if(SFX_ITEM_SET == rStyle.GetItemState(nWhich))
                    mpObjectItemSet->ClearItem(nWhich);
                nWhich = aIter.NextWhich();
            }
        }

        // set new stylesheet as parent
        mpObjectItemSet->SetParent(&pNewStyleSheet->GetItemSet());
    }
}

void SdrAttrObj::NbcSetStyleSheet(SfxStyleSheet* pNewStyleSheet, FASTBOOL bDontRemoveHardAttr)
{
    RemoveStyleSheet();
    AddStyleSheet(pNewStyleSheet, bDontRemoveHardAttr);
    bBoundRectDirty = TRUE;
    SetRectsDirty(TRUE);
}

void SdrAttrObj::SetStyleSheet(SfxStyleSheet* pNewStyleSheet, FASTBOOL bDontRemoveHardAttr)
{
    Rectangle aBoundRect0;

    if(pUserCall)
        aBoundRect0 = GetBoundRect();

    SendRepaintBroadcast();
    NbcSetStyleSheet(pNewStyleSheet, bDontRemoveHardAttr);
    SetChanged();
    SendRepaintBroadcast();
    SendUserCall(SDRUSERCALL_CHGATTR, aBoundRect0);
}

INT32 SdrAttrObj::ImpGetLineWdt() const
{
    const SfxItemSet& rSet = GetItemSet();
    XLineStyle eLine = ((XLineStyleItem&)(rSet.Get(XATTR_LINESTYLE))).GetValue();

    if(XLINE_NONE == eLine)
        return 0; // Garkeine Linie da.

    sal_Int32 nWdt = ((XLineWidthItem&)(rSet.Get(XATTR_LINEWIDTH))).GetValue();

    return nWdt;
}

INT32 SdrAttrObj::ImpGetLineEndAdd() const
{
    const SfxItemSet& rSet = GetItemSet();
    BOOL bStartSet(TRUE);
    BOOL bEndSet(TRUE);

    if(SFX_ITEM_DONTCARE != rSet.GetItemState(XATTR_LINESTART))
    {
        String aStr(((const XLineStartItem&)rSet.Get(XATTR_LINESTART)).GetName());
        if(!aStr.Len())
            bStartSet = FALSE;
    }

    if(rSet.GetItemState(XATTR_LINEEND) != SFX_ITEM_DONTCARE)
    {
        String aStr(((const XLineEndItem&)rSet.Get(XATTR_LINEEND)).GetName());
        if(!aStr.Len())
            bEndSet = FALSE;
    }

    BOOL bLineEndSet = bStartSet || bEndSet;
    XLineStyle eLine = ((XLineStyleItem&)(rSet.Get(XATTR_LINESTYLE))).GetValue();

    if(XLINE_NONE == eLine)
        return 0; // Garkeine Linie da.

    // Strichstaerke
    sal_Int32 nLineWdt = ((XLineWidthItem&)(rSet.Get(XATTR_LINEWIDTH))).GetValue();
    sal_Int32 nSttWdt = ((const XLineStartWidthItem&)(rSet.Get(XATTR_LINESTARTWIDTH))).GetValue();

    if(nSttWdt < 0)
        nSttWdt = -nLineWdt * nSttWdt / 100;

    if(!bLineEndSet)
        nSttWdt = 0;

    BOOL bSttCenter = ((const XLineStartCenterItem&)(rSet.Get(XATTR_LINESTARTCENTER))).GetValue();
    sal_Int32 nSttHgt = 0;

    if(bSttCenter)
    {
        // Linienende steht um die Haelfe ueber
        XPolygon aSttPoly(((const XLineStartItem&)(rSet.Get(XATTR_LINESTART))).GetValue());
        nSttHgt = XOutputDevice::InitLineStartEnd(aSttPoly, nSttWdt, bSttCenter);
        // InitLineStartEnd liefert bei bCenter=TRUE die halbe Hoehe
    }

    nSttWdt++;
    nSttWdt /= 2;

    // Lieber etwas mehr, dafuer keine Wurzel ziehen
    long nSttAdd = Max(nSttWdt, nSttHgt);
    nSttAdd *= 3;
    nSttAdd /= 2;

    long nEndWdt = ((const XLineEndWidthItem&)(rSet.Get(XATTR_LINEENDWIDTH))).GetValue();

    if(nEndWdt < 0)
        nEndWdt = -nLineWdt * nEndWdt / 100; // <0 = relativ

    if(!bLineEndSet)
        nEndWdt = 0;

    BOOL bEndCenter = ((const XLineEndCenterItem&)(rSet.Get(XATTR_LINEENDCENTER))).GetValue();
    sal_Int32 nEndHgt = 0;

    if(bEndCenter)
    {
        // Linienende steht um die Haelfe ueber
        XPolygon aEndPoly(((const XLineEndItem&)(rSet.Get(XATTR_LINEEND))).GetValue());
        nEndHgt = XOutputDevice::InitLineStartEnd(aEndPoly, nEndWdt, bEndCenter);
        // InitLineStartEnd liefert bei bCenter=TRUE die halbe Hoehe
    }

    nEndWdt++;
    nEndWdt /= 2;

    // Lieber etwas mehr, dafuer keine Wurzel ziehen
    sal_Int32 nEndAdd = Max(nEndWdt, nEndHgt);
    nEndAdd *= 3;
    nEndAdd /= 2;

    return Max(nSttAdd, nEndAdd);
}

//////////////////////////////////////////////////////////////////////////////

FASTBOOL SdrAttrObj::ImpLineEndHitTest(const Point& rEndPt, double nSin, double nCos, FASTBOOL bStart, const Point& rHit, USHORT nTol) const
{
    const SfxItemSet& rSet = GetItemSet();
    sal_Int32 nWdt = 0;
    BOOL bCenter = FALSE;
    XPolygon aXPoly;

    if(bStart)
    {
        nWdt = ((const XLineStartWidthItem&)(rSet.Get(XATTR_LINESTARTWIDTH))).GetValue();
        bCenter = ((const XLineStartCenterItem&)(rSet.Get(XATTR_LINESTARTCENTER))).GetValue();
        aXPoly = ((const XLineStartItem&)(rSet.Get(XATTR_LINESTART))).GetValue();
    }
    else
    {
        nWdt = ((const XLineEndWidthItem&)(rSet.Get(XATTR_LINEENDWIDTH))).GetValue();
        bCenter = ((const XLineEndCenterItem&)(rSet.Get(XATTR_LINEENDCENTER))).GetValue();
        aXPoly = ((const XLineEndItem&)(rSet.Get(XATTR_LINEEND))).GetValue();
    }

    if(nWdt < 0)
    {
        sal_Int32 nLineWdt = ((XLineWidthItem&)(rSet.Get(XATTR_LINEWIDTH))).GetValue(); // Strichstaerke
        nWdt = -nLineWdt * nWdt / 100; // <0 = relativ
    }

    // InitLineStartEnd liefert bei bCenter=TRUE die halbe Hoehe
    XOutputDevice::InitLineStartEnd(aXPoly, nWdt, bCenter);
    RotateXPoly(aXPoly, Point(), nSin, nCos);
    Point aHit(rHit);
    aHit -= rEndPt;
    Rectangle aHitRect(aHit.X() - nTol, aHit.Y() - nTol, aHit.X() + nTol, aHit.Y() + nTol);
    FASTBOOL bHit = IsRectTouchesPoly(XOutCreatePolygon(aXPoly, NULL), aHitRect);

    return bHit;
}

FASTBOOL SdrAttrObj::ImpGetShadowDist(sal_Int32& nXDist, sal_Int32& nYDist) const
{
    const SfxItemSet& rSet = GetItemSet();

    nXDist = 0L;
    nYDist = 0L;

    BOOL bShadOn = ((SdrShadowItem&)(rSet.Get(SDRATTR_SHADOW))).GetValue();
    if(bShadOn)
    {
        nXDist = ((SdrShadowXDistItem&)(rSet.Get(SDRATTR_SHADOWXDIST))).GetValue();
        nYDist = ((SdrShadowYDistItem&)(rSet.Get(SDRATTR_SHADOWYDIST))).GetValue();
        return TRUE;
    }

    return FALSE;
}

void SdrAttrObj::ImpAddShadowToBoundRect()
{
    sal_Int32 nXDist;
    sal_Int32 nYDist;

    if(ImpGetShadowDist(nXDist, nYDist))
    {
        if(nXDist > 0)
            aOutRect.Right() += nXDist;
        else
            aOutRect.Left() += nXDist;

        if(nYDist > 0)
            aOutRect.Bottom() += nYDist;
        else
            aOutRect.Top() += nYDist;
    }
}

FASTBOOL SdrAttrObj::ImpSetShadowAttributes(ExtOutputDevice& rXOut, FASTBOOL bNoFill) const
{
    const SfxItemSet& rSet = GetItemSet();
    BOOL bShadOn=((SdrShadowItem&)(rSet.Get(SDRATTR_SHADOW))).GetValue();

    if(bShadOn)
    {
// LineAttr for shadow no longer necessary, lines and line shadows are drawn in Paint()
// routines individually (grep for CreateLinePoly())
//
//          if (pLineAttr!=NULL) {
//              XLineAttrSetItem aL(*pLineAttr);
//              aL.GetItemSet().Put(XLineColorItem(String(),aShadCol));
//              aL.GetItemSet().Put(XLineTransparenceItem(nTransp));
//              rXOut.SetLineAttr(aL);
//          }
        if(!bNoFill)
        {
            const SdrShadowColorItem& rShadColItem = ((const SdrShadowColorItem&)(rSet.Get(SDRATTR_SHADOWCOLOR)));
            Color aShadCol(rShadColItem.GetValue());
            sal_uInt16 nTransp = ((const SdrShadowTransparenceItem&)(rSet.Get(SDRATTR_SHADOWTRANSPARENCE))).GetValue();
            XFillStyle eStyle = ((const XFillStyleItem&)(rSet.Get(XATTR_FILLSTYLE))).GetValue();
            BOOL bFillBackground = ((const XFillBackgroundItem&)(rSet.Get(XATTR_FILLBACKGROUND))).GetValue();
            SfxItemSet aSet(rSet);

            if(eStyle==XFILL_HATCH && !bFillBackground)
            {
                // #41666#
                XHatch aHatch = ((XFillHatchItem&)(rSet.Get(XATTR_FILLHATCH))).GetValue();
                aHatch.SetColor(aShadCol);
                aSet.Put(XFillHatchItem(String(), aHatch));
            }
            else
            {
                if(eStyle != XFILL_NONE && eStyle != XFILL_SOLID)
                {
                    // also fuer Gradient und Bitmap
                    aSet.Put(XFillStyleItem(XFILL_SOLID));
                }

                aSet.Put(XFillColorItem(String(),aShadCol));

                // #92183# set XFillTransparenceItem only when no FloatTransparence is used,
                // else the OutDev will use the wrong method
                if(nTransp)
                {
                    const XFillFloatTransparenceItem& rFillFloatTransparence =
                        (const XFillFloatTransparenceItem&)rSet.Get(XATTR_FILLFLOATTRANSPARENCE);
                    if(!rFillFloatTransparence.IsEnabled())
                        aSet.Put(XFillTransparenceItem(nTransp));
                }
            }

            rXOut.SetFillAttr(aSet);
        }
        return TRUE;
    }

    return FALSE;
}

// ItemPool fuer dieses Objekt wechseln
void SdrAttrObj::MigrateItemPool(SfxItemPool* pSrcPool, SfxItemPool* pDestPool)
{
    if(pSrcPool && pDestPool && (pSrcPool != pDestPool))
    {
        // call parent
        SdrObject::MigrateItemPool(pSrcPool, pDestPool);

        // eigene Reaktion
        if(pDestPool && pSrcPool && (pDestPool != pSrcPool))
        {
            if(mpObjectItemSet)
            {
                // migrate ItemSet to new pool. Scaling is NOT necessary
                // because this functionality is used by UNDO only. Thus
                // objects and ItemSets would be moved back to their original
                // pool before usage.
                SfxItemSet* pNewSet = mpObjectItemSet->Clone(TRUE, pDestPool);
                SfxStyleSheet* pStySheet = GetStyleSheet();

                if(GetStyleSheet())
                    pNewSet->SetParent(&GetStyleSheet()->GetItemSet());

                // set new itemset
                ImpDeleteItemSet();
                mpObjectItemSet = pNewSet;

                // set stylesheet (if used)
                if(pStySheet)
                    AddStyleSheet(pStySheet, TRUE);
            }
        }
    }
}

BOOL SdrAttrObj::HasFill() const
{
    return (!bClosedObj) ? FALSE
        : ((XFillStyleItem&)(GetItem(XATTR_FILLSTYLE))).GetValue()!=XFILL_NONE;
}

BOOL SdrAttrObj::HasLine() const
{
    return ((XLineStyleItem&)(GetItem(XATTR_LINESTYLE))).GetValue()!=XLINE_NONE;
}

// #94547# Have to re-activate more performant, but corrected version.
// This is necessary since SetItemSet() of the old implementation calls
// ItemSetChanged() which replaces in textobjects all text items which
// is wrong behaviour for BurnInStyleSheet.
void SdrAttrObj::BurnInStyleSheetAttributes( BOOL bPseudoSheetsOnly )
{
    if(GetStyleSheet() && HAS_BASE(SfxStyleSheet, mpStyleSheet))
    {
        // prepare copied, new itemset, but WITHOUT parent
        ImpForceItemSet();
        SfxItemSet* pDestItemSet = new SfxItemSet(*mpObjectItemSet);
        pDestItemSet->SetParent(0L);

        // pepare forgetting the current stylesheet like in RemoveStyleSheet()
        EndListening(*mpStyleSheet);
        EndListening(mpStyleSheet->GetPool());

        // get itemset of the stylesheet
        const SfxItemSet& rSet = mpStyleSheet->GetItemSet();

        // prepare the iter; use the mpObjectItemSet which may have less
        // WhichIDs than the style.
        SfxWhichIter aIter(*pDestItemSet);
        sal_uInt16 nWhich(aIter.FirstWhich());
        const SfxPoolItem *pItem = NULL;

        // set all attributes of the stylesheet at the new itemset
        while(nWhich)
        {
            if(SFX_ITEM_SET == rSet.GetItemState(nWhich, TRUE, &pItem))
                pDestItemSet->Put(*pItem);
            nWhich = aIter.NextWhich();
        }

        // prepare 2nd loop
        nWhich = aIter.FirstWhich();

        // now set all hard attributes of the current at the new itemset
        while(nWhich)
        {
            if(SFX_ITEM_SET == mpObjectItemSet->GetItemState(nWhich, FALSE, &pItem))
                pDestItemSet->Put(*pItem);
            nWhich = aIter.NextWhich();
        }

        // replace itemsets
        delete mpObjectItemSet;
        mpObjectItemSet = pDestItemSet;

        // set necessary changes like in RemoveStyleSheet()
        bBoundRectDirty = TRUE;
        SetRectsDirty(TRUE);
        mpStyleSheet = NULL;
    }
}

// #91695# back to corrected old version. Have to check new version again for later builds.
//void SdrAttrObj::BurnInStyleSheetAttributes( BOOL bPseudoSheetsOnly )
//{
//  SfxItemPool* pPool = GetItemPool();
//  if ( pPool && mpStyleSheet )
//  {
//      // Get StyleSheet attributes
//      SfxItemSet aSet(*pPool,
//          SDRATTR_START, SDRATTR_NOTPERSIST_FIRST-1,
//          SDRATTR_NOTPERSIST_LAST+1, SDRATTR_END,
//          EE_ITEMS_START,EE_ITEMS_END,
//          0,0);
//
//      SfxWhichIter aIter( mpStyleSheet->GetItemSet() );
//      sal_uInt16 nWhich( aIter.FirstWhich() );
//      const SfxPoolItem* pItem = NULL;
//
//      while( nWhich )
//      {
//          if( SFX_ITEM_SET == mpStyleSheet->GetItemSet().GetItemState(nWhich, TRUE, &pItem) )
//              aSet.Put( *pItem );
//
//          nWhich = aIter.NextWhich();
//      }
//
//      SfxWhichIter aHardAttrIter( GetItemSet() );
//      nWhich = aHardAttrIter.FirstWhich();
//
//      while( nWhich )
//      {
//          if( SFX_ITEM_SET == GetItemSet().GetItemState(nWhich, FALSE, &pItem) )
//              aSet.Put( *pItem );
//
//          nWhich = aHardAttrIter.NextWhich();
//      }
//
//      // Set StyleSheet attributes as hard attributes
//      SetItemSet( aSet );
//      }
//}

/*
void SdrAttrObj::BurnInStyleSheetAttributes( BOOL bPseudoSheetsOnly )
{
    // #89025# Added more performant implementation
    if(mpStyleSheet)
    {
        const SfxItemSet& rSet = mpStyleSheet->GetItemSet();
        SfxWhichIter aIter(rSet);
        sal_uInt16 nWhich(aIter.FirstWhich());
        const SfxPoolItem *pItem = NULL;

        ImpForceItemSet();
        const SfxItemSet* pParentSet = mpObjectItemSet->GetParent();
        if(pParentSet != 0L)
            mpObjectItemSet->SetParent(0L);

        while(nWhich)
        {
            if(SFX_ITEM_SET == rSet.GetItemState(nWhich, TRUE, &pItem))
                mpObjectItemSet->Put(*pItem);
            nWhich = aIter.NextWhich();
        }

        if(pParentSet != 0L)
            mpObjectItemSet->SetParent(pParentSet);
    }
}
*/