/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"

#include <svx/svdmodel.hxx>

#include <rtl/uuid.h>
#include <com/sun/star/lang/XComponent.hpp>
#include <osl/endian.h>
#include <rtl/logfile.hxx>
#include <math.h>
#include <tools/urlobj.hxx>
#include <unotools/ucbstreamhelper.hxx>

#include <tools/string.hxx>
#include <svl/whiter.hxx>
#include <svx/xit.hxx>
#include <svx/xbtmpit.hxx>
#include <svx/xlndsit.hxx>
#include <svx/xlnedit.hxx>
#include <svx/xflgrit.hxx>
#include <svx/xflftrit.hxx>
#include <svx/xflhtit.hxx>
#include <svx/xlnstit.hxx>

#include "svx/svditext.hxx"
#include <editeng/editeng.hxx>   // Fuer EditEngine::CreatePool()

#include <svx/xtable.hxx>

#include "svx/svditer.hxx"
#include <svx/svdtrans.hxx>
#include <svx/svdpage.hxx>
#include <svx/svdlayer.hxx>
#include <svx/svdundo.hxx>
#include <svx/svdpool.hxx>
#include <svx/svdobj.hxx>
#include <svx/svdotext.hxx>  // fuer ReformatAllTextObjects und CalcFieldValue
#include <svx/svdetc.hxx>
#include <svx/svdoutl.hxx>
#include <svx/svdoole2.hxx>
#include "svx/svdglob.hxx"  // Stringcache
#include "svx/svdstr.hrc"   // Objektname
#include "svdoutlinercache.hxx"

#include "svx/xflclit.hxx"
#include "svx/xflhtit.hxx"
#include "svx/xlnclit.hxx"

#include <svl/asiancfg.hxx>
#include "editeng/fontitem.hxx"
#include <editeng/colritem.hxx>
#include <editeng/fhgtitem.hxx>
#include <svl/style.hxx>
#include <tools/bigint.hxx>
#include <editeng/numitem.hxx>
#include <editeng/bulitem.hxx>
#include <editeng/outlobj.hxx>
#include "editeng/forbiddencharacterstable.hxx"
#include <svl/zforlist.hxx>
#include <comphelper/processfactory.hxx>

// #90477#
#include <tools/tenccvt.hxx>
#include <unotools/syslocale.hxx>

// #95114#
#include <vcl/svapp.hxx>
#include <svx/sdr/properties/properties.hxx>
#include <editeng/eeitem.hxx>
#include <svl/itemset.hxx>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;

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

struct SdrModelImpl
{
	SfxUndoManager*	mpUndoManager;
	SdrUndoFactory* mpUndoFactory;
	bool mbAllowShapePropertyChangeListener;
};

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

DBG_NAME(SdrModel)
TYPEINIT1(SdrModel,SfxBroadcaster);
void SdrModel::ImpCtor(SfxItemPool* pPool, ::comphelper::IEmbeddedHelper* _pEmbeddedHelper,
	bool bUseExtColorTable, bool bLoadRefCounts)
{
	mpImpl = new SdrModelImpl;
	mpImpl->mpUndoManager=0;
	mpImpl->mpUndoFactory=0;
	mpImpl->mbAllowShapePropertyChangeListener=false;
	mbInDestruction=false;
	aObjUnit=SdrEngineDefaults::GetMapFraction();
	eObjUnit=SdrEngineDefaults::GetMapUnit();
	eUIUnit=FUNIT_MM;
	aUIScale=Fraction(1,1);
	nUIUnitKomma=0;
	bUIOnlyKomma=sal_False;
	pLayerAdmin=NULL;
	pItemPool=pPool;
	bMyPool=sal_False;
	m_pEmbeddedHelper=_pEmbeddedHelper;
	pDrawOutliner=NULL;
	pHitTestOutliner=NULL;
	pRefOutDev=NULL;
	nProgressAkt=0;
	nProgressMax=0;
	nProgressOfs=0;
	pDefaultStyleSheet=NULL;
    mpDefaultStyleSheetForSdrGrafObjAndSdrOle2Obj = 0;
	pLinkManager=NULL;
	pUndoStack=NULL;
	pRedoStack=NULL;
	nMaxUndoCount=16;
	pAktUndoGroup=NULL;
	nUndoLevel=0;
	mbUndoEnabled=true;
	nProgressPercent=0;
	nLoadVersion=0;
	bExtColorTable=sal_False;
	mbChanged = sal_False;
	bInfoChanged=sal_False;
	bPagNumsDirty=sal_False;
	bMPgNumsDirty=sal_False;
	bPageNotValid=sal_False;
	bSavePortable=sal_False;
	bSaveCompressed=sal_False;
	bSaveNative=sal_False;
	bSwapGraphics=sal_False;
	nSwapGraphicsMode=SDR_SWAPGRAPHICSMODE_DEFAULT;
	bSaveOLEPreview=sal_False;
	bPasteResize=sal_False;
	bNoBitmapCaching=sal_False;
	bReadOnly=sal_False;
	nStreamCompressMode=COMPRESSMODE_NONE;
	nStreamNumberFormat=NUMBERFORMAT_INT_BIGENDIAN;
	nDefaultTabulator=0;
	pColorTable=NULL;
	pDashList=NULL;
	pLineEndList=NULL;
	pHatchList=NULL;
	pGradientList=NULL;
	pBitmapList=NULL;
	mpNumberFormatter = NULL;
	bTransparentTextFrames=sal_False;
	bStarDrawPreviewMode = sal_False;
	nStarDrawPreviewMasterPageNum = SDRPAGE_NOTFOUND;
	pModelStorage = NULL;
	mpForbiddenCharactersTable = NULL;
	mbModelLocked = sal_False;
	mpOutlinerCache = NULL;
	mbKernAsianPunctuation = sal_False;
    mbAddExtLeading = sal_False;
	mnHandoutPageCount = 0;

    SvxAsianConfig aAsian;
	mnCharCompressType = aAsian.GetCharDistanceCompression();

#ifdef OSL_LITENDIAN
	nStreamNumberFormat=NUMBERFORMAT_INT_LITTLEENDIAN;
#endif
	bExtColorTable=bUseExtColorTable;

	if ( pPool == NULL )
    {
		pItemPool=new SdrItemPool(0L, bLoadRefCounts);
		// Der Outliner hat keinen eigenen Pool, deshalb den der EditEngine
		SfxItemPool* pOutlPool=EditEngine::CreatePool( bLoadRefCounts );
		// OutlinerPool als SecondaryPool des SdrPool
		pItemPool->SetSecondaryPool(pOutlPool);
		// Merken, dass ich mir die beiden Pools selbst gemacht habe
		bMyPool=sal_True;
	}
	pItemPool->SetDefaultMetric((SfxMapUnit)eObjUnit);

// SJ: #95129# using static SdrEngineDefaults only if default SvxFontHeight item is not available
    const SfxPoolItem* pPoolItem = pItemPool->GetPoolDefaultItem( EE_CHAR_FONTHEIGHT );
    if ( pPoolItem )
        nDefTextHgt = ((SvxFontHeightItem*)pPoolItem)->GetHeight();
    else
        nDefTextHgt = SdrEngineDefaults::GetFontHeight();

	pItemPool->SetPoolDefaultItem( SdrTextWordWrapItem( sal_False ) );

	SetTextDefaults();

	pLayerAdmin=new SdrLayerAdmin;
	pLayerAdmin->SetModel(this);
	ImpSetUIUnit();

	// den DrawOutliner OnDemand erzeugen geht noch nicht, weil ich den Pool
	// sonst nicht kriege (erst ab 302!)
	pDrawOutliner = SdrMakeOutliner( OUTLINERMODE_TEXTOBJECT, this );
	ImpSetOutlinerDefaults(pDrawOutliner, sal_True);

	pHitTestOutliner = SdrMakeOutliner( OUTLINERMODE_TEXTOBJECT, this );
	ImpSetOutlinerDefaults(pHitTestOutliner, sal_True);

	ImpCreateTables();
}

SdrModel::SdrModel(SfxItemPool* pPool, ::comphelper::IEmbeddedHelper* pPers, sal_Bool bLoadRefCounts):
	maMaPag(1024,32,32),
	maPages(1024,32,32)
{
#ifdef TIMELOG
    RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "svx", "aw93748", "SdrModel::SdrModel(...)" );
#endif

	DBG_CTOR(SdrModel,NULL);
	ImpCtor(pPool,pPers,sal_False, (FASTBOOL)bLoadRefCounts);
}

SdrModel::SdrModel(const String& rPath, SfxItemPool* pPool, ::comphelper::IEmbeddedHelper* pPers, sal_Bool bLoadRefCounts):
	maMaPag(1024,32,32),
	maPages(1024,32,32),
	aTablePath(rPath)
{
#ifdef TIMELOG
    RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "svx", "aw93748", "SdrModel::SdrModel(...)" );
#endif

	DBG_CTOR(SdrModel,NULL);
	ImpCtor(pPool,pPers,sal_False, (FASTBOOL)bLoadRefCounts);
}

SdrModel::SdrModel(SfxItemPool* pPool, ::comphelper::IEmbeddedHelper* pPers, FASTBOOL bUseExtColorTable, sal_Bool bLoadRefCounts):
	maMaPag(1024,32,32),
	maPages(1024,32,32)
{
#ifdef TIMELOG
    RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "svx", "aw93748", "SdrModel::SdrModel(...)" );
#endif

	DBG_CTOR(SdrModel,NULL);
	ImpCtor(pPool,pPers,bUseExtColorTable, (FASTBOOL)bLoadRefCounts);
}

SdrModel::SdrModel(const String& rPath, SfxItemPool* pPool, ::comphelper::IEmbeddedHelper* pPers, FASTBOOL bUseExtColorTable, sal_Bool bLoadRefCounts):
	maMaPag(1024,32,32),
	maPages(1024,32,32),
	aTablePath(rPath)
{
#ifdef TIMELOG
    RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "svx", "aw93748", "SdrModel::SdrModel(...)" );
#endif

	DBG_CTOR(SdrModel,NULL);
	ImpCtor(pPool,pPers,bUseExtColorTable, (FASTBOOL)bLoadRefCounts);
}

SdrModel::SdrModel(const SdrModel& /*rSrcModel*/):
	SfxBroadcaster(),
	tools::WeakBase< SdrModel >(),
	maMaPag(1024,32,32),
	maPages(1024,32,32)
{
#ifdef TIMELOG
    RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "svx", "aw93748", "SdrModel::SdrModel(...)" );
#endif

	// noch nicht implementiert
	DBG_ERROR("SdrModel::CopyCtor() ist noch nicht implementiert");
}

SdrModel::~SdrModel()
{
#ifdef TIMELOG
    RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "svx", "aw93748", "SdrModel::~SdrModel(...)" );
#endif

	DBG_DTOR(SdrModel,NULL);

	mbInDestruction = true;

	Broadcast(SdrHint(HINT_MODELCLEARED));

	delete mpOutlinerCache;

	ClearUndoBuffer();
#ifdef DBG_UTIL
	if(pAktUndoGroup)
	{
		ByteString aStr("Im Dtor des SdrModel steht noch ein offenes Undo rum: \"");

		aStr += ByteString(pAktUndoGroup->GetComment(), gsl_getSystemTextEncoding());
		aStr += '\"';

		DBG_ERROR(aStr.GetBuffer());
	}
#endif
	if (pAktUndoGroup!=NULL)
		delete pAktUndoGroup;

	// #116168#
	ClearModel(sal_True);

	delete pLayerAdmin;

	// Den DrawOutliner erst nach dem ItemPool loeschen, da
	// der ItemPool Items des DrawOutliners referenziert !!! (<- das war mal)
	// Wg. Problem bei Malte Reihenfolge wieder umgestellt.
	// Loeschen des Outliners vor dem loeschen des ItemPools
	delete pHitTestOutliner;
	delete pDrawOutliner;

	// delete StyleSheetPool, derived classes should not do this since
	// the DrawingEngine may need it in its destrctor (SB)
	if( mxStyleSheetPool.is() )
	{
		Reference< XComponent > xComponent( dynamic_cast< cppu::OWeakObject* >( mxStyleSheetPool.get() ), UNO_QUERY );
		if( xComponent.is() ) try
		{
			xComponent->dispose();
		}
		catch( RuntimeException& )
		{
		}
		mxStyleSheetPool.clear();
	}

	if (bMyPool)
	{
		// Pools loeschen, falls es meine sind
		SfxItemPool* pOutlPool=pItemPool->GetSecondaryPool();
        SfxItemPool::Free(pItemPool);
		// Der OutlinerPool muss nach dem ItemPool plattgemacht werden, da der
		// ItemPool SetItems enthaelt die ihrerseits Items des OutlinerPools
		// referenzieren (Joe)
        SfxItemPool::Free(pOutlPool);
	}

	if( mpForbiddenCharactersTable )
		mpForbiddenCharactersTable->release();

	// Tabellen, Listen und Paletten loeschen
	if (!bExtColorTable)
		delete pColorTable;
	delete pDashList;
	delete pLineEndList;
	delete pHatchList;
	delete pGradientList;
	delete pBitmapList;

	if(mpNumberFormatter)
		delete mpNumberFormatter;

	delete mpImpl->mpUndoFactory;
	delete mpImpl;
}

bool SdrModel::IsInDestruction() const
{
	return mbInDestruction;
}

const SvNumberFormatter& SdrModel::GetNumberFormatter() const
{
	if(!mpNumberFormatter)
	{
		// use cast here since from outside view this IS a const method
		((SdrModel*)this)->mpNumberFormatter = new SvNumberFormatter(
			::comphelper::getProcessServiceFactory(), LANGUAGE_SYSTEM);
	}

	return *mpNumberFormatter;
}

// noch nicht implementiert:
void SdrModel::operator=(const SdrModel& /*rSrcModel*/)
{
	DBG_ERROR("SdrModel::operator=() ist noch nicht implementiert");
}

FASTBOOL SdrModel::operator==(const SdrModel& /*rCmpModel*/) const
{
	DBG_ERROR("SdrModel::operator==() ist noch nicht implementiert");
	return sal_False;
}

void SdrModel::SetSwapGraphics( FASTBOOL bSwap )
{
	bSwapGraphics = bSwap;
}

FASTBOOL SdrModel::IsReadOnly() const
{
	return bReadOnly;
}

void SdrModel::SetReadOnly(FASTBOOL bYes)
{
	bReadOnly=bYes;
}

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

void SdrModel::SetMaxUndoActionCount(sal_uIntPtr nAnz)
{
	if (nAnz<1) nAnz=1;
	nMaxUndoCount=nAnz;
	if (pUndoStack!=NULL) {
		while (pUndoStack->Count()>nMaxUndoCount) {
			delete (SfxUndoAction*) pUndoStack->Remove(pUndoStack->Count());
		}
	}
}

void SdrModel::ClearUndoBuffer()
{
	if (pUndoStack!=NULL) {
		while (pUndoStack->Count()!=0) {
			delete (SfxUndoAction*) pUndoStack->Remove(pUndoStack->Count()-1);
		}
		delete pUndoStack;
		pUndoStack=NULL;
	}
	if (pRedoStack!=NULL) {
		while (pRedoStack->Count()!=0) {
			delete (SfxUndoAction*) pRedoStack->Remove(pRedoStack->Count()-1);
		}
		delete pRedoStack;
		pRedoStack=NULL;
	}
}

FASTBOOL SdrModel::Undo()
{
	FASTBOOL bRet=sal_False;
	if( mpImpl->mpUndoManager )
	{
		DBG_ERROR("svx::SdrModel::Undo(), method not supported with application undo manager!");
	}
	else
	{
		SfxUndoAction* pDo=(SfxUndoAction*)GetUndoAction(0);
		if(pDo!=NULL)
		{
			const bool bWasUndoEnabled = mbUndoEnabled;
			mbUndoEnabled = false;
			pDo->Undo();
			if(pRedoStack==NULL)
				pRedoStack=new Container(1024,16,16);
			pRedoStack->Insert(pUndoStack->Remove((sal_uIntPtr)0),(sal_uIntPtr)0);
			mbUndoEnabled = bWasUndoEnabled;
		}
	}
	return bRet;
}

FASTBOOL SdrModel::Redo()
{
	FASTBOOL bRet=sal_False;
	if( mpImpl->mpUndoManager )
	{
		DBG_ERROR("svx::SdrModel::Redo(), method not supported with application undo manager!");
	}
	else
	{
		SfxUndoAction* pDo=(SfxUndoAction*)GetRedoAction(0);
		if(pDo!=NULL)
		{
			const bool bWasUndoEnabled = mbUndoEnabled;
			mbUndoEnabled = false;
			pDo->Redo();
			if(pUndoStack==NULL)
				pUndoStack=new Container(1024,16,16);
			pUndoStack->Insert(pRedoStack->Remove((sal_uIntPtr)0),(sal_uIntPtr)0);
			mbUndoEnabled = bWasUndoEnabled;
		}
	}
	return bRet;
}

FASTBOOL SdrModel::Repeat(SfxRepeatTarget& rView)
{
	FASTBOOL bRet=sal_False;
	if( mpImpl->mpUndoManager )
	{
		DBG_ERROR("svx::SdrModel::Redo(), method not supported with application undo manager!");
	}
	else
	{
		SfxUndoAction* pDo=(SfxUndoAction*)GetUndoAction(0);
		if(pDo!=NULL)
		{
			if(pDo->CanRepeat(rView))
			{
				pDo->Repeat(rView);
				bRet=sal_True;
			}
		}
	}
	return bRet;
}

void SdrModel::ImpPostUndoAction(SdrUndoAction* pUndo)
{
	DBG_ASSERT( mpImpl->mpUndoManager == 0, "svx::SdrModel::ImpPostUndoAction(), method not supported with application undo manager!" );
	if( IsUndoEnabled() )
	{
		if (aUndoLink.IsSet())
		{
			aUndoLink.Call(pUndo);
		}
		else
		{
			if (pUndoStack==NULL)
				pUndoStack=new Container(1024,16,16);
			pUndoStack->Insert(pUndo,(sal_uIntPtr)0);
			while (pUndoStack->Count()>nMaxUndoCount)
			{
				delete (SfxUndoAction*)pUndoStack->Remove(pUndoStack->Count()-1);
			}
			if (pRedoStack!=NULL)
				pRedoStack->Clear();
		}
	}
	else
	{
		delete pUndo;
	}
}

void SdrModel::BegUndo()
{
	if( mpImpl->mpUndoManager )
	{
		const String aEmpty;
		mpImpl->mpUndoManager->EnterListAction(aEmpty,aEmpty);
		nUndoLevel++;
	}
	else if( IsUndoEnabled() )
	{
		if(pAktUndoGroup==NULL)
		{
			pAktUndoGroup = new SdrUndoGroup(*this);
			nUndoLevel=1;
		}
		else
		{
			nUndoLevel++;
		}
	}
}

