summaryrefslogtreecommitdiff
path: root/sw/source/core/attr/calbck.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/attr/calbck.cxx')
-rw-r--r--sw/source/core/attr/calbck.cxx567
1 files changed, 567 insertions, 0 deletions
diff --git a/sw/source/core/attr/calbck.cxx b/sw/source/core/attr/calbck.cxx
new file mode 100644
index 000000000000..844bd0dfbbd2
--- /dev/null
+++ b/sw/source/core/attr/calbck.cxx
@@ -0,0 +1,567 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx> // contains RES_.. IDs
+#include <frame.hxx>
+#include <hints.hxx>
+#include <swcache.hxx> // mba: get rid of that dependency
+#include <swfntcch.hxx> // mba: get rid of that dependency
+
+static SwClientIter* pClientIters = 0;
+
+TYPEINIT0(SwClient);
+
+/*************************************************************************/
+SwClient::SwClient(SwModify *pToRegisterIn)
+ : pLeft( 0 ), pRight( 0 ), pRegisteredIn( 0 ), mbIsAllowedToBeRemovedInModifyCall(false)
+{
+ if(pToRegisterIn)
+ // connect to SwModify
+ pToRegisterIn->Add(this);
+}
+
+/*************************************************************************/
+void SwClient::CheckRegistration( const SfxPoolItem* pOld, const SfxPoolItem * )
+{
+ // this method only handles notification about dying SwModify objects
+ if( (!pOld || pOld->Which() != RES_OBJECTDYING) )
+ return;
+
+ const SwPtrMsgPoolItem *pDead = static_cast<const SwPtrMsgPoolItem*>(pOld);
+ if(pDead && pDead->pObject == pRegisteredIn)
+ {
+ // I've got a notification from the object I know
+ SwModify *pAbove = const_cast<SwModify*>(pRegisteredIn->GetRegisteredIn());
+ if(pAbove)
+ {
+ // if the dying object itself was listening at an SwModify, I take over
+ // adding myself to pAbove will automatically remove me from my current pRegisteredIn
+ pAbove->Add(this);
+ return;
+ }
+
+ // destroy connection
+ pRegisteredIn->Remove(this);
+ }
+}
+
+void SwClient::Modify( const SfxPoolItem *pOldValue, const SfxPoolItem *pNewValue )
+{
+ CheckRegistration( pOldValue, pNewValue );
+}
+
+void SwClient::SwClientNotify( const SwModify&, const SfxHint& )
+{
+
+}
+
+//*************************************************************************
+SwClient::~SwClient()
+{
+ DBG_ASSERT( !pRegisteredIn || pRegisteredIn->GetDepends(),"SwModify still known, but Client already disconnected!" );
+ if( pRegisteredIn && pRegisteredIn->GetDepends() )
+ // still connected
+ pRegisteredIn->Remove( this );
+}
+
+
+sal_Bool SwClient::GetInfo( SfxPoolItem& ) const
+{
+ return sal_True; // und weiter
+}
+
+
+/*************************************************************************/
+SwModify::SwModify()
+ : SwClient(0), pRoot(0)
+{
+ bModifyLocked = sal_False;
+ bLockClientList = sal_False;
+ bInDocDTOR = sal_False;
+ bInCache = sal_False;
+ bInSwFntCache = sal_False;
+}
+
+SwModify::SwModify( SwModify *pToRegisterIn )
+ : SwClient(pToRegisterIn), pRoot( 0 )
+{
+ bModifyLocked = sal_False;
+ bLockClientList = sal_False;
+ bInDocDTOR = sal_False;
+ bInCache = sal_False;
+ bInSwFntCache = sal_False;
+}
+
+/*************************************************************************/
+SwModify::~SwModify()
+{
+ OSL_ENSURE( !IsModifyLocked(), "Modify destroyed but locked." );
+
+ if ( IsInCache() )
+ SwFrm::GetCache().Delete( this );
+
+ if ( IsInSwFntCache() )
+ pSwFontCache->Delete( this );
+
+ if( pRoot )
+ {
+ // there are depending objects
+ if( IsInDocDTOR() )
+ {
+ // if document gets destroyed anyway, just tell clients to forget me
+ // so that they don't try to get removed from my list later when they also get destroyed
+ SwClientIter aIter( *this );
+ SwClient* p = aIter.GoStart();
+ while ( p )
+ {
+ p->pRegisteredIn = 0;
+ p = aIter++;
+ }
+ }
+ else
+ {
+ // notify all clients that they shall remove themselves
+ SwPtrMsgPoolItem aDyObject( RES_OBJECTDYING, this );
+ NotifyClients( &aDyObject, &aDyObject );
+
+ // remove all clients that have not done themselves
+ // mba: possibly a hotfix for forgotten base class calls?!
+ while( pRoot )
+ pRoot->CheckRegistration(&aDyObject, &aDyObject);
+ }
+ }
+}
+
+/*************************************************************************/
+void SwModify::Modify( const SfxPoolItem *pOldValue, const SfxPoolItem *pNewValue )
+{
+ NotifyClients( pOldValue, pNewValue );
+}
+
+void SwModify::NotifyClients( const SfxPoolItem *pOldValue, const SfxPoolItem *pNewValue )
+{
+ if (IsInCache() || IsInSwFntCache())
+ {
+ const sal_uInt16 nWhich = pOldValue ? pOldValue->Which() :
+ pNewValue ? pNewValue->Which() : 0;
+ CheckCaching( nWhich );
+ }
+
+ if (!pRoot || IsModifyLocked())
+ return;
+
+ LockModify();
+
+ // mba: WTF?!
+ if( !pOldValue )
+ bLockClientList = sal_True;
+ else
+ {
+ // following Modifies shouldn't call an ASSERT
+ switch( pOldValue->Which() )
+ {
+ case RES_OBJECTDYING:
+ case RES_REMOVE_UNO_OBJECT:
+ bLockClientList = ((SwPtrMsgPoolItem *)pOldValue)->pObject != this;
+ break;
+
+ case RES_FOOTNOTE_DELETED:
+ case RES_REFMARK_DELETED:
+ case RES_TOXMARK_DELETED:
+ case RES_FIELD_DELETED:
+ bLockClientList = sal_False;
+ break;
+ default:
+ bLockClientList = sal_True;
+ }
+ }
+
+ ModifyBroadcast( pOldValue, pNewValue );
+ bLockClientList = sal_False;
+ UnlockModify();
+}
+
+sal_Bool SwModify::GetInfo( SfxPoolItem& rInfo ) const
+{
+ sal_Bool bRet = sal_True; // bedeutet weiter zum naechsten
+
+ if( pRoot )
+ {
+ SwClientIter aIter( *(SwModify*)this );
+
+ SwClient* pLast = aIter.GoStart();
+ if( pLast )
+ while( 0 != ( bRet = pLast->GetInfo( rInfo )) &&
+ 0 != ( pLast = aIter++ ) )
+ ;
+ }
+
+ return bRet;
+}
+
+/*************************************************************************/
+void SwModify::Add(SwClient *pDepend)
+{
+ OSL_ENSURE( !bLockClientList, "Client inserted while in Modify" );
+
+ if(pDepend->pRegisteredIn != this )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ SwClientIter* pTmp = pClientIters;
+ while( pTmp )
+ {
+ OSL_ENSURE( &pTmp->GetModify() != pRoot, "Client added to active ClientIter" );
+ pTmp = pTmp->pNxtIter;
+ }
+#endif
+ // deregister new client in case it is already registered elsewhere
+ if( pDepend->pRegisteredIn != 0 )
+ pDepend->pRegisteredIn->Remove( pDepend );
+
+ if( !pRoot )
+ {
+ // first client added
+ pRoot = pDepend;
+ pRoot->pLeft = 0;
+ pRoot->pRight = 0;
+ }
+ else
+ {
+ // append client
+ pDepend->pRight = pRoot->pRight;
+ pRoot->pRight = pDepend;
+ pDepend->pLeft = pRoot;
+ if( pDepend->pRight )
+ pDepend->pRight->pLeft = pDepend;
+ }
+
+ // connect client to me
+ pDepend->pRegisteredIn = this;
+ }
+}
+
+/*************************************************************************/
+
+SwClient* SwModify::Remove(SwClient * pDepend)
+{
+ if ( bInDocDTOR )
+ return 0;
+
+ OSL_ENSURE( !bLockClientList || pDepend->mbIsAllowedToBeRemovedInModifyCall, "SwClient shall be removed in Modify call!" );
+
+ if( pDepend->pRegisteredIn == this )
+ {
+ // SwClient is my listener
+ // remove it from my list
+ SwClient* pR = pDepend->pRight;
+ SwClient* pL = pDepend->pLeft;
+ if( pRoot == pDepend )
+ pRoot = pL ? pL : pR;
+
+ if( pL )
+ pL->pRight = pR;
+ if( pR )
+ pR->pLeft = pL;
+
+ // update ClientIters
+ SwClientIter* pTmp = pClientIters;
+ while( pTmp )
+ {
+ if( pTmp->pAct == pDepend || pTmp->pDelNext == pDepend )
+ // if object being removed is the current or next object in an iterator, advance this iterator
+ pTmp->pDelNext = pR;
+ pTmp = pTmp->pNxtIter;
+ }
+
+ pDepend->pLeft = 0;
+ pDepend->pRight = 0;
+ }
+ else
+ {
+ OSL_FAIL( "SwModify::Remove(): pDepend nicht gefunden" );
+ }
+
+ // disconnect client from me
+ pDepend->pRegisteredIn = 0;
+ return pDepend;
+}
+
+int SwModify::GetClientCount() const
+{
+ int nRet=0;
+ SwClientIter aIter( *this );
+ SwClient *pLast = aIter.GoStart();
+ if( pLast )
+ do
+ {
+ ++nRet;
+ } while( 0 != ( pLast = aIter++ ));
+ return nRet;
+}
+
+void SwModify::CheckCaching( const sal_uInt16 nWhich )
+{
+ if (isCHRATR(nWhich))
+ {
+ SetInSwFntCache( sal_False );
+ }
+ else
+ switch ( nWhich )
+ {
+ case RES_OBJECTDYING:
+ case RES_FMT_CHG:
+ case RES_ATTRSET_CHG:
+ SetInSwFntCache( sal_False );
+
+ case RES_UL_SPACE:
+ case RES_LR_SPACE:
+ case RES_BOX:
+ case RES_SHADOW:
+ case RES_FRM_SIZE:
+ case RES_KEEP:
+ case RES_BREAK:
+ if ( IsInCache() )
+ {
+ SwFrm::GetCache().Delete( this );
+ SetInCache( sal_False );
+ }
+ break;
+ }
+}
+
+void SwModify::CallSwClientNotify( const SfxHint& rHint ) const
+{
+ SwClientIter aIter(*this);
+ SwClient * pClient = aIter.GoStart();
+ while (pClient)
+ {
+ pClient->SwClientNotify( *this, rHint );
+ pClient = aIter++;
+ }
+}
+
+void SwModify::ModifyBroadcast( const SfxPoolItem *pOldValue, const SfxPoolItem *pNewValue, TypeId nType )
+{
+ SwClientIter aIter(*this);
+ SwClient * pClient = aIter.First( nType );
+ while (pClient)
+ {
+ pClient->Modify( pOldValue, pNewValue );
+ pClient = aIter.Next();
+ }
+}
+
+// ----------
+// SwDepend
+// ----------
+
+/*************************************************************************/
+
+SwDepend::SwDepend(SwClient *pTellHim, SwModify *pDepend)
+ : SwClient(pDepend)
+{
+ pToTell = pTellHim;
+}
+
+/*************************************************************************/
+
+void SwDepend::Modify( const SfxPoolItem* pOldValue, const SfxPoolItem *pNewValue )
+{
+ if(pNewValue && pNewValue->Which() == RES_OBJECTDYING)
+ CheckRegistration(pOldValue,pNewValue);
+ else if(pToTell)
+ pToTell->ModifyNotification(pOldValue, pNewValue);
+}
+
+void SwDepend::SwClientNotify( const SwModify& rMod, const SfxHint& rHint )
+{
+ if ( pToTell )
+ pToTell->SwClientNotifyCall( rMod, rHint );
+}
+
+sal_Bool SwDepend::GetInfo( SfxPoolItem& rInfo ) const
+{
+ return pToTell ? pToTell->GetInfo( rInfo ) : sal_True;
+}
+
+/********************************************************************/
+
+SwClientIter::SwClientIter( const SwModify& rModify )
+ : rRoot( rModify )
+{
+ pNxtIter = 0;
+ if( pClientIters )
+ {
+ // append to list of ClientIters
+ SwClientIter* pTmp = pClientIters;
+ while( pTmp->pNxtIter )
+ pTmp = pTmp->pNxtIter;
+ pTmp->pNxtIter = this;
+ }
+ else
+ pClientIters = this;
+
+ pAct = const_cast<SwClient*>(rRoot.GetDepends());
+ pDelNext = pAct;
+}
+
+
+
+SwClientIter::~SwClientIter()
+{
+ if( pClientIters )
+ {
+ // reorganize list of ClientIters
+ if( pClientIters == this )
+ pClientIters = pNxtIter;
+ else
+ {
+ SwClientIter* pTmp = pClientIters;
+ while( pTmp->pNxtIter != this )
+ if( 0 == ( pTmp = pTmp->pNxtIter ) )
+ {
+ OSL_ENSURE( this, "wo ist mein Pointer" );
+ return ;
+ }
+ pTmp->pNxtIter = pNxtIter;
+ }
+ }
+}
+
+
+SwClient* SwClientIter::operator++(int)
+{
+ if( pDelNext == pAct )
+ {
+ pAct = pAct->pRight;
+ pDelNext = pAct;
+ }
+ else
+ pAct = pDelNext;
+ return pAct;
+}
+
+SwClient* SwClientIter::GoStart()
+{
+ pAct = const_cast<SwClient*>(rRoot.GetDepends());
+ if( pAct )
+ while( pAct->pLeft )
+ pAct = pAct->pLeft;
+ pDelNext = pAct;
+ return pAct;
+}
+
+SwClient* SwClientIter::GoEnd()
+{
+ pAct = pDelNext;
+ if( !pAct )
+ pAct = const_cast<SwClient*>(rRoot.GetDepends());
+ if( pAct )
+ while( pAct->pRight )
+ pAct = pAct->pRight;
+ pDelNext = pAct;
+ return pAct;
+}
+
+SwClient* SwClientIter::First( TypeId nType )
+{
+ aSrchId = nType;
+ GoStart();
+ if( pAct )
+ do {
+ if( pAct->IsA( aSrchId ) )
+ break;
+
+ if( pDelNext == pAct )
+ {
+ pAct = pAct->pRight;
+ pDelNext = pAct;
+ }
+ else
+ pAct = pDelNext;
+
+ } while( pAct );
+ return pAct;
+}
+
+SwClient* SwClientIter::Next()
+{
+ do {
+ if( pDelNext == pAct )
+ {
+ pAct = pAct->pRight;
+ pDelNext = pAct;
+ }
+ else
+ pAct = pDelNext;
+
+ if( pAct && pAct->IsA( aSrchId ) )
+ break;
+ } while( pAct );
+ return pAct;
+}
+
+SwClient* SwClientIter::Last( TypeId nType )
+{
+ aSrchId = nType;
+ GoEnd();
+ if( pAct )
+ do {
+ if( pAct->IsA( aSrchId ) )
+ break;
+
+ if( pDelNext == pAct )
+ pAct = pAct->pLeft;
+ else
+ pAct = pDelNext->pLeft;
+ pDelNext = pAct;
+
+ } while( pAct );
+ return pAct;
+}
+
+SwClient* SwClientIter::Previous()
+{
+ do {
+ if( pDelNext == pAct )
+ pAct = pAct->pLeft;
+ else
+ pAct = pDelNext->pLeft;
+ pDelNext = pAct;
+
+ if( pAct && pAct->IsA( aSrchId ) )
+ break;
+ } while( pAct );
+ return pAct;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */