LCOV - code coverage report
Current view: top level - libreoffice/sw/source/core/attr - calbck.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 215 255 84.3 %
Date: 2012-12-27 Functions: 31 37 83.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <frame.hxx>
      21             : #include <hintids.hxx>          // contains RES_.. IDs
      22             : #include <hints.hxx>
      23             : #include <swcache.hxx>          // mba: get rid of that dependency
      24             : #include <swfntcch.hxx>         // mba: get rid of that dependency
      25             : 
      26             : static SwClientIter* pClientIters = 0;
      27             : 
      28      270198 : TYPEINIT0( SwClient );
      29             : 
      30             : // ----------
      31             : // SwClient
      32             : // ----------
      33             : 
      34       99034 : SwClient::SwClient( SwModify* pToRegisterIn )
      35       99034 :     : pLeft( 0 ), pRight( 0 ), pRegisteredIn( 0 ), mbIsAllowedToBeRemovedInModifyCall( false )
      36             : {
      37       99034 :     if(pToRegisterIn)
      38             :         // connect to SwModify
      39       37854 :         pToRegisterIn->Add(this);
      40       99034 : }
      41             : 
      42        5596 : void SwClient::CheckRegistration( const SfxPoolItem* pOld, const SfxPoolItem* )
      43             : {
      44             :     // this method only handles notification about dying SwModify objects
      45        5596 :     if( (!pOld || pOld->Which() != RES_OBJECTDYING) )
      46        5440 :         return;
      47             : 
      48         156 :     const SwPtrMsgPoolItem* pDead = static_cast<const SwPtrMsgPoolItem*>(pOld);
      49         156 :     if(pDead && pDead->pObject == pRegisteredIn)
      50             :     {
      51             :         // I've got a notification from the object I know
      52         156 :         SwModify* pAbove = const_cast<SwModify*>(pRegisteredIn->GetRegisteredIn());
      53         156 :         if(pAbove)
      54             :         {
      55             :             // if the dying object itself was listening at an SwModify, I take over
      56             :             // adding myself to pAbove will automatically remove me from my current pRegisteredIn
      57           0 :             pAbove->Add(this);
      58           0 :             return;
      59             :         }
      60             :         // destroy connection
      61         156 :         pRegisteredIn->Remove(this);
      62             :     }
      63             : }
      64             : 
      65        5111 : void SwClient::Modify( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue )
      66             : {
      67        5111 :     CheckRegistration( pOldValue, pNewValue );
      68        5111 : }
      69             : 
      70          61 : void SwClient::SwClientNotify( const SwModify&, const SfxHint& )
      71             : {
      72          61 : }
      73             : 
      74      179530 : SwClient::~SwClient()
      75             : {
      76             :     OSL_ENSURE( !pRegisteredIn || pRegisteredIn->GetDepends(), "SwModify still known, but Client already disconnected!" );
      77       89765 :     if( pRegisteredIn && pRegisteredIn->GetDepends() )
      78             :         // still connected
      79       29227 :         pRegisteredIn->Remove( this );
      80       89765 : }
      81             : 
      82         160 : bool SwClient::GetInfo( SfxPoolItem& ) const
      83             : {
      84         160 :     return true;
      85             : }
      86             : 
      87             : // ----------
      88             : // SwModify
      89             : // ----------
      90             : 
      91        2174 : SwModify::SwModify()
      92        2174 :     : SwClient(0), pRoot(0)
      93             : {
      94        2174 :     bModifyLocked = false;
      95        2174 :     bLockClientList = sal_False;
      96        2174 :     bInDocDTOR = sal_False;
      97        2174 :     bInCache = sal_False;
      98        2174 :     bInSwFntCache = sal_False;
      99        2174 : }
     100             : 
     101       34767 : SwModify::SwModify( SwModify* pToRegisterIn )
     102       34767 :     : SwClient( pToRegisterIn ), pRoot( 0 )
     103             : {
     104       34767 :     bModifyLocked = false;
     105       34767 :     bLockClientList = sal_False;
     106       34767 :     bInDocDTOR = sal_False;
     107       34767 :     bInCache = sal_False;
     108       34767 :     bInSwFntCache = sal_False;
     109       34767 : }
     110             : 
     111       48978 : SwModify::~SwModify()
     112             : {
     113             :     OSL_ENSURE( !IsModifyLocked(), "Modify destroyed but locked." );
     114             : 
     115       24438 :     if ( IsInCache() )
     116         412 :         SwFrm::GetCache().Delete( this );
     117             : 
     118       24438 :     if ( IsInSwFntCache() )
     119           0 :         pSwFontCache->Delete( this );
     120             : 
     121       24438 :     if( pRoot )
     122             :     {
     123             :         // there are depending objects
     124        7053 :         if( IsInDocDTOR() )
     125             :         {
     126             :             // If the document gets destroyed anyway, just tell clients to
     127             :             // forget me so that they don't try to get removed from my list
     128             :             // later when they also get destroyed
     129           0 :             SwClientIter aIter( *this );
     130           0 :             SwClient* p = aIter.GoStart();
     131           0 :             while ( p )
     132             :             {
     133           0 :                 p->pRegisteredIn = 0;
     134           0 :                 p = ++aIter;
     135           0 :             }
     136             :         }
     137             :         else
     138             :         {
     139             :             // notify all clients that they shall remove themselves
     140        7053 :             SwPtrMsgPoolItem aDyObject( RES_OBJECTDYING, this );
     141        7053 :             NotifyClients( &aDyObject, &aDyObject );
     142             : 
     143             :             // remove all clients that have not done themselves
     144             :             // mba: possibly a hotfix for forgotten base class calls?!
     145       14262 :             while( pRoot )
     146        7209 :                 pRoot->CheckRegistration( &aDyObject, &aDyObject );
     147             :         }
     148             :     }
     149       24540 : }
     150             : 
     151        6609 : void SwModify::Modify( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue )
     152             : {
     153        6609 :     NotifyClients( pOldValue, pNewValue );
     154        6609 : }
     155             : 
     156      103695 : void SwModify::NotifyClients( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue )
     157             : {
     158      103695 :     if ( IsInCache() || IsInSwFntCache() )
     159             :     {
     160             :         const sal_uInt16 nWhich = pOldValue ? pOldValue->Which() :
     161         313 :                                         pNewValue ? pNewValue->Which() : 0;
     162         313 :         CheckCaching( nWhich );
     163             :     }
     164             : 
     165      103695 :     if ( !pRoot || IsModifyLocked() )
     166      165352 :         return;
     167             : 
     168       42038 :     LockModify();
     169             : 
     170             :     // mba: WTF?!
     171       42038 :     if( !pOldValue )
     172             :     {
     173        9144 :         bLockClientList = sal_True;
     174             :     }
     175             :     else
     176             :     {
     177       32894 :         switch( pOldValue->Which() )
     178             :         {
     179             :         case RES_OBJECTDYING:
     180             :         case RES_REMOVE_UNO_OBJECT:
     181        7099 :             bLockClientList = ((SwPtrMsgPoolItem*)pOldValue)->pObject != this;
     182        7099 :             break;
     183             : 
     184             :         case RES_FOOTNOTE_DELETED:
     185             :         case RES_REFMARK_DELETED:
     186             :         case RES_TOXMARK_DELETED:
     187             :         case RES_FIELD_DELETED:
     188           2 :             bLockClientList = sal_False;
     189           2 :             break;
     190             : 
     191             :         default:
     192       25793 :             bLockClientList = sal_True;
     193             :         }
     194             :     }
     195             : 
     196       42038 :     ModifyBroadcast( pOldValue, pNewValue );
     197       42038 :     bLockClientList = sal_False;
     198       42038 :     UnlockModify();
     199             : }
     200             : 
     201        6060 : bool SwModify::GetInfo( SfxPoolItem& rInfo ) const
     202             : {
     203        6060 :     bool bRet = true;       // means: continue with next
     204             : 
     205        6060 :     if( pRoot )
     206             :     {
     207        1328 :         SwClientIter aIter( *(SwModify*)this );
     208             : 
     209        1328 :         SwClient* pLast = aIter.GoStart();
     210        1328 :         if( pLast )
     211             :         {
     212        1328 :             while( ( bRet = pLast->GetInfo( rInfo ) ) &&
     213             :                    0 != ( pLast = ++aIter ) )
     214             :                 ;
     215        1328 :         }
     216             :     }
     217             : 
     218        6060 :     return bRet;
     219             : }
     220             : 
     221       61604 : void SwModify::Add( SwClient* pDepend )
     222             : {
     223             :     OSL_ENSURE( !bLockClientList, "Client inserted while in Modify" );
     224             : 
     225       61604 :     if(pDepend->pRegisteredIn != this )
     226             :     {
     227             : #if OSL_DEBUG_LEVEL > 0
     228             :         SwClientIter* pTmp = pClientIters;
     229             :         while( pTmp )
     230             :         {
     231             :             OSL_ENSURE( &pTmp->GetModify() != pRoot, "Client added to active ClientIter" );
     232             :             pTmp = pTmp->pNxtIter;
     233             :         }
     234             : #endif
     235             :         // deregister new client in case it is already registered elsewhere
     236       57879 :         if( pDepend->pRegisteredIn != 0 )
     237        3550 :             pDepend->pRegisteredIn->Remove( pDepend );
     238             : 
     239       57879 :         if( !pRoot )
     240             :         {
     241             :             // first client added
     242       29135 :             pRoot = pDepend;
     243       29135 :             pRoot->pLeft = 0;
     244       29135 :             pRoot->pRight = 0;
     245             :         }
     246             :         else
     247             :         {
     248             :             // append client
     249       28744 :             pDepend->pRight = pRoot->pRight;
     250       28744 :             pRoot->pRight = pDepend;
     251       28744 :             pDepend->pLeft = pRoot;
     252       28744 :             if( pDepend->pRight )
     253       20286 :                 pDepend->pRight->pLeft = pDepend;
     254             :         }
     255             : 
     256             :         // connect client to me
     257       57879 :         pDepend->pRegisteredIn = this;
     258             :     }
     259       61604 : }
     260             : 
     261       49953 : SwClient* SwModify::Remove( SwClient* pDepend )
     262             : {
     263       49953 :     if ( bInDocDTOR )
     264           0 :         return 0;
     265             : 
     266             :     OSL_ENSURE( !bLockClientList || pDepend->mbIsAllowedToBeRemovedInModifyCall, "SwClient shall be removed in Modify call!" );
     267             : 
     268       49953 :     if( pDepend->pRegisteredIn == this )
     269             :     {
     270             :         // SwClient is my listener
     271             :         // remove it from my list
     272       49953 :         SwClient* pR = pDepend->pRight;
     273       49953 :         SwClient* pL = pDepend->pLeft;
     274       49953 :         if( pRoot == pDepend )
     275       32670 :             pRoot = pL ? pL : pR;
     276             : 
     277       49953 :         if( pL )
     278       17283 :             pL->pRight = pR;
     279       49953 :         if( pR )
     280       19451 :             pR->pLeft = pL;
     281             : 
     282             :         // update ClientIters
     283       49953 :         SwClientIter* pTmp = pClientIters;
     284      108822 :         while( pTmp )
     285             :         {
     286        8916 :             if( pTmp->pAct == pDepend || pTmp->pDelNext == pDepend )
     287             :             {
     288             :                 // if object being removed is the current or next object in an
     289             :                 // iterator, advance this iterator
     290        7006 :                 pTmp->pDelNext = pR;
     291             :             }
     292        8916 :             pTmp = pTmp->pNxtIter;
     293             :         }
     294             : 
     295       49953 :         pDepend->pLeft = 0;
     296       49953 :         pDepend->pRight = 0;
     297             :     }
     298             :     else
     299             :     {
     300             :         OSL_FAIL( "SwModify::Remove(): could not find pDepend" );
     301             :     }
     302             : 
     303             :     // disconnect client from me
     304       49953 :     pDepend->pRegisteredIn = 0;
     305       49953 :     return pDepend;
     306             : }
     307             : 
     308         527 : void SwModify::CheckCaching( const sal_uInt16 nWhich )
     309             : {
     310         527 :     if( isCHRATR( nWhich ) )
     311             :     {
     312           0 :         SetInSwFntCache( sal_False );
     313             :     }
     314             :     else
     315             :     {
     316         527 :         switch( nWhich )
     317             :         {
     318             :         case RES_OBJECTDYING:
     319             :         case RES_FMT_CHG:
     320             :         case RES_ATTRSET_CHG:
     321         304 :             SetInSwFntCache( sal_False );
     322             : 
     323             :         case RES_UL_SPACE:
     324             :         case RES_LR_SPACE:
     325             :         case RES_BOX:
     326             :         case RES_SHADOW:
     327             :         case RES_FRM_SIZE:
     328             :         case RES_KEEP:
     329             :         case RES_BREAK:
     330         305 :             if( IsInCache() )
     331             :             {
     332         234 :                 SwFrm::GetCache().Delete( this );
     333         234 :                 SetInCache( sal_False );
     334             :             }
     335         305 :             break;
     336             :         }
     337             :     }
     338         527 : }
     339             : 
     340         474 : void SwModify::CallSwClientNotify( const SfxHint& rHint ) const
     341             : {
     342         474 :     SwClientIter aIter(*this);
     343         474 :     SwClient* pClient = aIter.GoStart();
     344        1009 :     while( pClient )
     345             :     {
     346          61 :         pClient->SwClientNotify( *this, rHint );
     347          61 :         pClient = ++aIter;
     348         474 :     }
     349         474 : }
     350             : 
     351       42074 : void SwModify::ModifyBroadcast( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue, TypeId nType )
     352             : {
     353       42074 :     SwClientIter aIter( *this );
     354       42074 :     SwClient* pClient = aIter.First( nType );
     355      159380 :     while( pClient )
     356             :     {
     357       75232 :         pClient->Modify( pOldValue, pNewValue );
     358       75232 :         pClient = aIter.Next();
     359       42074 :     }
     360       42074 : }
     361             : 
     362             : // ----------
     363             : // SwDepend
     364             : // ----------
     365             : 
     366        7063 : SwDepend::SwDepend( SwClient* pTellHim, SwModify* pDepend )
     367        7063 :     : SwClient( pDepend )
     368             : {
     369        7063 :     pToTell  = pTellHim;
     370        7063 : }
     371             : 
     372          32 : void SwDepend::Modify( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue )
     373             : {
     374          32 :     if( pNewValue && pNewValue->Which() == RES_OBJECTDYING )
     375           0 :         CheckRegistration(pOldValue,pNewValue);
     376          32 :     else if( pToTell )
     377          32 :         pToTell->ModifyNotification(pOldValue, pNewValue);
     378          32 : }
     379             : 
     380           0 : void SwDepend::SwClientNotify( const SwModify& rMod, const SfxHint& rHint )
     381             : {
     382           0 :     if ( pToTell )
     383           0 :         pToTell->SwClientNotifyCall( rMod, rHint );
     384           0 : }
     385             : 
     386           0 : bool SwDepend::GetInfo( SfxPoolItem& rInfo ) const
     387             : {
     388           0 :     return pToTell ? pToTell->GetInfo( rInfo ) : true;
     389             : }
     390             : 
     391             : // ------------
     392             : // SwClientIter
     393             : // ------------
     394             : 
     395       85051 : SwClientIter::SwClientIter( const SwModify& rModify )
     396       85051 :     : rRoot( rModify )
     397             : {
     398       85051 :     pNxtIter = 0;
     399       85051 :     if( pClientIters )
     400             :     {
     401             :         // append to list of ClientIters
     402       15372 :         SwClientIter* pTmp = pClientIters;
     403       41277 :         while( pTmp->pNxtIter )
     404       10533 :             pTmp = pTmp->pNxtIter;
     405       15372 :         pTmp->pNxtIter = this;
     406             :     }
     407             :     else
     408       69679 :         pClientIters = this;
     409             : 
     410       85051 :     pAct = const_cast<SwClient*>(rRoot.GetDepends());
     411       85051 :     pDelNext = pAct;
     412       85051 : }
     413             : 
     414             : 
     415             : 
     416       85051 : SwClientIter::~SwClientIter()
     417             : {
     418       85051 :     if( pClientIters )
     419             :     {
     420             :         // reorganize list of ClientIters
     421       85051 :         if( pClientIters == this )
     422       69679 :             pClientIters = pNxtIter;
     423             :         else
     424             :         {
     425       15372 :             SwClientIter* pTmp = pClientIters;
     426       41277 :             while( pTmp->pNxtIter != this )
     427       10533 :                 if( 0 == ( pTmp = pTmp->pNxtIter ) )
     428             :                 {
     429             :                     OSL_ENSURE( this, "Lost my pointer" );
     430           0 :                     return ;
     431             :                 }
     432       15372 :             pTmp->pNxtIter = pNxtIter;
     433             :         }
     434             :     }
     435       85051 : }
     436             : 
     437        1480 : SwClient* SwClientIter::operator++()
     438             : {
     439        1480 :     if( pDelNext == pAct )
     440             :     {
     441        1480 :         pAct = pAct->pRight;
     442        1480 :         pDelNext = pAct;
     443             :     }
     444             :     else
     445           0 :         pAct = pDelNext;
     446        1480 :     return pAct;
     447             : }
     448             : 
     449       84986 : SwClient* SwClientIter::GoStart()
     450             : {
     451       84986 :     pAct = const_cast<SwClient*>(rRoot.GetDepends());
     452       84986 :     if( pAct )
     453             :     {
     454      146898 :         while( pAct->pLeft )
     455           0 :             pAct = pAct->pLeft;
     456             :     }
     457       84986 :     pDelNext = pAct;
     458       84986 :     return pAct;
     459             : }
     460             : 
     461          25 : SwClient* SwClientIter::GoEnd()
     462             : {
     463          25 :     pAct = pDelNext;
     464          25 :     if( !pAct )
     465          25 :         pAct = const_cast<SwClient*>(rRoot.GetDepends());
     466          25 :     if( pAct )
     467             :     {
     468           0 :         while( pAct->pRight )
     469           0 :             pAct = pAct->pRight;
     470             :     }
     471          25 :     pDelNext = pAct;
     472          25 :     return pAct;
     473             : }
     474             : 
     475       82670 : SwClient* SwClientIter::First( TypeId nType )
     476             : {
     477       82670 :     aSrchId = nType;
     478       82670 :     GoStart();
     479       82670 :     if( pAct )
     480       20552 :         do {
     481       89213 :             if( pAct->IsA( aSrchId ) )
     482       68661 :                 break;
     483             : 
     484       20552 :             if( pDelNext == pAct )
     485             :             {
     486       20552 :                 pAct = pAct->pRight;
     487       20552 :                 pDelNext = pAct;
     488             :             }
     489             :             else
     490           0 :                 pAct = pDelNext;
     491             :         } while( pAct );
     492       82670 :     return pAct;
     493             : }
     494             : 
     495          25 : SwClient* SwClientIter::Last( TypeId nType )
     496             : {
     497          25 :     aSrchId = nType;
     498          25 :     GoEnd();
     499          25 :     if( pAct )
     500           0 :         do {
     501           0 :             if( pAct->IsA( aSrchId ) )
     502           0 :                 break;
     503             : 
     504           0 :             if( pDelNext == pAct )
     505           0 :                 pAct = pAct->pLeft;
     506             :             else
     507           0 :                 pAct = pDelNext->pLeft;
     508           0 :             pDelNext = pAct;
     509             :         } while( pAct );
     510          25 :     return pAct;
     511             : }
     512             : 
     513       84233 : SwClient* SwClientIter::Next()
     514             : {
     515       50958 :     do {
     516       84233 :         if( pDelNext == pAct )
     517             :         {
     518       77227 :             pAct = pAct->pRight;
     519       77227 :             pDelNext = pAct;
     520             :         }
     521             :         else
     522        7006 :             pAct = pDelNext;
     523             : 
     524       84233 :         if( pAct && pAct->IsA( aSrchId ) )
     525       33275 :             break;
     526             :     } while( pAct );
     527       80813 :     return pAct;
     528             : }
     529             : 
     530           0 : SwClient* SwClientIter::Previous()
     531             : {
     532           0 :     do {
     533           0 :         if( pDelNext == pAct )
     534           0 :             pAct = pAct->pLeft;
     535             :         else
     536           0 :             pAct = pDelNext->pLeft;
     537           0 :         pDelNext = pAct;
     538             : 
     539           0 :         if( pAct && pAct->IsA( aSrchId ) )
     540           0 :             break;
     541             :     } while( pAct );
     542           0 :     return pAct;
     543             : }
     544             : 
     545             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10