void SdrModel::BegUndo(const XubString& rComment)
{
	if( mpImpl->mpUndoManager )
	{
		const String aEmpty;
		mpImpl->mpUndoManager->EnterListAction( rComment, aEmpty );
		nUndoLevel++;
	}
	else if( IsUndoEnabled() )
	{
		BegUndo();
		if (nUndoLevel==1)
		{
			pAktUndoGroup->SetComment(rComment);
		}
	}
}

void SdrModel::BegUndo(const XubString& rComment, const XubString& rObjDescr, SdrRepeatFunc eFunc)
{
	if( mpImpl->mpUndoManager )
	{
		String aComment(rComment);
		if( aComment.Len() && rObjDescr.Len() )
		{
			String aSearchString(RTL_CONSTASCII_USTRINGPARAM("%1"));
			aComment.SearchAndReplace(aSearchString, rObjDescr);
		}
		const String aEmpty;
		mpImpl->mpUndoManager->EnterListAction( aComment,aEmpty );
		nUndoLevel++;
	}
	else if( IsUndoEnabled() )
	{
		BegUndo();
		if (nUndoLevel==1)
		{
			pAktUndoGroup->SetComment(rComment);
			pAktUndoGroup->SetObjDescription(rObjDescr);
			pAktUndoGroup->SetRepeatFunction(eFunc);
		}
	}
}

void SdrModel::BegUndo(SdrUndoGroup* pUndoGrp)
{
	if( mpImpl->mpUndoManager )
	{
		DBG_ERROR("svx::SdrModel::BegUndo(), method not supported with application undo manager!" );
		nUndoLevel++;
	}
	else if( IsUndoEnabled() )
	{
		if (pAktUndoGroup==NULL)
		{
			pAktUndoGroup=pUndoGrp;
			nUndoLevel=1;
		}
		else
		{
			delete pUndoGrp;
			nUndoLevel++;
		}
	}
	else
	{
		delete pUndoGrp;
	}
}

void SdrModel::EndUndo()
{
	DBG_ASSERT(nUndoLevel!=0,"SdrModel::EndUndo(): UndoLevel is already 0!");
	if( mpImpl->mpUndoManager )
	{
		if( nUndoLevel )
		{
			nUndoLevel--;
			mpImpl->mpUndoManager->LeaveListAction();
		}
	}
	else
	{
		if(pAktUndoGroup!=NULL && IsUndoEnabled())
		{
			nUndoLevel--;
			if(nUndoLevel==0)
			{
				if(pAktUndoGroup->GetActionCount()!=0)
				{
					SdrUndoAction* pUndo=pAktUndoGroup;
					pAktUndoGroup=NULL;
					ImpPostUndoAction(pUndo);
				}
				else
				{
					// was empty
					delete pAktUndoGroup;
					pAktUndoGroup=NULL;
				}
			}
		}
	}
}

void SdrModel::SetUndoComment(const XubString& rComment)
{
	DBG_ASSERT(nUndoLevel!=0,"SdrModel::SetUndoComment(): UndoLevel is on level 0!");

	if( mpImpl->mpUndoManager )
	{
		DBG_ERROR("svx::SdrModel::SetUndoComment(), method not supported with application undo manager!" );
	}
	else if( IsUndoEnabled() )
	{
		if(nUndoLevel==1)
		{
			pAktUndoGroup->SetComment(rComment);
		}
	}
}

void SdrModel::SetUndoComment(const XubString& rComment, const XubString& rObjDescr)
{
	DBG_ASSERT(nUndoLevel!=0,"SdrModel::SetUndoComment(): UndoLevel is 0!");
	if( mpImpl->mpUndoManager )
	{
		DBG_ERROR("svx::SdrModel::SetUndoComment(), method not supported with application undo manager!" );
	}
	else
	{
		if (nUndoLevel==1)
		{
			pAktUndoGroup->SetComment(rComment);
			pAktUndoGroup->SetObjDescription(rObjDescr);
		}
	}
}

void SdrModel::AddUndo(SdrUndoAction* pUndo)
{
	if( mpImpl->mpUndoManager )
	{
		mpImpl->mpUndoManager->AddUndoAction( pUndo );
	}
	else if( !IsUndoEnabled() )
	{
		delete pUndo;
	}
	else
	{
		if (pAktUndoGroup!=NULL)
		{
			pAktUndoGroup->AddAction(pUndo);
		}
		else
		{
			ImpPostUndoAction(pUndo);
		}
	}
}

void SdrModel::EnableUndo( bool bEnable )
{
	if( mpImpl->mpUndoManager )
	{
		mpImpl->mpUndoManager->EnableUndo( bEnable );
	}
	else
	{
		mbUndoEnabled = bEnable;
	}
}

bool SdrModel::IsUndoEnabled() const
{
	if( mpImpl->mpUndoManager )
	{
		return mpImpl->mpUndoManager->IsUndoEnabled();
	}
	else
	{
		return mbUndoEnabled;
	}
}

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

void SdrModel::ImpCreateTables()
{
	// der Writer hat seinen eigenen ColorTable
	if (!bExtColorTable) pColorTable=new XColorTable(aTablePath,(XOutdevItemPool*)pItemPool);
	pDashList    =new XDashList    (aTablePath,(XOutdevItemPool*)pItemPool);
	pLineEndList =new XLineEndList (aTablePath,(XOutdevItemPool*)pItemPool);
	pHatchList   =new XHatchList   (aTablePath,(XOutdevItemPool*)pItemPool);
	pGradientList=new XGradientList(aTablePath,(XOutdevItemPool*)pItemPool);
	pBitmapList  =new XBitmapList  (aTablePath,(XOutdevItemPool*)pItemPool);
}

// #116168#
void SdrModel::ClearModel(sal_Bool bCalledFromDestructor)
{
	if(bCalledFromDestructor)
	{
		mbInDestruction = true;
	}

	sal_Int32 i;
	// delete all drawing pages
	sal_Int32 nAnz=GetPageCount();
	for (i=nAnz-1; i>=0; i--)
	{
		DeletePage( (sal_uInt16)i );
	}
	maPages.Clear();
	// #109538#
	PageListChanged();

	// delete all Masterpages
	nAnz=GetMasterPageCount();
	for(i=nAnz-1; i>=0; i--)
	{
		DeleteMasterPage( (sal_uInt16)i );
	}
	maMaPag.Clear();
	// #109538#
	MasterPageListChanged();

	pLayerAdmin->ClearLayer();
}

SdrModel* SdrModel::AllocModel() const
{
	SdrModel* pModel=new SdrModel;
	pModel->SetScaleUnit(eObjUnit,aObjUnit);
	return pModel;
}

SdrPage* SdrModel::AllocPage(FASTBOOL bMasterPage)
{
	return new SdrPage(*this,bMasterPage);
}

void SdrModel::SetTextDefaults() const
{
	SetTextDefaults( pItemPool, nDefTextHgt );
}

void ImpGetDefaultFontsLanguage( SvxFontItem& rLatin, SvxFontItem& rAsian, SvxFontItem& rComplex)
{
	const sal_uInt16 nItemCnt = 3;
	static struct {
		sal_uInt16 nFntType, nLanguage;
	}  aOutTypeArr[ nItemCnt ] = {
		{  DEFAULTFONT_LATIN_TEXT, LANGUAGE_ENGLISH_US },
		{  DEFAULTFONT_CJK_TEXT, LANGUAGE_ENGLISH_US },
		{  DEFAULTFONT_CTL_TEXT, LANGUAGE_ARABIC_SAUDI_ARABIA }
	};
	SvxFontItem* aItemArr[ nItemCnt ] = { &rLatin, &rAsian, &rComplex };

	for( sal_uInt16 n = 0; n < nItemCnt; ++n )
	{
		Font aFnt( OutputDevice::GetDefaultFont(
			aOutTypeArr[ n ].nFntType, aOutTypeArr[ n ].nLanguage,
			DEFAULTFONT_FLAGS_ONLYONE, 0 ));
		SvxFontItem* pI = aItemArr[ n ];
        pI->SetFamily( aFnt.GetFamily());
        pI->SetFamilyName( aFnt.GetName());
        pI->SetStyleName( String() );
        pI->SetPitch( aFnt.GetPitch());
        pI->SetCharSet( aFnt.GetCharSet() );
	}
}

void SdrModel::SetTextDefaults( SfxItemPool* pItemPool, sal_uIntPtr nDefTextHgt )
{
	// #95114# set application-language specific dynamic pool language defaults
    SvxFontItem aSvxFontItem( EE_CHAR_FONTINFO) ;
	SvxFontItem aSvxFontItemCJK(EE_CHAR_FONTINFO_CJK);
	SvxFontItem aSvxFontItemCTL(EE_CHAR_FONTINFO_CTL);
	sal_uInt16 nLanguage(Application::GetSettings().GetLanguage());

	// get DEFAULTFONT_LATIN_TEXT and set at pool as dynamic default
	Font aFont(OutputDevice::GetDefaultFont(DEFAULTFONT_LATIN_TEXT, nLanguage, DEFAULTFONT_FLAGS_ONLYONE, 0));
    aSvxFontItem.SetFamily(aFont.GetFamily());
    aSvxFontItem.SetFamilyName(aFont.GetName());
    aSvxFontItem.SetStyleName(String());
    aSvxFontItem.SetPitch( aFont.GetPitch());
    aSvxFontItem.SetCharSet( aFont.GetCharSet() );
	pItemPool->SetPoolDefaultItem(aSvxFontItem);

	// get DEFAULTFONT_CJK_TEXT and set at pool as dynamic default
	Font aFontCJK(OutputDevice::GetDefaultFont(DEFAULTFONT_CJK_TEXT, nLanguage, DEFAULTFONT_FLAGS_ONLYONE, 0));
    aSvxFontItemCJK.SetFamily( aFontCJK.GetFamily());
    aSvxFontItemCJK.SetFamilyName(aFontCJK.GetName());
    aSvxFontItemCJK.SetStyleName(String());
    aSvxFontItemCJK.SetPitch( aFontCJK.GetPitch());
    aSvxFontItemCJK.SetCharSet( aFontCJK.GetCharSet());
	pItemPool->SetPoolDefaultItem(aSvxFontItemCJK);

	// get DEFAULTFONT_CTL_TEXT and set at pool as dynamic default
	Font aFontCTL(OutputDevice::GetDefaultFont(DEFAULTFONT_CTL_TEXT, nLanguage, DEFAULTFONT_FLAGS_ONLYONE, 0));
    aSvxFontItemCTL.SetFamily(aFontCTL.GetFamily());
    aSvxFontItemCTL.SetFamilyName(aFontCTL.GetName());
    aSvxFontItemCTL.SetStyleName(String());
    aSvxFontItemCTL.SetPitch( aFontCTL.GetPitch() );
    aSvxFontItemCTL.SetCharSet( aFontCTL.GetCharSet());
	pItemPool->SetPoolDefaultItem(aSvxFontItemCTL);

	// set dynamic FontHeight defaults
	pItemPool->SetPoolDefaultItem( SvxFontHeightItem(nDefTextHgt, 100, EE_CHAR_FONTHEIGHT ) );
	pItemPool->SetPoolDefaultItem( SvxFontHeightItem(nDefTextHgt, 100, EE_CHAR_FONTHEIGHT_CJK ) );
	pItemPool->SetPoolDefaultItem( SvxFontHeightItem(nDefTextHgt, 100, EE_CHAR_FONTHEIGHT_CTL ) );

	// set FontColor defaults
    pItemPool->SetPoolDefaultItem( SvxColorItem(SdrEngineDefaults::GetFontColor(), EE_CHAR_COLOR) );
}

SdrOutliner& SdrModel::GetDrawOutliner(const SdrTextObj* pObj) const
{
	pDrawOutliner->SetTextObj(pObj);
	return *pDrawOutliner;
}

boost::shared_ptr< SdrOutliner > SdrModel::CreateDrawOutliner(const SdrTextObj* pObj)
{
	boost::shared_ptr< SdrOutliner > xDrawOutliner( SdrMakeOutliner( OUTLINERMODE_TEXTOBJECT, this ) );
	ImpSetOutlinerDefaults(xDrawOutliner.get(), sal_True);
	xDrawOutliner->SetTextObj(pObj);
	return xDrawOutliner;
}

const SdrTextObj* SdrModel::GetFormattingTextObj() const
{
	if (pDrawOutliner!=NULL) {
		return pDrawOutliner->GetTextObj();
	}
	return NULL;
}

void SdrModel::ImpSetOutlinerDefaults( SdrOutliner* pOutliner, sal_Bool bInit )
{
	/**************************************************************************
	* Initialisierung der Outliner fuer Textausgabe und HitTest
	**************************************************************************/
	if( bInit )
	{
		pOutliner->EraseVirtualDevice();
		pOutliner->SetUpdateMode(sal_False);
		pOutliner->SetEditTextObjectPool(pItemPool);
		pOutliner->SetDefTab(nDefaultTabulator);
	}

	pOutliner->SetRefDevice(GetRefDevice());
	pOutliner->SetForbiddenCharsTable(GetForbiddenCharsTable());
	pOutliner->SetAsianCompressionMode( mnCharCompressType );
	pOutliner->SetKernAsianPunctuation( IsKernAsianPunctuation() );
    pOutliner->SetAddExtLeading( IsAddExtLeading() );

	if ( !GetRefDevice() )
	{
		MapMode aMapMode(eObjUnit, Point(0,0), aObjUnit, aObjUnit);
		pOutliner->SetRefMapMode(aMapMode);
	}
}

void SdrModel::SetRefDevice(OutputDevice* pDev)
{
	pRefOutDev=pDev;
	ImpSetOutlinerDefaults( pDrawOutliner );
	ImpSetOutlinerDefaults( pHitTestOutliner );
	RefDeviceChanged();
}

void SdrModel::ImpReformatAllTextObjects()
{
	if( isLocked() )
		return;

	sal_uInt16 nAnz=GetMasterPageCount();
	sal_uInt16 nNum;
	for (nNum=0; nNum<nAnz; nNum++) {
		GetMasterPage(nNum)->ReformatAllTextObjects();
	}
	nAnz=GetPageCount();
	for (nNum=0; nNum<nAnz; nNum++) {
		GetPage(nNum)->ReformatAllTextObjects();
	}
}

/** #103122#
	steps over all available pages and sends notify messages to
	all edge objects that are connected to other objects so that
	they may reposition itselfs
*/
void SdrModel::ImpReformatAllEdgeObjects()
{
	if( isLocked() )
		return;

	sal_uInt16 nAnz=GetMasterPageCount();
	sal_uInt16 nNum;
	for (nNum=0; nNum<nAnz; nNum++)
	{
		GetMasterPage(nNum)->ReformatAllEdgeObjects();
	}
	nAnz=GetPageCount();
	for (nNum=0; nNum<nAnz; nNum++)
	{
		GetPage(nNum)->ReformatAllEdgeObjects();
	}
}

SvStream* SdrModel::GetDocumentStream(SdrDocumentStreamInfo& /*rStreamInfo*/) const
{
	return NULL;
}

// Die Vorlagenattribute der Zeichenobjekte in harte Attribute verwandeln.
void SdrModel::BurnInStyleSheetAttributes()
{
	sal_uInt16 nAnz=GetMasterPageCount();
	sal_uInt16 nNum;
	for (nNum=0; nNum<nAnz; nNum++) {
		GetMasterPage(nNum)->BurnInStyleSheetAttributes();
	}
	nAnz=GetPageCount();
	for (nNum=0; nNum<nAnz; nNum++) {
		GetPage(nNum)->BurnInStyleSheetAttributes();
	}
}

void SdrModel::RefDeviceChanged()
{
	Broadcast(SdrHint(HINT_REFDEVICECHG));
	ImpReformatAllTextObjects();
}

void SdrModel::SetDefaultFontHeight(sal_uIntPtr nVal)
{
	if (nVal!=nDefTextHgt) {
		nDefTextHgt=nVal;
		Broadcast(SdrHint(HINT_DEFFONTHGTCHG));
		ImpReformatAllTextObjects();
	}
}

void SdrModel::SetDefaultTabulator(sal_uInt16 nVal)
{
	if (nDefaultTabulator!=nVal) {
		nDefaultTabulator=nVal;
		Outliner& rOutliner=GetDrawOutliner();
		rOutliner.SetDefTab(nVal);
		Broadcast(SdrHint(HINT_DEFAULTTABCHG));
		ImpReformatAllTextObjects();
	}
}

void SdrModel::ImpSetUIUnit()
{
	if(0 == aUIScale.GetNumerator() || 0 == aUIScale.GetDenominator()) 
    {
        aUIScale = Fraction(1,1);
    }

    // set start values
	nUIUnitKomma = 0;
	sal_Int64 nMul(1);
	sal_Int64 nDiv(1);

	// normalize on meters resp. inch
	switch (eObjUnit) 
    {
		case MAP_100TH_MM   : nUIUnitKomma+=5; break;
		case MAP_10TH_MM    : nUIUnitKomma+=4; break;
		case MAP_MM         : nUIUnitKomma+=3; break;
		case MAP_CM         : nUIUnitKomma+=2; break;
		case MAP_1000TH_INCH: nUIUnitKomma+=3; break;
		case MAP_100TH_INCH : nUIUnitKomma+=2; break;
		case MAP_10TH_INCH  : nUIUnitKomma+=1; break;
		case MAP_INCH       : nUIUnitKomma+=0; break;
		case MAP_POINT      : nDiv=72;     break;          // 1Pt   = 1/72"
		case MAP_TWIP       : nDiv=144; nUIUnitKomma++; break; // 1Twip = 1/1440"
		case MAP_PIXEL      : break;
		case MAP_SYSFONT    : break;
		case MAP_APPFONT    : break;
		case MAP_RELATIVE   : break;
		default: break;
	} // switch

	// 1 mile    =  8 furlong = 63.360" = 1.609.344,0mm
	// 1 furlong = 10 chains  =  7.920" =   201.168,0mm
	// 1 chain   =  4 poles   =    792" =    20.116,8mm
	// 1 pole    =  5 1/2 yd  =    198" =     5.029,2mm
	// 1 yd      =  3 ft      =     36" =       914,4mm
	// 1 ft      = 12 "       =      1" =       304,8mm
	switch (eUIUnit) 
    {
		case FUNIT_NONE   : break;
		// Metrisch
		case FUNIT_100TH_MM: nUIUnitKomma-=5; break;
		case FUNIT_MM     : nUIUnitKomma-=3; break;
		case FUNIT_CM     : nUIUnitKomma-=2; break;
		case FUNIT_M      : nUIUnitKomma+=0; break;
		case FUNIT_KM     : nUIUnitKomma+=3; break;
		// Inch
		case FUNIT_TWIP   : nMul=144; nUIUnitKomma--;  break;  // 1Twip = 1/1440"
		case FUNIT_POINT  : nMul=72;     break;            // 1Pt   = 1/72"
		case FUNIT_PICA   : nMul=6;      break;            // 1Pica = 1/6"  ?
		case FUNIT_INCH   : break;                         // 1"    = 1"
		case FUNIT_FOOT   : nDiv*=12;    break;            // 1Ft   = 12"
		case FUNIT_MILE   : nDiv*=6336; nUIUnitKomma++; break; // 1mile = 63360"
		// sonstiges
		case FUNIT_CUSTOM : break;
		case FUNIT_PERCENT: nUIUnitKomma+=2; break;
	} // switch

    // check if mapping is from metric to inch and adapt
	const bool bMapInch(IsInch(eObjUnit));
	const bool bUIMetr(IsMetric(eUIUnit));

    if (bMapInch && bUIMetr) 
    {
		nUIUnitKomma += 4;
		nMul *= 254;
	}
	
    // check if mapping is from inch to metric and adapt
	const bool bMapMetr(IsMetric(eObjUnit));
	const bool bUIInch(IsInch(eUIUnit));

    if (bMapMetr && bUIInch) 
    {
		nUIUnitKomma -= 4;
		nDiv *= 254;
	}

	// use temporary fraction for reduction (fallback to 32bit here),
    // may need to be changed in the future, too
    if(1 != nMul || 1 != nDiv)
    {
        const Fraction aTemp(static_cast< long >(nMul), static_cast< long >(nDiv));
        nMul = aTemp.GetNumerator();
        nDiv = aTemp.GetDenominator();
    }

    // #i89872# take Unit of Measurement into account
    if(1 != aUIScale.GetDenominator() || 1 != aUIScale.GetNumerator())
    {
        // divide by UIScale
	    nMul *= aUIScale.GetDenominator();
	    nDiv *= aUIScale.GetNumerator();
    }

    // shorten trailing zeroes for dividend
    while(0 == (nMul % 10))
    {
	    nUIUnitKomma--;
	    nMul /= 10;
    }

    // shorten trailing zeroes for divisor
    while(0 == (nDiv % 10)) 
    {
	    nUIUnitKomma++;
	    nDiv /= 10;
    }

    // end preparations, set member values
    aUIUnitFact = Fraction(sal_Int32(nMul), sal_Int32(nDiv));
	bUIOnlyKomma = (nMul == nDiv);
	TakeUnitStr(eUIUnit, aUIUnitStr);
}

void SdrModel::SetScaleUnit(MapUnit eMap, const Fraction& rFrac)
{
	if (eObjUnit!=eMap || aObjUnit!=rFrac) {
		eObjUnit=eMap;
		aObjUnit=rFrac;
		pItemPool->SetDefaultMetric((SfxMapUnit)eObjUnit);
		ImpSetUIUnit();
		ImpSetOutlinerDefaults( pDrawOutliner );
		ImpSetOutlinerDefaults( pHitTestOutliner );
		ImpReformatAllTextObjects(); // #40424#
	}
}

void SdrModel::SetScaleUnit(MapUnit eMap)
{
	if (eObjUnit!=eMap) {
		eObjUnit=eMap;
		pItemPool->SetDefaultMetric((SfxMapUnit)eObjUnit);
		ImpSetUIUnit();
		ImpSetOutlinerDefaults( pDrawOutliner );
		ImpSetOutlinerDefaults( pHitTestOutliner );
		ImpReformatAllTextObjects(); // #40424#
	}
}

void SdrModel::SetScaleFraction(const Fraction& rFrac)
{
	if (aObjUnit!=rFrac) {
		aObjUnit=rFrac;
		ImpSetUIUnit();
		ImpSetOutlinerDefaults( pDrawOutliner );
		ImpSetOutlinerDefaults( pHitTestOutliner );
		ImpReformatAllTextObjects(); // #40424#
	}
}

void SdrModel::SetUIUnit(FieldUnit eUnit)
{
	if (eUIUnit!=eUnit) {
		eUIUnit=eUnit;
		ImpSetUIUnit();
		ImpReformatAllTextObjects(); // #40424#
	}
}

void SdrModel::SetUIScale(const Fraction& rScale)
{
	if (aUIScale!=rScale) {
		aUIScale=rScale;
		ImpSetUIUnit();
		ImpReformatAllTextObjects(); // #40424#
	}
}

void SdrModel::SetUIUnit(FieldUnit eUnit, const Fraction& rScale)
{
	if (eUIUnit!=eUnit || aUIScale!=rScale) {
		eUIUnit=eUnit;
		aUIScale=rScale;
		ImpSetUIUnit();
		ImpReformatAllTextObjects(); // #40424#
	}
}

void SdrModel::TakeUnitStr(FieldUnit eUnit, XubString& rStr)
{
	switch(eUnit)
	{
		default:
		case FUNIT_NONE   :
		case FUNIT_CUSTOM :
		{
			rStr = String();
			break;
		}
		case FUNIT_100TH_MM:
		{
			sal_Char aText[] = "/100mm";
			rStr = UniString(aText, sizeof(aText-1));
			break;
		}
		case FUNIT_MM     :
		{
			sal_Char aText[] = "mm";
			rStr = UniString(aText, sizeof(aText-1));
			break;
		}
		case FUNIT_CM     :
		{
			sal_Char aText[] = "cm";
			rStr = UniString(aText, sizeof(aText-1));
			break;
		}
		case FUNIT_M      :
		{
			rStr = String();
			rStr += sal_Unicode('m');
			break;
		}
		case FUNIT_KM     :
		{
			sal_Char aText[] = "km";
			rStr = UniString(aText, sizeof(aText-1));
			break;
		}
		case FUNIT_TWIP   :
		{
			sal_Char aText[] = "twip";
			rStr = UniString(aText, sizeof(aText-1));
			break;
		}
		case FUNIT_POINT  :
		{
			sal_Char aText[] = "pt";
			rStr = UniString(aText, sizeof(aText-1));
			break;
		}
		case FUNIT_PICA   :
		{
			sal_Char aText[] = "pica";
			rStr = UniString(aText, sizeof(aText-1));
			break;
		}
		case FUNIT_INCH   :
		{
			rStr = String();
			rStr += sal_Unicode('"');
			break;
		}
		case FUNIT_FOOT   :
		{
			sal_Char aText[] = "ft";
			rStr = UniString(aText, sizeof(aText-1));
			break;
		}
		case FUNIT_MILE   :
		{
			sal_Char aText[] = "mile(s)";
			rStr = UniString(aText, sizeof(aText-1));
			break;
		}
		case FUNIT_PERCENT:
		{
			rStr = String();
			rStr += sal_Unicode('%');
			break;
		}
	}
}

void SdrModel::TakeMetricStr(long nVal, XubString& rStr, FASTBOOL bNoUnitChars, sal_Int32 nNumDigits) const
{
	// #i22167#
	// change to double precision usage to not loose decimal places after comma
	const bool bNegative(nVal < 0L);
    SvtSysLocale aSysLoc;
    const LocaleDataWrapper& rLoc(aSysLoc.GetLocaleData());
	double fLocalValue(double(nVal) * double(aUIUnitFact));

	if(bNegative)
	{
		fLocalValue = -fLocalValue;
	}

	if( -1 == nNumDigits )
	{
		nNumDigits = rLoc.getNumDigits();
	}

	sal_Int32 nKomma(nUIUnitKomma);

	if(nKomma > nNumDigits)
	{
		const sal_Int32 nDiff(nKomma - nNumDigits);
		const double fFactor(pow(10.0, static_cast<const int>(nDiff)));

		fLocalValue /= fFactor;
		nKomma = nNumDigits;
	}
	else if(nKomma < nNumDigits)
	{
		const sal_Int32 nDiff(nNumDigits - nKomma);
		const double fFactor(pow(10.0, static_cast<const int>(nDiff)));

		fLocalValue *= fFactor;
		nKomma = nNumDigits;
	}

	rStr = UniString::CreateFromInt32(static_cast<sal_Int32>(fLocalValue + 0.5));

	if(nKomma < 0)
	{
		// Negatives Komma bedeutet: Nullen dran
		sal_Int32 nAnz(-nKomma);

		for(sal_Int32 i=0; i<nAnz; i++)
			rStr += sal_Unicode('0');

		nKomma = 0;
	}

	// #83257# the second condition needs to be <= since inside this loop
	// also the leading zero is inserted.
	if(nKomma > 0 && rStr.Len() <= nKomma)
	{
		// Fuer Komma evtl. vorne Nullen dran
		sal_Int32 nAnz(nKomma - rStr.Len());

        if(nAnz >= 0 && rLoc.isNumLeadingZero())
			nAnz++;

		for(sal_Int32 i=0; i<nAnz; i++)
			rStr.Insert(sal_Unicode('0'), 0);
	}

    sal_Unicode cDec( rLoc.getNumDecimalSep().GetChar(0) );

	// KommaChar einfuegen
	sal_Int32 nVorKomma(rStr.Len() - nKomma);

	if(nKomma > 0)
        rStr.Insert(cDec, (xub_StrLen) nVorKomma);

    if(!rLoc.isNumTrailingZeros())
	{
		while(rStr.Len() && rStr.GetChar(rStr.Len() - 1) == sal_Unicode('0'))
			rStr.Erase(rStr.Len() - 1);

		if(rStr.Len() && rStr.GetChar(rStr.Len() - 1) == cDec)
			rStr.Erase(rStr.Len() - 1);
	}

	// ggf. Trennpunkte bei jedem Tausender einfuegen
    if( nVorKomma > 3 )
	{
        String aThoSep( rLoc.getNumThousandSep() );
        if ( aThoSep.Len() > 0 )
        {
            sal_Unicode cTho( aThoSep.GetChar(0) );
            sal_Int32 i(nVorKomma - 3);

            while(i > 0) // #78311#
            {
                rStr.Insert(cTho, (xub_StrLen)i);
                i -= 3;
            }
        }
	}

	if(!rStr.Len())
	{
		rStr = String();
		rStr += sal_Unicode('0');
	}

	if(bNegative)
	{
		rStr.Insert(sal_Unicode('-'), 0);
	}

	if(!bNoUnitChars)
		rStr += aUIUnitStr;
}

void SdrModel::TakeWinkStr(long nWink, XubString& rStr, FASTBOOL bNoDegChar) const
{
	sal_Bool bNeg(nWink < 0);

	if(bNeg)
		nWink = -nWink;

	rStr = UniString::CreateFromInt32(nWink);

    SvtSysLocale aSysLoc;
    const LocaleDataWrapper& rLoc = aSysLoc.GetLocaleData();
	xub_StrLen nAnz(2);

    if(rLoc.isNumLeadingZero())
		nAnz++;

	while(rStr.Len() < nAnz)
		rStr.Insert(sal_Unicode('0'), 0);

    rStr.Insert(rLoc.getNumDecimalSep().GetChar(0), rStr.Len() - 2);

	if(bNeg)
		rStr.Insert(sal_Unicode('-'), 0);

	if(!bNoDegChar)
		rStr += DEGREE_CHAR;
}

void SdrModel::TakePercentStr(const Fraction& rVal, XubString& rStr, FASTBOOL bNoPercentChar) const
{
	sal_Int32 nMul(rVal.GetNumerator());
	sal_Int32 nDiv(rVal.GetDenominator());
	sal_Bool bNeg(nMul < 0);

	if(nDiv < 0)
		bNeg = !bNeg;

	if(nMul < 0)
		nMul = -nMul;

	if(nDiv < 0)
		nDiv = -nDiv;

	nMul *= 100;
	nMul += nDiv/2;
	nMul /= nDiv;

	rStr = UniString::CreateFromInt32(nMul);

	if(bNeg)
		rStr.Insert(sal_Unicode('-'), 0);

	if(!bNoPercentChar)
		rStr += sal_Unicode('%');
}

void SdrModel::SetChanged(sal_Bool bFlg)
{
	mbChanged = bFlg;
}

void SdrModel::RecalcPageNums(FASTBOOL bMaster)
{
	Container& rPL=*(bMaster ? &maMaPag : &maPages);
	sal_uInt16 nAnz=sal_uInt16(rPL.Count());
	sal_uInt16 i;
	for (i=0; i<nAnz; i++) {
		SdrPage* pPg=(SdrPage*)(rPL.GetObject(i));
		pPg->SetPageNum(i);
	}
	if (bMaster) bMPgNumsDirty=sal_False;
	else bPagNumsDirty=sal_False;
}

void SdrModel::InsertPage(SdrPage* pPage, sal_uInt16 nPos)
{
	sal_uInt16 nAnz=GetPageCount();
	if (nPos>nAnz) nPos=nAnz;
	maPages.Insert(pPage,nPos);
	// #109538#
	PageListChanged();
	pPage->SetInserted(sal_True);
	pPage->SetPageNum(nPos);
	pPage->SetModel(this);
	if (nPos<nAnz) bPagNumsDirty=sal_True;
	SetChanged();
	SdrHint aHint(HINT_PAGEORDERCHG);
	aHint.SetPage(pPage);
	Broadcast(aHint);
}

void SdrModel::DeletePage(sal_uInt16 nPgNum)
{
	SdrPage* pPg=RemovePage(nPgNum);
	delete pPg;
}

SdrPage* SdrModel::RemovePage(sal_uInt16 nPgNum)
{
	SdrPage* pPg=(SdrPage*)maPages.Remove(nPgNum);
	// #109538#
	PageListChanged();
	if (pPg!=NULL) {
		pPg->SetInserted(sal_False);
	}
	bPagNumsDirty=sal_True;
	SetChanged();
	SdrHint aHint(HINT_PAGEORDERCHG);
	aHint.SetPage(pPg);
	Broadcast(aHint);
	return pPg;
}

void SdrModel::MovePage(sal_uInt16 nPgNum, sal_uInt16 nNewPos)
{
	SdrPage* pPg=(SdrPage*)maPages.Remove(nPgNum);
	// #109538#
	PageListChanged();
	if (pPg!=NULL) {
		pPg->SetInserted(sal_False);
		InsertPage(pPg,nNewPos);
	}
}

void SdrModel::InsertMasterPage(SdrPage* pPage, sal_uInt16 nPos)
{
	sal_uInt16 nAnz=GetMasterPageCount();
	if (nPos>nAnz) nPos=nAnz;
	maMaPag.Insert(pPage,nPos);
	// #109538#
	MasterPageListChanged();
	pPage->SetInserted(sal_True);
	pPage->SetPageNum(nPos);
	pPage->SetModel(this);
	if (nPos<nAnz) {
		bMPgNumsDirty=sal_True;
	}
	SetChanged();
	SdrHint aHint(HINT_PAGEORDERCHG);
	aHint.SetPage(pPage);
	Broadcast(aHint);
}

void SdrModel::DeleteMasterPage(sal_uInt16 nPgNum)
{
	SdrPage* pPg=RemoveMasterPage(nPgNum);
	if (pPg!=NULL) delete pPg;
}

SdrPage* SdrModel::RemoveMasterPage(sal_uInt16 nPgNum)
{
	SdrPage* pRetPg=(SdrPage*)maMaPag.Remove(nPgNum);
	// #109538#
	MasterPageListChanged();

	if(pRetPg)
	{
		// Nun die Verweise der normalen Zeichenseiten auf die entfernte MasterPage loeschen
		sal_uInt16 nPageAnz(GetPageCount());

		for(sal_uInt16 np(0); np < nPageAnz; np++)
		{
			GetPage(np)->TRG_ImpMasterPageRemoved(*pRetPg);
		}

		pRetPg->SetInserted(sal_False);
	}

	bMPgNumsDirty=sal_True;
	SetChanged();
	SdrHint aHint(HINT_PAGEORDERCHG);
	aHint.SetPage(pRetPg);
	Broadcast(aHint);
	return pRetPg;
}

void SdrModel::MoveMasterPage(sal_uInt16 nPgNum, sal_uInt16 nNewPos)
{
	SdrPage* pPg=(SdrPage*)maMaPag.Remove(nPgNum);
	// #109538#
	MasterPageListChanged();
	if (pPg!=NULL) {
		pPg->SetInserted(sal_False);
		maMaPag.Insert(pPg,nNewPos);
		// #109538#
		MasterPageListChanged();
	}
	bMPgNumsDirty=sal_True;
	SetChanged();
	SdrHint aHint(HINT_PAGEORDERCHG);
	aHint.SetPage(pPg);
	Broadcast(aHint);
}

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

FASTBOOL SdrModel::CheckConsistence() const
{
	FASTBOOL bRet=sal_True;
#ifdef DBG_UTIL
	DBG_CHKTHIS(SdrModel,NULL);
#endif
	return bRet;
}

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

// #48289#
void SdrModel::CopyPages(sal_uInt16 nFirstPageNum, sal_uInt16 nLastPageNum,
						 sal_uInt16 nDestPos,
						 FASTBOOL bUndo, FASTBOOL bMoveNoCopy)
{
	if( bUndo && !IsUndoEnabled() )
		bUndo = false;

	if( bUndo )
		BegUndo(ImpGetResStr(STR_UndoMergeModel));

	sal_uInt16 nPageAnz=GetPageCount();
	sal_uInt16 nMaxPage=nPageAnz;
	
	if (nMaxPage!=0)
		nMaxPage--;
	if (nFirstPageNum>nMaxPage)
		nFirstPageNum=nMaxPage;
	if (nLastPageNum>nMaxPage)
		nLastPageNum =nMaxPage;
	FASTBOOL bReverse=nLastPageNum<nFirstPageNum;
	if (nDestPos>nPageAnz)
		nDestPos=nPageAnz;

	// Zunaechst die Zeiger der betroffenen Seiten in einem Array sichern
	sal_uInt16 nPageNum=nFirstPageNum;
	sal_uInt16 nCopyAnz=((!bReverse)?(nLastPageNum-nFirstPageNum):(nFirstPageNum-nLastPageNum))+1;
	SdrPage** pPagePtrs=new SdrPage*[nCopyAnz];
	sal_uInt16 nCopyNum;
	for(nCopyNum=0; nCopyNum<nCopyAnz; nCopyNum++)
	{
		pPagePtrs[nCopyNum]=GetPage(nPageNum);
		if (bReverse)
			nPageNum--;
		else
			nPageNum++;
	}

	// Jetzt die Seiten kopieren
	sal_uInt16 nDestNum=nDestPos;
	for (nCopyNum=0; nCopyNum<nCopyAnz; nCopyNum++)
	{
		SdrPage* pPg=pPagePtrs[nCopyNum];
		sal_uInt16 nPageNum2=pPg->GetPageNum();
		if (!bMoveNoCopy)
		{
			const SdrPage* pPg1=GetPage(nPageNum2);
			pPg=pPg1->Clone();
			InsertPage(pPg,nDestNum);
			if (bUndo)
				AddUndo(GetSdrUndoFactory().CreateUndoCopyPage(*pPg));
			nDestNum++;
		}
		else
		{
			// Move ist nicht getestet!
			if (nDestNum>nPageNum2)
				nDestNum--;

			if(bUndo)
				AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*GetPage(nPageNum2),nPageNum2,nDestNum));

			pPg=RemovePage(nPageNum2);
			InsertPage(pPg,nDestNum);
			nDestNum++;
		}

		if(bReverse)
			nPageNum2--;
		else
			nPageNum2++;
	}

	delete[] pPagePtrs;
	if(bUndo)
		EndUndo();
}

void SdrModel::Merge(SdrModel& rSourceModel,
					 sal_uInt16 nFirstPageNum, sal_uInt16 nLastPageNum,
					 sal_uInt16 nDestPos,
					 FASTBOOL bMergeMasterPages, FASTBOOL bAllMasterPages,
					 FASTBOOL bUndo, FASTBOOL bTreadSourceAsConst)
{
	if (&rSourceModel==this)
	{ // #48289#
		CopyPages(nFirstPageNum,nLastPageNum,nDestPos,bUndo,!bTreadSourceAsConst);
		return;
	}

	if( bUndo && !IsUndoEnabled() )
		bUndo = false;

	if (bUndo)
		BegUndo(ImpGetResStr(STR_UndoMergeModel));

	sal_uInt16 nSrcPageAnz=rSourceModel.GetPageCount();
	sal_uInt16 nSrcMasterPageAnz=rSourceModel.GetMasterPageCount();
	sal_uInt16 nDstMasterPageAnz=GetMasterPageCount();
	FASTBOOL bInsPages=(nFirstPageNum<nSrcPageAnz || nLastPageNum<nSrcPageAnz);
	sal_uInt16 nMaxSrcPage=nSrcPageAnz; if (nMaxSrcPage!=0) nMaxSrcPage--;
	if (nFirstPageNum>nMaxSrcPage) nFirstPageNum=nMaxSrcPage;
	if (nLastPageNum>nMaxSrcPage)  nLastPageNum =nMaxSrcPage;
	FASTBOOL bReverse=nLastPageNum<nFirstPageNum;

	sal_uInt16*   pMasterMap=NULL;
	int* pMasterNeed=NULL;
	sal_uInt16    nMasterNeed=0;
	if (bMergeMasterPages && nSrcMasterPageAnz!=0) {
		// Feststellen, welche MasterPages aus rSrcModel benoetigt werden
		pMasterMap=new sal_uInt16[nSrcMasterPageAnz];
		pMasterNeed=new int[nSrcMasterPageAnz];
		memset(pMasterMap,0xFF,nSrcMasterPageAnz*sizeof(sal_uInt16));
		if (bAllMasterPages) {
			memset(pMasterNeed,sal_True,nSrcMasterPageAnz*sizeof(FASTBOOL));
		} else {
			memset(pMasterNeed,sal_False,nSrcMasterPageAnz*sizeof(FASTBOOL));
			sal_uInt16 nAnf= bReverse ? nLastPageNum : nFirstPageNum;
			sal_uInt16 nEnd= bReverse ? nFirstPageNum : nLastPageNum;
			for (sal_uInt16 i=nAnf; i<=nEnd; i++) {
				const SdrPage* pPg=rSourceModel.GetPage(i);
				if(pPg->TRG_HasMasterPage())
				{
					SdrPage& rMasterPage = pPg->TRG_GetMasterPage();
					sal_uInt16 nMPgNum(rMasterPage.GetPageNum());

					if(nMPgNum < nSrcMasterPageAnz)
					{
						pMasterNeed[nMPgNum] = sal_True;
					}
				}
			}
		}
		// Nun das Mapping der MasterPages bestimmen
		sal_uInt16 nAktMaPagNum=nDstMasterPageAnz;
		for (sal_uInt16 i=0; i<nSrcMasterPageAnz; i++) {
			if (pMasterNeed[i]) {
				pMasterMap[i]=nAktMaPagNum;
				nAktMaPagNum++;
				nMasterNeed++;
			}
		}
	}

	// rueberholen der Masterpages
	if (pMasterMap!=NULL && pMasterNeed!=NULL && nMasterNeed!=0) {
		for (sal_uInt16 i=nSrcMasterPageAnz; i>0;) {
			i--;
			if (pMasterNeed[i]) {
				SdrPage* pPg=NULL;
				if (bTreadSourceAsConst) {
					const SdrPage* pPg1=rSourceModel.GetMasterPage(i);
					pPg=pPg1->Clone();
				} else {
					pPg=rSourceModel.RemoveMasterPage(i);
				}
				if (pPg!=NULL) {
					// und alle ans einstige Ende des DstModel reinschieben.
					// nicht InsertMasterPage() verwenden da die Sache
					// inkonsistent ist bis alle drin sind
					maMaPag.Insert(pPg,nDstMasterPageAnz);
					// #109538#
					MasterPageListChanged();
					pPg->SetInserted(sal_True);
					pPg->SetModel(this);
					bMPgNumsDirty=sal_True;
					if (bUndo) AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pPg));
				} else {
					DBG_ERROR("SdrModel::Merge(): MasterPage im SourceModel nicht gefunden");
				}
			}
		}
	}

	// rueberholen der Zeichenseiten
	if (bInsPages) {
		sal_uInt16 nSourcePos=nFirstPageNum;
		sal_uInt16 nMergeCount=sal_uInt16(Abs((long)((long)nFirstPageNum-nLastPageNum))+1);
		if (nDestPos>GetPageCount()) nDestPos=GetPageCount();
		while (nMergeCount>0) {
			SdrPage* pPg=NULL;
			if (bTreadSourceAsConst) {
				const SdrPage* pPg1=rSourceModel.GetPage(nSourcePos);
				pPg=pPg1->Clone();
			} else {
				pPg=rSourceModel.RemovePage(nSourcePos);
			}
			if (pPg!=NULL) {
				InsertPage(pPg,nDestPos);
				if (bUndo) AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pPg));
				// und nun zu den MasterPageDescriptoren

				if(pPg->TRG_HasMasterPage())
				{
					SdrPage& rMasterPage = pPg->TRG_GetMasterPage();
					sal_uInt16 nMaPgNum(rMasterPage.GetPageNum());

					if (bMergeMasterPages)
					{
						sal_uInt16 nNeuNum(0xFFFF);

						if(pMasterMap)
						{
							nNeuNum = pMasterMap[nMaPgNum];
						}

						if(nNeuNum != 0xFFFF)
						{
							if(bUndo)
							{
								AddUndo(GetSdrUndoFactory().CreateUndoPageChangeMasterPage(*pPg));
							}

							pPg->TRG_SetMasterPage(*GetMasterPage(nNeuNum));
						}
						DBG_ASSERT(nNeuNum!=0xFFFF,"SdrModel::Merge(): Irgendwas ist krumm beim Mappen der MasterPages");
					} else {
						if (nMaPgNum>=nDstMasterPageAnz) {
							// Aha, die ist ausserbalb des urspruenglichen Bereichs der Masterpages des DstModel
							pPg->TRG_ClearMasterPage();
						}
					}
				}

			} else {
				DBG_ERROR("SdrModel::Merge(): Zeichenseite im SourceModel nicht gefunden");
			}
			nDestPos++;
			if (bReverse) nSourcePos--;
			else if (bTreadSourceAsConst) nSourcePos++;
			nMergeCount--;
		}
	}

	delete [] pMasterMap;
	delete [] pMasterNeed;

	bMPgNumsDirty=sal_True;
	bPagNumsDirty=sal_True;

	SetChanged();
	// Fehlt: Mergen und Mapping der Layer
	// an den Objekten sowie an den MasterPageDescriptoren
	if (bUndo) EndUndo();
}

void SdrModel::SetStarDrawPreviewMode(sal_Bool bPreview)
{
	if (!bPreview && bStarDrawPreviewMode && GetPageCount())
	{
		// Das Zuruecksetzen ist nicht erlaubt, da das Model ev. nicht vollstaendig geladen wurde
		DBG_ASSERT(sal_False,"SdrModel::SetStarDrawPreviewMode(): Zuruecksetzen nicht erlaubt, da Model ev. nicht vollstaendig");
	}
	else
	{
		bStarDrawPreviewMode = bPreview;
	}
}

uno::Reference< uno::XInterface > SdrModel::getUnoModel()
{
	if( !mxUnoModel.is() )
		mxUnoModel = createUnoModel();

	return mxUnoModel;
}

void SdrModel::setUnoModel( ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xModel )
{
    mxUnoModel = xModel;
}

uno::Reference< uno::XInterface > SdrModel::createUnoModel()
{
	DBG_ERROR( "SdrModel::createUnoModel() - base implementation should not be called!" );
	::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xInt;
	return xInt;
}

void SdrModel::setLock( sal_Bool bLock )
{
	if( mbModelLocked != bLock )
	{
        // #120437# need to set first, else ImpReformatAllEdgeObjects will do nothing
		mbModelLocked = bLock;

        if( sal_False == bLock )
		{
			// ReformatAllTextObjects(); #103122# due to a typo in the above if, this code was never
			//							 executed, so I remove it until we discover that we need it here
			ImpReformatAllEdgeObjects();	// #103122#
		}
	}
}

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

void SdrModel::MigrateItemSet( const SfxItemSet* pSourceSet, SfxItemSet* pDestSet, SdrModel* pNewModel )
{
	if( pSourceSet && pDestSet && (pSourceSet != pDestSet ) )
	{
		if( pNewModel == NULL )
			pNewModel = this;

		SfxWhichIter aWhichIter(*pSourceSet);
		sal_uInt16 nWhich(aWhichIter.FirstWhich());
		const SfxPoolItem *pPoolItem;

		while(nWhich)
		{
			if(SFX_ITEM_SET == pSourceSet->GetItemState(nWhich, sal_False, &pPoolItem))
			{
				const SfxPoolItem* pItem = pPoolItem;

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

				// set item
				if( pItem )
				{
					pDestSet->Put(*pItem);

					// delete item if it was a generated one
					if( pItem != pPoolItem)
						delete (SfxPoolItem*)pItem;
				}
			}
			nWhich = aWhichIter.NextWhich();
		}
	}
}

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

void SdrModel::SetForbiddenCharsTable( vos::ORef<SvxForbiddenCharactersTable> xForbiddenChars )
{
	if( mpForbiddenCharactersTable )
		mpForbiddenCharactersTable->release();

	mpForbiddenCharactersTable = xForbiddenChars.getBodyPtr();

	if( mpForbiddenCharactersTable )
		mpForbiddenCharactersTable->acquire();

	ImpSetOutlinerDefaults( pDrawOutliner );
	ImpSetOutlinerDefaults( pHitTestOutliner );
}

vos::ORef<SvxForbiddenCharactersTable> SdrModel::GetForbiddenCharsTable() const
{
	return mpForbiddenCharactersTable;
}

void SdrModel::SetCharCompressType( sal_uInt16 nType )
{
	if( nType != mnCharCompressType )
	{
		mnCharCompressType = nType;
		ImpSetOutlinerDefaults( pDrawOutliner );
		ImpSetOutlinerDefaults( pHitTestOutliner );
	}
}

void SdrModel::SetKernAsianPunctuation( sal_Bool bEnabled )
{
	if( mbKernAsianPunctuation != bEnabled )
	{
		mbKernAsianPunctuation = bEnabled;
		ImpSetOutlinerDefaults( pDrawOutliner );
		ImpSetOutlinerDefaults( pHitTestOutliner );
	}
}

void SdrModel::SetAddExtLeading( sal_Bool bEnabled )
{
    if( mbAddExtLeading != bEnabled )
    {
        mbAddExtLeading = bEnabled;
        ImpSetOutlinerDefaults( pDrawOutliner );
        ImpSetOutlinerDefaults( pHitTestOutliner );
    }
}

void SdrModel::ReformatAllTextObjects()
{
	ImpReformatAllTextObjects();
}

FASTBOOL SdrModel::HasTransparentObjects( sal_Bool bCheckForAlphaChannel ) const
{
	FASTBOOL	bRet = sal_False;
	sal_uInt16		n, nCount;

	for( n = 0, nCount = GetMasterPageCount(); ( n < nCount ) && !bRet; n++ )
		if( GetMasterPage( n )->HasTransparentObjects( bCheckForAlphaChannel ) )
			bRet = sal_True;

	if( !bRet )
	{
		for( n = 0, nCount = GetPageCount(); ( n < nCount ) && !bRet; n++ )
			if( GetPage( n )->HasTransparentObjects( bCheckForAlphaChannel ) )
				bRet = sal_True;
	}

	return bRet;
}

SdrOutliner* SdrModel::createOutliner( sal_uInt16 nOutlinerMode )
{
	if( NULL == mpOutlinerCache )
		mpOutlinerCache = new SdrOutlinerCache(this);

	return mpOutlinerCache->createOutliner( nOutlinerMode );
}

void SdrModel::disposeOutliner( SdrOutliner* pOutliner )
{
	if( mpOutlinerCache )
	{
		mpOutlinerCache->disposeOutliner( pOutliner );
	}
	else
	{
		delete pOutliner;
	}
}

SvxNumType SdrModel::GetPageNumType() const
{
	return SVX_ARABIC;
}

const SdrPage* SdrModel::GetPage(sal_uInt16 nPgNum) const
{
	DBG_ASSERT(nPgNum < maPages.Count(), "SdrModel::GetPage: Access out of range (!)");
	return (SdrPage*)(maPages.GetObject(nPgNum));
}

SdrPage* SdrModel::GetPage(sal_uInt16 nPgNum)
{
	DBG_ASSERT(nPgNum < maPages.Count(), "SdrModel::GetPage: Access out of range (!)");
	return (SdrPage*)(maPages.GetObject(nPgNum));
}

sal_uInt16 SdrModel::GetPageCount() const
{
	return sal_uInt16(maPages.Count());
}

void SdrModel::PageListChanged()
{
}

const SdrPage* SdrModel::GetMasterPage(sal_uInt16 nPgNum) const
{
	DBG_ASSERT(nPgNum < maMaPag.Count(), "SdrModel::GetMasterPage: Access out of range (!)");
	return (SdrPage*)(maMaPag.GetObject(nPgNum));
}

SdrPage* SdrModel::GetMasterPage(sal_uInt16 nPgNum)
{
	DBG_ASSERT(nPgNum < maMaPag.Count(), "SdrModel::GetMasterPage: Access out of range (!)");
	return (SdrPage*)(maMaPag.GetObject(nPgNum));
}

sal_uInt16 SdrModel::GetMasterPageCount() const
{
	return sal_uInt16(maMaPag.Count());
}

void SdrModel::MasterPageListChanged()
{
}

void SdrModel::SetSdrUndoManager( SfxUndoManager* pUndoManager )
{
	mpImpl->mpUndoManager = pUndoManager;
}

SfxUndoManager* SdrModel::GetSdrUndoManager() const
{
    return mpImpl->mpUndoManager;
}

SdrUndoFactory& SdrModel::GetSdrUndoFactory() const
{
	if( !mpImpl->mpUndoFactory )
		mpImpl->mpUndoFactory = new SdrUndoFactory;
	return *mpImpl->mpUndoFactory;
}

void SdrModel::SetSdrUndoFactory( SdrUndoFactory* pUndoFactory )
{
	if( pUndoFactory && (pUndoFactory != mpImpl->mpUndoFactory) )
	{
		delete mpImpl->mpUndoFactory;
		mpImpl->mpUndoFactory = pUndoFactory;
	}
}

/** cl: added this for OJ to complete his reporting engine, does not work
	correctly so only enable it for his model */
bool SdrModel::IsAllowShapePropertyChangeListener() const
{
	return mpImpl && mpImpl->mbAllowShapePropertyChangeListener;
}

void SdrModel::SetAllowShapePropertyChangeListener( bool bAllow )
{
	if( mpImpl )
	{
		mpImpl->mbAllowShapePropertyChangeListener = bAllow;
	}
}

const ::com::sun::star::uno::Sequence< sal_Int8 >& SdrModel::getUnoTunnelImplementationId()
{
	static ::com::sun::star::uno::Sequence< sal_Int8 > * pSeq = 0;
	if( !pSeq )
	{
		::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
		if( !pSeq )
		{
			static Sequence< sal_Int8 > aSeq( 16 );
			rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
			pSeq = &aSeq;
		}
	}
	return *pSeq;
}

//
// i120668, move from the header files, add delete action
//
void            SdrModel::SetColorTable(XColorTable* pTable)       { delete pColorTable; pColorTable=pTable; }
void            SdrModel::SetDashList(XDashList* pList)            { delete pDashList; pDashList=pList; }
void            SdrModel::SetLineEndList(XLineEndList* pList)      { delete pLineEndList; pLineEndList=pList; }
void            SdrModel::SetHatchList(XHatchList* pList)          { delete pHatchList; pHatchList=pList; }
void            SdrModel::SetGradientList(XGradientList* pList)    { delete pGradientList; pGradientList=pList; }
void            SdrModel::SetBitmapList(XBitmapList* pList)        { delete pBitmapList; pBitmapList=pList; }

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

TYPEINIT1(SdrHint,SfxHint);

SdrHint::SdrHint()
:	mpPage(0L),
	mpObj(0L),
	mpObjList(0L),
	meHint(HINT_UNKNOWN)
{
}

SdrHint::SdrHint(SdrHintKind eNewHint)
:	mpPage(0L),
	mpObj(0L),
	mpObjList(0L),
	meHint(eNewHint)
{
}

SdrHint::SdrHint(const SdrObject& rNewObj)
:	mpPage(rNewObj.GetPage()),
	mpObj(&rNewObj),
	mpObjList(rNewObj.GetObjList()),
	meHint(HINT_OBJCHG)
{
	maRectangle = rNewObj.GetLastBoundRect();
}

SdrHint::SdrHint(const SdrObject& rNewObj, const Rectangle& rRect)
:	mpPage(rNewObj.GetPage()),
	mpObj(&rNewObj),
	mpObjList(rNewObj.GetObjList()),
	meHint(HINT_OBJCHG)
{
	maRectangle = rRect;
}

void SdrHint::SetPage(const SdrPage* pNewPage)
{
	mpPage = pNewPage;
}

void SdrHint::SetObjList(const SdrObjList* pNewOL)
{
	mpObjList = pNewOL;
}

void SdrHint::SetObject(const SdrObject* pNewObj)
{
	mpObj = pNewObj;
}

void SdrHint::SetKind(SdrHintKind eNewKind)
{
	meHint = eNewKind;
}

void SdrHint::SetRect(const Rectangle& rNewRect)
{
	maRectangle = rNewRect;
}

const SdrPage* SdrHint::GetPage() const
{
	return mpPage;
}

const SdrObjList* SdrHint::GetObjList() const
{
	return mpObjList;
}

const SdrObject* SdrHint::GetObject() const
{
	return mpObj;
}

SdrHintKind SdrHint::GetKind() const
{
	return meHint;
}

const Rectangle& SdrHint::GetRect() const
{
	return maRectangle;
}

// eof