LCOV - code coverage report
Current view: top level - sfx2/source/control - bindings.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 653 964 67.7 %
Date: 2015-06-13 12:38:46 Functions: 55 80 68.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 <sal/config.h>
      21             : 
      22             : #include <iomanip>
      23             : 
      24             : #include <sal/log.hxx>
      25             : #include <svl/itempool.hxx>
      26             : #include <svl/itemiter.hxx>
      27             : #include <svl/eitem.hxx>
      28             : #include <svl/aeitem.hxx>
      29             : #include <svl/intitem.hxx>
      30             : #include <svl/stritem.hxx>
      31             : #include <svl/visitem.hxx>
      32             : #include <com/sun/star/util/URLTransformer.hpp>
      33             : #include <com/sun/star/util/XURLTransformer.hpp>
      34             : #include <com/sun/star/frame/XDispatchProviderInterceptor.hpp>
      35             : #include <com/sun/star/frame/XDispatch.hpp>
      36             : #include <com/sun/star/frame/XDispatchProvider.hpp>
      37             : #include <com/sun/star/frame/XStatusListener.hpp>
      38             : #include <com/sun/star/frame/FrameSearchFlag.hpp>
      39             : #include <com/sun/star/frame/XDispatchProviderInterception.hpp>
      40             : #include <com/sun/star/frame/FeatureStateEvent.hpp>
      41             : #include <com/sun/star/frame/DispatchDescriptor.hpp>
      42             : #include <com/sun/star/frame/XController.hpp>
      43             : #include <comphelper/processfactory.hxx>
      44             : #include "itemdel.hxx"
      45             : 
      46             : //Includes below due to nInReschedule
      47             : #include "appdata.hxx"
      48             : #include <sfx2/bindings.hxx>
      49             : #include <sfx2/msg.hxx>
      50             : #include "statcach.hxx"
      51             : #include <sfx2/ctrlitem.hxx>
      52             : #include <sfx2/app.hxx>
      53             : #include <sfx2/dispatch.hxx>
      54             : #include <sfx2/request.hxx>
      55             : #include <sfx2/objface.hxx>
      56             : #include "sfxtypes.hxx"
      57             : #include "workwin.hxx"
      58             : #include <sfx2/unoctitm.hxx>
      59             : #include <sfx2/sfx.hrc>
      60             : #include <sfx2/sfxuno.hxx>
      61             : #include <sfx2/viewfrm.hxx>
      62             : #include <sfx2/objsh.hxx>
      63             : #include <sfx2/msgpool.hxx>
      64             : 
      65             : #include <com/sun/star/frame/XModuleManager.hpp>
      66             : #include <boost/scoped_array.hpp>
      67             : #include <boost/scoped_ptr.hpp>
      68             : #include <boost/ptr_container/ptr_vector.hpp>
      69             : #include <unordered_map>
      70             : 
      71             : using namespace ::com::sun::star;
      72             : using namespace ::com::sun::star::uno;
      73             : using namespace ::com::sun::star::util;
      74             : 
      75             : static sal_uInt16 nTimeOut = 300;
      76             : 
      77             : #define TIMEOUT_FIRST       nTimeOut
      78             : #define TIMEOUT_UPDATING     20
      79             : #define TIMEOUT_IDLE       2500
      80             : 
      81             : typedef std::unordered_map< sal_uInt16, bool > InvalidateSlotMap;
      82             : 
      83             : 
      84             : 
      85             : typedef std::vector<SfxStateCache*> SfxStateCacheArr_Impl;
      86             : 
      87             : struct SfxFoundCache_Impl
      88             : {
      89             :     sal_uInt16      nSlotId;   // the Slot-Id
      90             :     sal_uInt16      nWhichId;  // If available: Which-Id, else: nSlotId
      91             :     const SfxSlot*  pSlot;     // Pointer to <Master-Slot>
      92             :     SfxStateCache*  pCache;    // Pointer to StatusCache, if possible NULL
      93             : 
      94       97995 :     SfxFoundCache_Impl(sal_uInt16 nS, sal_uInt16 nW, const SfxSlot *pS, SfxStateCache *pC ):
      95             :         nSlotId(nS),
      96             :         nWhichId(nW),
      97             :         pSlot(pS),
      98       97995 :         pCache(pC)
      99       97995 :     {}
     100             : };
     101             : 
     102       51516 : class SfxFoundCacheArr_Impl
     103             : {
     104             :     typedef boost::ptr_vector<SfxFoundCache_Impl> DataType;
     105             :     DataType maData;
     106             : 
     107             : public:
     108             : 
     109      482822 :     SfxFoundCache_Impl& operator[] ( size_t i )
     110             :     {
     111      482822 :         return maData[i];
     112             :     }
     113             : 
     114      337075 :     size_t size() const
     115             :     {
     116      337075 :         return maData.size();
     117             :     }
     118             : 
     119       96153 :     void push_back( SfxFoundCache_Impl* p )
     120             :     {
     121       96153 :         maData.push_back(p);
     122       96153 :     }
     123             : };
     124             : 
     125           0 : class SfxUnoControllerArr_Impl
     126             : {
     127             :     typedef std::vector<SfxUnoControllerItem*> DataType;
     128             :     DataType maData;
     129             : 
     130             : public:
     131             : 
     132             :     typedef DataType::iterator iterator;
     133             : 
     134           0 :     iterator begin()
     135             :     {
     136           0 :         return maData.begin();
     137             :     }
     138             : 
     139           0 :     iterator end()
     140             :     {
     141           0 :         return maData.end();
     142             :     }
     143             : 
     144           0 :     void erase( iterator it )
     145             :     {
     146           0 :         maData.erase(it);
     147           0 :     }
     148             : 
     149           0 :     SfxUnoControllerItem* operator[] ( size_t i )
     150             :     {
     151           0 :         return maData[i];
     152             :     }
     153             : 
     154           0 :     size_t size() const
     155             :     {
     156           0 :         return maData.size();
     157             :     }
     158             : 
     159           0 :     void push_back( SfxUnoControllerItem* p )
     160             :     {
     161           0 :         maData.push_back(p);
     162           0 :     }
     163             : };
     164             : 
     165           0 : class SfxAsyncExec_Impl
     166             : {
     167             :     ::com::sun::star::util::URL aCommand;
     168             :     ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > xDisp;
     169             :     Timer           aTimer;
     170             : 
     171             : public:
     172             : 
     173           0 :     SfxAsyncExec_Impl( const ::com::sun::star::util::URL& rCmd, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch >& rDisp )
     174             :         : aCommand( rCmd )
     175           0 :         , xDisp( rDisp )
     176             :     {
     177           0 :         aTimer.SetTimeoutHdl( LINK(this, SfxAsyncExec_Impl, TimerHdl) );
     178           0 :         aTimer.SetTimeout( 0 );
     179           0 :         aTimer.Start();
     180           0 :     }
     181             : 
     182             :     DECL_LINK_TYPED( TimerHdl, Timer*, void);
     183             : };
     184             : 
     185           0 : IMPL_LINK_TYPED(SfxAsyncExec_Impl, TimerHdl, Timer*, pTimer, void)
     186             : {
     187             :     (void)pTimer; // unused
     188           0 :     aTimer.Stop();
     189             : 
     190           0 :     Sequence<beans::PropertyValue> aSeq;
     191           0 :     xDisp->dispatch( aCommand, aSeq );
     192             : 
     193           0 :     delete this;
     194           0 : }
     195             : 
     196             : enum class SfxPopupAction
     197             : {
     198             :     DELETE,
     199             :     HIDE,
     200             :     SHOW
     201             : };
     202             : 
     203             : 
     204        6501 : class SfxBindings_Impl
     205             : {
     206             : public:
     207             :     ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchRecorder > xRecorder;
     208             :     ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider >  xProv;
     209             :     SfxUnoControllerArr_Impl*
     210             :                             pUnoCtrlArr;
     211             :     SfxWorkWindow*          pWorkWin;
     212             :     SfxBindings*            pSubBindings;
     213             :     SfxBindings*            pSuperBindings;
     214             :     SfxStateCacheArr_Impl*  pCaches;        // One chache for each binding
     215             :     sal_uInt16              nCachedFunc1;   // index for the last one called
     216             :     sal_uInt16              nCachedFunc2;   // index for the second last called
     217             :     sal_uInt16              nMsgPos;        // Message-Position relative the one to be updated
     218             :     SfxPopupAction          ePopupAction;   // Checked in DeleteFloatinWindow()
     219             :     bool                    bContextChanged;
     220             :     bool                    bMsgDirty;      // Has a MessageServer been invalidated?
     221             :     bool                    bAllMsgDirty;   //  Has a MessageServer been invalidated?
     222             :     bool                    bAllDirty;      // After InvalidateAll
     223             :     bool                    bCtrlReleased;  // while EnterRegistrations
     224             :     AutoTimer               aTimer;         // for volatile Slots
     225             :     bool                    bInUpdate;      // for Assertions
     226             :     bool                    bInNextJob;     // for Assertions
     227             :     bool                    bFirstRound;    // First round in Update
     228             :     sal_uInt16              nFirstShell;    // Shell, the first round is preferred
     229             :     sal_uInt16              nOwnRegLevel;   // Counts the real Locks, except those of the Super Bindings
     230             :     InvalidateSlotMap       m_aInvalidateSlots; // store slots which are invalidated while in update
     231             : };
     232             : 
     233        3254 : SfxBindings::SfxBindings()
     234        3254 : :   pImp(new SfxBindings_Impl),
     235             :     pDispatcher(0),
     236        6508 :     nRegLevel(1)    // first becomes 0, when the Dispatcher is set
     237             : {
     238        3254 :     pImp->nMsgPos = 0;
     239        3254 :     pImp->bAllMsgDirty = true;
     240        3254 :     pImp->bContextChanged = false;
     241        3254 :     pImp->bMsgDirty = true;
     242        3254 :     pImp->bAllDirty = true;
     243        3254 :     pImp->ePopupAction = SfxPopupAction::DELETE;
     244        3254 :     pImp->nCachedFunc1 = 0;
     245        3254 :     pImp->nCachedFunc2 = 0;
     246        3254 :     pImp->bCtrlReleased = false;
     247        3254 :     pImp->bFirstRound = false;
     248        3254 :     pImp->bInNextJob = false;
     249        3254 :     pImp->bInUpdate = false;
     250        3254 :     pImp->pSubBindings = NULL;
     251        3254 :     pImp->pSuperBindings = NULL;
     252        3254 :     pImp->pWorkWin = NULL;
     253        3254 :     pImp->pUnoCtrlArr = NULL;
     254        3254 :     pImp->nOwnRegLevel = nRegLevel;
     255             : 
     256             :     // all caches are valid (no pending invalidate-job)
     257             :     // create the list of caches
     258        3254 :     pImp->pCaches = new SfxStateCacheArr_Impl;
     259        3254 :     pImp->aTimer.SetTimeoutHdl( LINK(this, SfxBindings, NextJob) );
     260        3254 : }
     261             : 
     262             : 
     263             : 
     264        9737 : SfxBindings::~SfxBindings()
     265             : 
     266             : /*  [Description]
     267             : 
     268             :     Destructor of the SfxBindings class. The one, for each <SfxApplication>
     269             :     existing Instance is automatically destroyed by the <SfxApplication>
     270             :     after the execution of <SfxApplication::Exit()>.
     271             : 
     272             :     The still existing <SfxControllerItem> instances, which are registered
     273             :     by the SfxBindings instance, are automatically destroyed in the Destructor.
     274             :     These are usually the Floating-Toolboxen, Value-Sets
     275             :     etc. Arrays of SfxControllerItems may at this time no longer exist.
     276             : */
     277             : 
     278             : {
     279             :     // The SubBindings should not be locked!
     280        3247 :     pImp->pSubBindings = NULL;
     281             : 
     282        3247 :     ENTERREGISTRATIONS();
     283             : 
     284        3247 :     pImp->aTimer.Stop();
     285        3247 :     DeleteControllers_Impl();
     286             : 
     287             :     // Delete Caches
     288        3247 :     for(SfxStateCacheArr_Impl::const_iterator it = pImp->pCaches->begin(); it != pImp->pCaches->end(); ++it)
     289           0 :         delete *it;
     290             : 
     291        3247 :     DELETEZ( pImp->pWorkWin );
     292             : 
     293        3247 :     delete pImp->pCaches;
     294        3247 :     delete pImp;
     295        6490 : }
     296             : 
     297             : 
     298             : 
     299        3247 : void SfxBindings::DeleteControllers_Impl()
     300             : {
     301             :     // in the first round delete SfxPopupWindows
     302        3247 :     sal_uInt16 nCount = pImp->pCaches->size();
     303             :     sal_uInt16 nCache;
     304      115155 :     for ( nCache = 0; nCache < nCount; ++nCache )
     305             :     {
     306             :         // Remember were you are
     307      111908 :         SfxStateCache *pCache = (*pImp->pCaches)[nCache];
     308      111908 :         sal_uInt16 nSlotId = pCache->GetId();
     309             : 
     310             :         // Re-align, because the cache may have been reduced
     311      111908 :         sal_uInt16 nNewCount = pImp->pCaches->size();
     312      111908 :         if ( nNewCount < nCount )
     313             :         {
     314           0 :             nCache = GetSlotPos(nSlotId);
     315           0 :             if ( nCache >= nNewCount ||
     316           0 :                  nSlotId != (*pImp->pCaches)[nCache]->GetId() )
     317           0 :                 --nCache;
     318           0 :             nCount = nNewCount;
     319             :         }
     320             :     }
     321             : 
     322             :     // Delete all Caches
     323      115155 :     for ( nCache = pImp->pCaches->size(); nCache > 0; --nCache )
     324             :     {
     325             :         // Get Cache via ::com::sun::star::sdbcx::Index
     326      111908 :         SfxStateCache *pCache = (*pImp->pCaches)[ nCache-1 ];
     327             : 
     328             :         // unbind all controllers in the cache
     329             :         SfxControllerItem *pNext;
     330      111924 :         for ( SfxControllerItem *pCtrl = pCache->GetItemLink();
     331             :               pCtrl; pCtrl = pNext )
     332             :         {
     333          16 :             pNext = pCtrl->GetItemLink();
     334          16 :             pCtrl->UnBind();
     335             :         }
     336             : 
     337      111908 :         if ( pCache->GetInternalController() )
     338       80183 :             pCache->GetInternalController()->UnBind();
     339             : 
     340             :         // Delete Cache
     341      111908 :         if( nCache-1 < (sal_uInt16) pImp->pCaches->size() )
     342      111908 :             delete (*pImp->pCaches)[nCache-1];
     343      111908 :         pImp->pCaches->erase(pImp->pCaches->begin()+ nCache - 1);
     344             :     }
     345             : 
     346        3247 :     if( pImp->pUnoCtrlArr )
     347             :     {
     348           0 :         sal_uInt16 nCtrlCount = pImp->pUnoCtrlArr->size();
     349           0 :         for ( sal_uInt16 n=nCtrlCount; n>0; n-- )
     350             :         {
     351           0 :             SfxUnoControllerItem *pCtrl = (*pImp->pUnoCtrlArr)[n-1];
     352           0 :             pCtrl->ReleaseBindings();
     353             :         }
     354             : 
     355             :         DBG_ASSERT( !pImp->pUnoCtrlArr->size(), "Do not remove UnoControllerItems!" );
     356           0 :         DELETEZ( pImp->pUnoCtrlArr );
     357             :     }
     358        3247 : }
     359             : 
     360             : 
     361             : 
     362           2 : void SfxBindings::HidePopups( bool bHide )
     363             : {
     364             :     // Hide SfxPopupWindows
     365           2 :     HidePopupCtrls_Impl( bHide );
     366           2 :     SfxBindings *pSub = pImp->pSubBindings;
     367           4 :     while ( pSub )
     368             :     {
     369           0 :         pImp->pSubBindings->HidePopupCtrls_Impl( bHide );
     370           0 :         pSub = pSub->pImp->pSubBindings;
     371             :     }
     372             : 
     373             :     // Hide SfxChildWindows
     374             :     DBG_ASSERT( pDispatcher, "HidePopups not allowed without dispatcher" );
     375           2 :     if ( pImp->pWorkWin )
     376           2 :         pImp->pWorkWin->HidePopups_Impl( bHide, true );
     377           2 : }
     378             : 
     379        6295 : void SfxBindings::HidePopupCtrls_Impl( bool bHide )
     380             : {
     381        6295 :     if ( bHide )
     382             :     {
     383             :         // Hide SfxPopupWindows
     384        3146 :         pImp->ePopupAction = SfxPopupAction::HIDE;
     385             :     }
     386             :     else
     387             :     {
     388             :         // Show SfxPopupWindows
     389        3149 :         pImp->ePopupAction = SfxPopupAction::SHOW;
     390             :     }
     391             : 
     392        6295 :     pImp->ePopupAction = SfxPopupAction::DELETE;
     393        6295 : }
     394             : 
     395             : 
     396             : 
     397       25758 : void SfxBindings::Update_Impl
     398             : (
     399             :     SfxStateCache*  pCache      // The up to date SfxStatusCache
     400             : )
     401             : {
     402       25758 :     if( pCache->GetDispatch().is() && pCache->GetItemLink() )
     403             :     {
     404           0 :         pCache->SetCachedState(true);
     405           0 :         if ( !pCache->GetInternalController() )
     406           0 :             return;
     407             :     }
     408             : 
     409       25758 :     if ( !pDispatcher )
     410           0 :         return;
     411             : 
     412             :     // gather together all with the same status method which are dirty
     413       25758 :     SfxDispatcher &rDispat = *pDispatcher;
     414       25758 :     const SfxSlot *pRealSlot = 0;
     415       25758 :     const SfxSlotServer* pMsgServer = 0;
     416       25758 :     SfxFoundCacheArr_Impl aFound;
     417       25758 :     SfxItemSet *pSet = CreateSet_Impl( pCache, pRealSlot, &pMsgServer, aFound );
     418       25758 :     bool bUpdated = false;
     419       25758 :     if ( pSet )
     420             :     {
     421             :         // Query Status
     422       23916 :         if ( rDispat._FillState( *pMsgServer, *pSet, pRealSlot ) )
     423             :         {
     424             :             // Post Status
     425             :             const SfxInterface *pInterface =
     426       23916 :                 rDispat.GetShell(pMsgServer->GetShellLevel())->GetInterface();
     427      120069 :             for ( size_t nPos = 0; nPos < aFound.size(); ++nPos )
     428             :             {
     429       96153 :                 const SfxFoundCache_Impl& rFound = aFound[nPos];
     430       96153 :                 sal_uInt16 nWhich = rFound.nWhichId;
     431       96153 :                 const SfxPoolItem *pItem = 0;
     432       96153 :                 SfxItemState eState = pSet->GetItemState(nWhich, true, &pItem);
     433       96153 :                 if ( eState == SfxItemState::DEFAULT && SfxItemPool::IsWhich(nWhich) )
     434        5078 :                     pItem = &pSet->Get(nWhich);
     435       96153 :                 UpdateControllers_Impl( pInterface, aFound[nPos], pItem, eState );
     436             :             }
     437       23916 :             bUpdated = true;
     438             :         }
     439             : 
     440       23916 :         delete pSet;
     441             :     }
     442             : 
     443       25758 :     if ( !bUpdated && pCache )
     444             :     {
     445             :         // When pCache == NULL and no SlotServer
     446             :         // (for example due to locked Dispatcher! ),
     447             :         // obviously do not try to update
     448             :         SfxFoundCache_Impl aFoundCache(
     449        1842 :                             pCache->GetId(), 0,
     450        3684 :                             pRealSlot, pCache );
     451        1842 :         UpdateControllers_Impl( 0, aFoundCache, 0, SfxItemState::DISABLED);
     452       25758 :     }
     453             : }
     454             : 
     455             : 
     456             : 
     457        1476 : void SfxBindings::InvalidateSlotsInMap_Impl()
     458             : {
     459        1476 :     InvalidateSlotMap::const_iterator pIter = pImp->m_aInvalidateSlots.begin();
     460        2952 :     while ( pIter != pImp->m_aInvalidateSlots.end() )
     461             :     {
     462           0 :         Invalidate( pIter->first );
     463           0 :         ++pIter;
     464             :     }
     465        1476 :     pImp->m_aInvalidateSlots.clear();
     466        1476 : }
     467             : 
     468             : 
     469             : 
     470           0 : void SfxBindings::AddSlotToInvalidateSlotsMap_Impl( sal_uInt16 nId )
     471             : {
     472           0 :     pImp->m_aInvalidateSlots[nId] = true;
     473           0 : }
     474             : 
     475             : 
     476             : 
     477        2593 : void SfxBindings::Update
     478             : (
     479             :     sal_uInt16      nId     // the bound and up-to-date Slot-Id
     480             : )
     481             : {
     482             :     DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
     483             : 
     484        2593 :     if ( pDispatcher )
     485        2593 :         pDispatcher->Flush();
     486             : 
     487        2593 :     if ( pImp->pSubBindings )
     488           0 :         pImp->pSubBindings->Update( nId );
     489             : 
     490        2593 :     SfxStateCache* pCache = GetStateCache( nId );
     491        2593 :     if ( pCache )
     492             :     {
     493        1476 :         pImp->bInUpdate = true;
     494        1476 :         if ( pImp->bMsgDirty )
     495             :         {
     496         342 :             UpdateSlotServer_Impl();
     497         342 :             pCache = GetStateCache( nId );
     498             :         }
     499             : 
     500        1476 :         if (pCache)
     501             :         {
     502        1476 :             bool bInternalUpdate = true;
     503        1476 :             if( pCache->GetDispatch().is() && pCache->GetItemLink() )
     504             :             {
     505           0 :                 pCache->SetCachedState(true);
     506           0 :                 bInternalUpdate = ( pCache->GetInternalController() != 0 );
     507             :             }
     508             : 
     509        1476 :             if ( bInternalUpdate )
     510             :             {
     511             :                 // Query Status
     512        1476 :                 const SfxSlotServer* pMsgServer = pDispatcher ? pCache->GetSlotServer(*pDispatcher, pImp->xProv) : NULL;
     513        1917 :                 if ( !pCache->IsControllerDirty() &&
     514         441 :                     ( !pMsgServer ||
     515         441 :                     !pMsgServer->GetSlot()->IsMode(SfxSlotMode::VOLATILE) ) )
     516             :                 {
     517         441 :                     pImp->bInUpdate = false;
     518         441 :                     InvalidateSlotsInMap_Impl();
     519         441 :                     return;
     520             :                 }
     521        1035 :                 if (!pMsgServer)
     522             :                 {
     523           0 :                     pCache->SetState(SfxItemState::DISABLED, 0);
     524           0 :                     pImp->bInUpdate = false;
     525           0 :                     InvalidateSlotsInMap_Impl();
     526           0 :                     return;
     527             :                 }
     528             : 
     529        1035 :                 Update_Impl(pCache);
     530             :             }
     531             : 
     532        1035 :             pImp->bAllDirty = false;
     533             :         }
     534             : 
     535        1035 :         pImp->bInUpdate = false;
     536        1035 :         InvalidateSlotsInMap_Impl();
     537             :     }
     538             : }
     539             : 
     540             : 
     541             : 
     542           0 : void SfxBindings::Update()
     543             : {
     544             :     DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
     545             : 
     546           0 :     if ( pImp->pSubBindings )
     547           0 :         pImp->pSubBindings->Update();
     548             : 
     549           0 :     if ( pDispatcher )
     550             :     {
     551           0 :         if ( nRegLevel )
     552           0 :             return;
     553             : 
     554           0 :         pImp->bInUpdate = true;
     555           0 :         pDispatcher->Flush();
     556           0 :         pDispatcher->Update_Impl();
     557           0 :         while ( !NextJob_Impl(0) )
     558             :             ; // loop
     559           0 :         pImp->bInUpdate = false;
     560           0 :         InvalidateSlotsInMap_Impl();
     561             :     }
     562             : }
     563             : 
     564             : 
     565             : 
     566           2 : void SfxBindings::SetState
     567             : (
     568             :     const SfxItemSet&   rSet    // status values to be set
     569             : )
     570             : {
     571             :     // when locked then only invalidate
     572           2 :     if ( nRegLevel )
     573             :     {
     574           0 :         SfxItemIter aIter(rSet);
     575           0 :         for ( const SfxPoolItem *pItem = aIter.FirstItem();
     576             :               pItem;
     577             :               pItem = aIter.NextItem() )
     578           0 :             Invalidate( pItem->Which() );
     579             :     }
     580             :     else
     581             :     {
     582             :         // Status may be accepted only if all slot-pointers are set
     583           2 :         if ( pImp->bMsgDirty )
     584           1 :             UpdateSlotServer_Impl();
     585             : 
     586             :         // Iterate over the itemset, update if the slot bound
     587             :         //! Bug: Use WhichIter and possibly send VoidItems up
     588           2 :         SfxItemIter aIter(rSet);
     589           8 :         for ( const SfxPoolItem *pItem = aIter.FirstItem();
     590             :               pItem;
     591             :               pItem = aIter.NextItem() )
     592             :         {
     593             :             SfxStateCache* pCache =
     594           6 :                     GetStateCache( rSet.GetPool()->GetSlotId(pItem->Which()) );
     595           6 :             if ( pCache )
     596             :             {
     597             :                 // Update status
     598           0 :                 if ( !pCache->IsControllerDirty() )
     599           0 :                     pCache->Invalidate(false);
     600           0 :                 pCache->SetState( SfxItemState::DEFAULT, pItem );
     601             : 
     602             :                 //! Not implemented: Updates from EnumSlots via master slots
     603             :             }
     604           2 :         }
     605             :     }
     606           2 : }
     607             : 
     608             : 
     609             : 
     610        1238 : void SfxBindings::SetState
     611             : (
     612             :     const SfxPoolItem&  rItem   // Status value to be set
     613             : )
     614             : {
     615        1238 :     if ( nRegLevel )
     616             :     {
     617          44 :         Invalidate( rItem.Which() );
     618             :     }
     619             :     else
     620             :     {
     621             :         // Status may be accepted only if all slot-pointers are set
     622        1194 :         if ( pImp->bMsgDirty )
     623         256 :             UpdateSlotServer_Impl();
     624             : 
     625             :         //update if the slot bound
     626             :         DBG_ASSERT( SfxItemPool::IsSlot( rItem.Which() ),
     627             :                     "cannot set items with which-id" );
     628        1194 :         SfxStateCache* pCache = GetStateCache( rItem.Which() );
     629        1194 :         if ( pCache )
     630             :         {
     631             :             // Update Status
     632         102 :             if ( !pCache->IsControllerDirty() )
     633          60 :                 pCache->Invalidate(false);
     634         102 :             pCache->SetState( SfxItemState::DEFAULT, &rItem );
     635             : 
     636             :             //! Not implemented: Updates from EnumSlots via master slots
     637             :         }
     638             :     }
     639        1238 : }
     640             : 
     641             : 
     642             : 
     643             : 
     644           0 : SfxStateCache* SfxBindings::GetAnyStateCache_Impl( sal_uInt16 nId )
     645             : {
     646           0 :     SfxStateCache* pCache = GetStateCache( nId );
     647           0 :     if ( !pCache && pImp->pSubBindings )
     648           0 :         return pImp->pSubBindings->GetAnyStateCache_Impl( nId );
     649           0 :     return pCache;
     650             : }
     651             : 
     652      359952 : SfxStateCache* SfxBindings::GetStateCache
     653             : (
     654             :     sal_uInt16   nId   /*  Slot-Id, which SfxStatusCache is to be found */
     655             : )
     656             : {
     657      359952 :     return GetStateCache(nId, 0);
     658             : }
     659             : 
     660      785488 : SfxStateCache* SfxBindings::GetStateCache
     661             : (
     662             :     sal_uInt16   nId,   /*  Slot-Id, which SfxStatusCache is to be found */
     663             :     sal_uInt16*  pPos   /*  NULL for instance the position from which the
     664             :                            bindings are to be searched binary. Returns the
     665             :                            position back for where the nId was found,
     666             :                            or where it was inserted. */
     667             : )
     668             : {
     669             :     DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
     670             :     // is the specified function bound?
     671      785488 :     const sal_uInt16 nStart = ( pPos ? *pPos : 0 );
     672      785488 :     const sal_uInt16 nPos = GetSlotPos( nId, nStart );
     673             : 
     674     1531391 :     if ( nPos < pImp->pCaches->size() &&
     675      745903 :          (*pImp->pCaches)[nPos]->GetId() == nId )
     676             :     {
     677      316155 :         if ( pPos )
     678       78759 :             *pPos = nPos;
     679      316155 :         return (*pImp->pCaches)[nPos];
     680             :     }
     681      469333 :     return 0;
     682             : }
     683             : 
     684             : 
     685             : 
     686       59131 : void SfxBindings::InvalidateAll
     687             : (
     688             :     bool  bWithMsg  /* true   Mark Slot Server as invalid
     689             :                        false  Slot Server remains valid */
     690             : )
     691             : {
     692             :     DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
     693             : 
     694       59131 :     if ( pImp->pSubBindings )
     695          25 :         pImp->pSubBindings->InvalidateAll( bWithMsg );
     696             : 
     697             :     // everything is already set dirty or downing => nothing to do
     698      170908 :     if ( !pDispatcher ||
     699      112602 :          ( pImp->bAllDirty && ( !bWithMsg || pImp->bAllMsgDirty ) ) ||
     700        2434 :          SfxGetpApp()->IsDowning() )
     701             :     {
     702      115828 :         return;
     703             :     }
     704             : 
     705        2434 :     pImp->bAllMsgDirty = pImp->bAllMsgDirty || bWithMsg;
     706        2434 :     pImp->bMsgDirty = pImp->bMsgDirty || pImp->bAllMsgDirty || bWithMsg;
     707        2434 :     pImp->bAllDirty = true;
     708             : 
     709      267063 :     for ( size_t n = 0; n < pImp->pCaches->size(); ++n )
     710      264629 :         (*pImp->pCaches)[n]->Invalidate(bWithMsg);
     711             : 
     712        2434 :     pImp->nMsgPos = 0;
     713        2434 :     if ( !nRegLevel )
     714             :     {
     715        1268 :         pImp->aTimer.Stop();
     716        1268 :         pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
     717        1268 :         pImp->aTimer.Start();
     718             :     }
     719             : }
     720             : 
     721             : 
     722             : 
     723       33024 : void SfxBindings::Invalidate
     724             : (
     725             :     const sal_uInt16* pIds /* numerically sorted NULL-terminated array of
     726             :                               slot IDs (individual, not as a couple!) */
     727             : )
     728             : {
     729       33024 :     if ( pImp->bInUpdate )
     730             :     {
     731           0 :         sal_Int32 i = 0;
     732           0 :         while ( pIds[i] != 0 )
     733           0 :             AddSlotToInvalidateSlotsMap_Impl( pIds[i++] );
     734             : 
     735           0 :         if ( pImp->pSubBindings )
     736           0 :             pImp->pSubBindings->Invalidate( pIds );
     737           0 :         return;
     738             :     }
     739             : 
     740       33024 :     if ( pImp->pSubBindings )
     741           0 :         pImp->pSubBindings->Invalidate( pIds );
     742             : 
     743             :     // everything is already set dirty or downing => nothing to do
     744       33024 :     if ( !pDispatcher || pImp->bAllDirty || SfxGetpApp()->IsDowning() )
     745       32821 :         return;
     746             : 
     747             :     // Search binary in always smaller areas
     748        5376 :     for ( sal_uInt16 n = GetSlotPos(*pIds);
     749        2688 :           *pIds && n < pImp->pCaches->size();
     750        2485 :           n = GetSlotPos(*pIds, n) )
     751             :     {
     752             :         // If SID is ever bound, then invalidate the cache
     753        2688 :         SfxStateCache *pCache = (*pImp->pCaches)[n];
     754        2688 :         if ( pCache->GetId() == *pIds )
     755        2639 :             pCache->Invalidate(false);
     756             : 
     757             :         // Next SID
     758        2688 :         if ( !*++pIds )
     759         203 :             break;
     760             :         DBG_ASSERT( *pIds > *(pIds-1), "pIds unsorted" );
     761             :     }
     762             : 
     763             :     // if not enticed to start update timer
     764         203 :     pImp->nMsgPos = 0;
     765         203 :     if ( !nRegLevel )
     766             :     {
     767         203 :         pImp->aTimer.Stop();
     768         203 :         pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
     769         203 :         pImp->aTimer.Start();
     770             :     }
     771             : }
     772             : 
     773             : 
     774             : 
     775         643 : void SfxBindings::InvalidateShell
     776             : (
     777             :     const SfxShell&  rSh,  /* <SfxShell> whose Slot-Ids should be
     778             :                               invalidated */
     779             :     bool             bDeep /* true
     780             :                               also the SfxShell's inherited slot IDs are invalidated
     781             : 
     782             :                               false
     783             :                               the inherited and not overridden Slot-Ids are
     784             :                               invalidated */
     785             :                              // for now always bDeep
     786             : )
     787             : {
     788             :     DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
     789             : 
     790         643 :     if ( pImp->pSubBindings )
     791           0 :         pImp->pSubBindings->InvalidateShell( rSh, bDeep );
     792             : 
     793         643 :     if ( !pDispatcher || pImp->bAllDirty || SfxGetpApp()->IsDowning() )
     794         510 :         return;
     795             : 
     796             :     // flush now already, it is done in GetShellLevel (rsh) anyway,
     797             :     // important so that is set correctly: pimp-> ball(Msg)Dirty
     798         133 :     pDispatcher->Flush();
     799             : 
     800         133 :     if ((pImp->bAllDirty && pImp->bAllMsgDirty) || SfxGetpApp()->IsDowning())
     801             :     {
     802             :         // if the next one is anyway, then all the servers are collected
     803           0 :         return;
     804             :     }
     805             : 
     806             :     // Find Level
     807         133 :     sal_uInt16 nLevel = pDispatcher->GetShellLevel(rSh);
     808         133 :     if ( nLevel != USHRT_MAX )
     809             :     {
     810       13411 :         for ( size_t n = 0; n < pImp->pCaches->size(); ++n )
     811             :         {
     812       13278 :             SfxStateCache *pCache = (*pImp->pCaches)[n];
     813             :             const SfxSlotServer *pMsgServer =
     814       13278 :                 pCache->GetSlotServer(*pDispatcher, pImp->xProv);
     815       13278 :             if ( pMsgServer && pMsgServer->GetShellLevel() == nLevel )
     816       10576 :                 pCache->Invalidate(false);
     817             :         }
     818         133 :         pImp->nMsgPos = 0;
     819         133 :         if ( !nRegLevel )
     820             :         {
     821         133 :             pImp->aTimer.Stop();
     822         133 :             pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
     823         133 :             pImp->aTimer.Start();
     824         133 :             pImp->bFirstRound = true;
     825         133 :             pImp->nFirstShell = nLevel;
     826             :         }
     827             :     }
     828             : }
     829             : 
     830             : 
     831             : 
     832      354201 : void SfxBindings::Invalidate
     833             : (
     834             :     sal_uInt16 nId              // Status value to be set
     835             : )
     836             : {
     837      354201 :     if ( pImp->bInUpdate )
     838             :     {
     839           0 :         AddSlotToInvalidateSlotsMap_Impl( nId );
     840           0 :         if ( pImp->pSubBindings )
     841           0 :             pImp->pSubBindings->Invalidate( nId );
     842           0 :         return;
     843             :     }
     844             : 
     845      354201 :     if ( pImp->pSubBindings )
     846          56 :         pImp->pSubBindings->Invalidate( nId );
     847             : 
     848      354201 :     if ( !pDispatcher || pImp->bAllDirty || SfxGetpApp()->IsDowning() )
     849      298176 :         return;
     850             : 
     851       56025 :     SfxStateCache* pCache = GetStateCache(nId);
     852       56025 :     if ( pCache )
     853             :     {
     854       10661 :         pCache->Invalidate(false);
     855       10661 :         pImp->nMsgPos = std::min(GetSlotPos(nId), pImp->nMsgPos);
     856       10661 :         if ( !nRegLevel )
     857             :         {
     858       10651 :             pImp->aTimer.Stop();
     859       10651 :             pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
     860       10651 :             pImp->aTimer.Start();
     861             :         }
     862             :     }
     863             : }
     864             : 
     865             : 
     866             : 
     867        2900 : void SfxBindings::Invalidate
     868             : (
     869             :     sal_uInt16  nId,                // Status value to be set
     870             :     bool        bWithItem,          // Clear StateCache?
     871             :     bool        bWithMsg            // Get new SlotServer?
     872             : )
     873             : {
     874             :     DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
     875             : 
     876        2900 :     if ( pImp->pSubBindings )
     877           0 :         pImp->pSubBindings->Invalidate( nId, bWithItem, bWithMsg );
     878             : 
     879        2900 :     if ( SfxGetpApp()->IsDowning() )
     880           0 :         return;
     881             : 
     882        2900 :     SfxStateCache* pCache = GetStateCache(nId);
     883        2900 :     if ( pCache )
     884             :     {
     885           9 :         if ( bWithItem )
     886           9 :             pCache->ClearCache();
     887           9 :         pCache->Invalidate(bWithMsg);
     888             : 
     889           9 :         if ( !pDispatcher || pImp->bAllDirty )
     890           4 :             return;
     891             : 
     892           5 :         pImp->nMsgPos = std::min(GetSlotPos(nId), pImp->nMsgPos);
     893           5 :         if ( !nRegLevel )
     894             :         {
     895           5 :             pImp->aTimer.Stop();
     896           5 :             pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
     897           5 :             pImp->aTimer.Start();
     898             :         }
     899             :     }
     900             : }
     901             : 
     902             : 
     903             : 
     904           0 : bool SfxBindings::IsBound( sal_uInt16 nSlotId, sal_uInt16 nStartSearchAt )
     905             : {
     906             :     DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
     907           0 :     return GetStateCache(nSlotId, &nStartSearchAt ) != 0;
     908             : }
     909             : 
     910             : 
     911             : 
     912     1142509 : sal_uInt16 SfxBindings::GetSlotPos( sal_uInt16 nId, sal_uInt16 nStartSearchAt )
     913             : {
     914             :     DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
     915             : 
     916             :     // answer immediately if a function-seek comes repeated
     917     2190378 :     if ( pImp->nCachedFunc1 < pImp->pCaches->size() &&
     918     1047869 :          (*pImp->pCaches)[pImp->nCachedFunc1]->GetId() == nId )
     919             :     {
     920      114227 :         return pImp->nCachedFunc1;
     921             :     }
     922     1964796 :     if ( pImp->nCachedFunc2 < pImp->pCaches->size() &&
     923      936514 :          (*pImp->pCaches)[pImp->nCachedFunc2]->GetId() == nId )
     924             :     {
     925             :         // swap the caches
     926       14060 :         sal_uInt16 nTemp = pImp->nCachedFunc1;
     927       14060 :         pImp->nCachedFunc1 = pImp->nCachedFunc2;
     928       14060 :         pImp->nCachedFunc2 = nTemp;
     929       14060 :         return pImp->nCachedFunc1;
     930             :     }
     931             : 
     932             :     // binary search, if not found, seek to target-position
     933     1014222 :     if ( pImp->pCaches->size() <= nStartSearchAt )
     934             :     {
     935        4936 :         return 0;
     936             :     }
     937     1009286 :     if ( (sal_uInt16) pImp->pCaches->size() == (nStartSearchAt+1) )
     938             :     {
     939       43844 :         return (*pImp->pCaches)[nStartSearchAt]->GetId() >= nId ? 0 : 1;
     940             :     }
     941      965442 :     sal_uInt16 nLow = nStartSearchAt;
     942      965442 :     sal_uInt16 nMid = 0;
     943      965442 :     sal_uInt16 nHigh = 0;
     944      965442 :     bool bFound = false;
     945      965442 :     nHigh = pImp->pCaches->size() - 1;
     946     7119844 :     while ( !bFound && nLow <= nHigh )
     947             :     {
     948     5204535 :         nMid = (nLow + nHigh) >> 1;
     949             :         DBG_ASSERT( nMid < pImp->pCaches->size(), "bsearch is buggy" );
     950     5204535 :         int nDiff = (int) nId - (int) ( ((*pImp->pCaches)[nMid])->GetId() );
     951     5204535 :         if ( nDiff < 0)
     952     2380814 :         {   if ( nMid == 0 )
     953       15575 :                 break;
     954     2365239 :             nHigh = nMid - 1;
     955             :         }
     956     2823721 :         else if ( nDiff > 0 )
     957     2408611 :         {   nLow = nMid + 1;
     958     2408611 :             if ( nLow == 0 )
     959           0 :                 break;
     960             :         }
     961             :         else
     962      415110 :             bFound = true;
     963             :     }
     964      965442 :     sal_uInt16 nPos = bFound ? nMid : nLow;
     965             :     DBG_ASSERT( nPos <= pImp->pCaches->size(), "" );
     966             :     DBG_ASSERT( nPos == pImp->pCaches->size() ||
     967             :                 nId <= (*pImp->pCaches)[nPos]->GetId(), "" );
     968             :     DBG_ASSERT( nPos == nStartSearchAt ||
     969             :                 nId > (*pImp->pCaches)[nPos-1]->GetId(), "" );
     970             :     DBG_ASSERT( ( (nPos+1) >= (sal_uInt16) pImp->pCaches->size() ) ||
     971             :                 nId < (*pImp->pCaches)[nPos+1]->GetId(), "" );
     972      965442 :     pImp->nCachedFunc2 = pImp->nCachedFunc1;
     973      965442 :     pImp->nCachedFunc1 = nPos;
     974      965442 :     return nPos;
     975             : }
     976             : 
     977       80218 : void SfxBindings::RegisterInternal_Impl( SfxControllerItem& rItem )
     978             : {
     979       80218 :     Register_Impl( rItem, true );
     980             : 
     981       80218 : }
     982             : 
     983       91640 : void SfxBindings::Register( SfxControllerItem& rItem )
     984             : {
     985       91640 :     Register_Impl( rItem, false );
     986       91640 : }
     987             : 
     988      171858 : void SfxBindings::Register_Impl( SfxControllerItem& rItem, bool bInternal )
     989             : {
     990             : //    DBG_ASSERT( nRegLevel > 0, "registration without EnterRegistrations" );
     991             :     DBG_ASSERT( !pImp->bInNextJob, "SfxBindings::Register while status-updating" );
     992             : 
     993             :     // insert new cache if it does not already exist
     994      171858 :     sal_uInt16 nId = rItem.GetId();
     995      171858 :     sal_uInt16 nPos = GetSlotPos(nId);
     996      323248 :     if ( nPos >= pImp->pCaches->size() ||
     997      151390 :          (*pImp->pCaches)[nPos]->GetId() != nId )
     998             :     {
     999      126799 :         SfxStateCache* pCache = new SfxStateCache(nId);
    1000      126799 :         pImp->pCaches->insert( pImp->pCaches->begin() + nPos, pCache );
    1001             :         DBG_ASSERT( nPos == 0 ||
    1002             :                     (*pImp->pCaches)[nPos]->GetId() >
    1003             :                         (*pImp->pCaches)[nPos-1]->GetId(), "" );
    1004             :         DBG_ASSERT( (nPos == pImp->pCaches->size()-1) ||
    1005             :                     (*pImp->pCaches)[nPos]->GetId() <
    1006             :                         (*pImp->pCaches)[nPos+1]->GetId(), "" );
    1007      126799 :         pImp->bMsgDirty = true;
    1008             :     }
    1009             : 
    1010             :     // enqueue the new binding
    1011      171858 :     if ( bInternal )
    1012             :     {
    1013       80218 :         (*pImp->pCaches)[nPos]->SetInternalController( &rItem );
    1014             :     }
    1015             :     else
    1016             :     {
    1017       91640 :         SfxControllerItem *pOldItem = (*pImp->pCaches)[nPos]->ChangeItemLink(&rItem);
    1018       91640 :         rItem.ChangeItemLink(pOldItem);
    1019             :     }
    1020      171858 : }
    1021             : 
    1022             : 
    1023             : 
    1024      171809 : void SfxBindings::Release( SfxControllerItem& rItem )
    1025             : {
    1026             :     DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
    1027             :     DBG_ASSERT( !pImp->bInNextJob, "SfxBindings::Release while status-updating" );
    1028      171809 :     ENTERREGISTRATIONS();
    1029             : 
    1030             :     // find the bound function
    1031      171809 :     sal_uInt16 nId = rItem.GetId();
    1032      171809 :     sal_uInt16 nPos = GetSlotPos(nId);
    1033      171809 :     SfxStateCache* pCache = (*pImp->pCaches)[nPos];
    1034      171809 :     if ( pCache->GetId() == nId )
    1035             :     {
    1036      171809 :         if ( pCache->GetInternalController() == &rItem )
    1037             :         {
    1038       80183 :             pCache->ReleaseInternalController();
    1039             :         }
    1040             :         else
    1041             :         {
    1042             :             // is this the first binding in the list?
    1043       91626 :             SfxControllerItem* pItem = pCache->GetItemLink();
    1044       91626 :             if ( pItem == &rItem )
    1045       90874 :                 pCache->ChangeItemLink( rItem.GetItemLink() );
    1046             :             else
    1047             :             {
    1048             :                 // search the binding in the list
    1049        1504 :                 while ( pItem && pItem->GetItemLink() != &rItem )
    1050           0 :                     pItem = pItem->GetItemLink();
    1051             : 
    1052             :                 // unlink it if it was found
    1053         752 :                 if ( pItem )
    1054         736 :                     pItem->ChangeItemLink( rItem.GetItemLink() );
    1055             :             }
    1056             :         }
    1057             : 
    1058             :         // was this the last controller?
    1059      171809 :         if ( pCache->GetItemLink() == 0 && !pCache->GetInternalController() )
    1060             :         {
    1061      126739 :             pImp->bCtrlReleased = true;
    1062             :         }
    1063             :     }
    1064             : 
    1065      171809 :     LEAVEREGISTRATIONS();
    1066      171809 : }
    1067             : 
    1068             : 
    1069           0 : const SfxPoolItem* SfxBindings::ExecuteSynchron( sal_uInt16 nId, const SfxPoolItem** ppItems, sal_uInt16 nModi,
    1070             :             const SfxPoolItem **ppInternalArgs )
    1071             : {
    1072             :     DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
    1073             : 
    1074           0 :     if( !nId || !pDispatcher )
    1075           0 :         return NULL;
    1076             : 
    1077           0 :     return Execute_Impl( nId, ppItems, nModi, SfxCallMode::SYNCHRON, ppInternalArgs );
    1078             : }
    1079             : 
    1080           0 : bool SfxBindings::Execute( sal_uInt16 nId, const SfxPoolItem** ppItems, sal_uInt16 nModi, SfxCallMode nCallMode,
    1081             :                         const SfxPoolItem **ppInternalArgs )
    1082             : {
    1083             :     DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
    1084             : 
    1085           0 :     if( !nId || !pDispatcher )
    1086           0 :         return false;
    1087             : 
    1088           0 :     const SfxPoolItem* pRet = Execute_Impl( nId, ppItems, nModi, nCallMode, ppInternalArgs );
    1089           0 :     return ( pRet != 0 );
    1090             : }
    1091             : 
    1092           0 : const SfxPoolItem* SfxBindings::Execute_Impl( sal_uInt16 nId, const SfxPoolItem** ppItems, sal_uInt16 nModi, SfxCallMode nCallMode,
    1093             :                         const SfxPoolItem **ppInternalArgs, bool bGlobalOnly )
    1094             : {
    1095           0 :     SfxStateCache *pCache = GetStateCache( nId );
    1096           0 :     if ( !pCache )
    1097             :     {
    1098           0 :         SfxBindings *pBind = pImp->pSubBindings;
    1099           0 :         while ( pBind )
    1100             :         {
    1101           0 :             if ( pBind->GetStateCache( nId ) )
    1102           0 :                 return pBind->Execute_Impl( nId, ppItems, nModi, nCallMode, ppInternalArgs, bGlobalOnly );
    1103           0 :             pBind = pBind->pImp->pSubBindings;
    1104             :         }
    1105             :     }
    1106             : 
    1107           0 :     SfxDispatcher &rDispatcher = *pDispatcher;
    1108           0 :     rDispatcher.Flush();
    1109             : 
    1110             :     // get SlotServer (Slot+ShellLevel) and Shell from cache
    1111           0 :     ::boost::scoped_ptr<SfxStateCache> xCache;
    1112           0 :     if ( !pCache )
    1113             :     {
    1114             :         // Execution of non cached slots (Accelerators don't use Controllers)
    1115             :         // slot is uncached, use SlotCache to handle external dispatch providers
    1116           0 :         xCache.reset(new SfxStateCache(nId));
    1117           0 :         pCache = xCache.get();
    1118           0 :         pCache->GetSlotServer( rDispatcher, pImp->xProv );
    1119             :     }
    1120             : 
    1121           0 :     if ( pCache->GetDispatch().is() )
    1122             :     {
    1123             :         DBG_ASSERT( !ppInternalArgs, "Internal args get lost when dispatched!" );
    1124             : 
    1125           0 :         SfxItemPool &rPool = GetDispatcher()->GetFrame()->GetObjectShell()->GetPool();
    1126           0 :         SfxRequest aReq( nId, nCallMode, rPool );
    1127           0 :         aReq.SetModifier( nModi );
    1128           0 :         if( ppItems )
    1129           0 :             while( *ppItems )
    1130           0 :                 aReq.AppendItem( **ppItems++ );
    1131             : 
    1132             :         // cache binds to an external dispatch provider
    1133           0 :         pCache->Dispatch( aReq.GetArgs(), nCallMode == SfxCallMode::SYNCHRON );
    1134           0 :         SfxPoolItem *pVoid = new SfxVoidItem( nId );
    1135           0 :         DeleteItemOnIdle( pVoid );
    1136           0 :         return pVoid;
    1137             :     }
    1138             : 
    1139             :     // slot is handled internally by SfxDispatcher
    1140           0 :     if ( pImp->bMsgDirty )
    1141           0 :         UpdateSlotServer_Impl();
    1142             : 
    1143           0 :     SfxShell *pShell=0;
    1144           0 :     const SfxSlot *pSlot=0;
    1145             : 
    1146           0 :     const SfxSlotServer* pServer = pCache->GetSlotServer( rDispatcher, pImp->xProv );
    1147           0 :     if ( !pServer )
    1148             :     {
    1149           0 :         return NULL;
    1150             :     }
    1151             :     else
    1152             :     {
    1153           0 :         pShell = rDispatcher.GetShell( pServer->GetShellLevel() );
    1154           0 :         pSlot = pServer->GetSlot();
    1155             :     }
    1156             : 
    1157           0 :     if ( bGlobalOnly )
    1158           0 :         if ( !pShell->ISA(SfxModule) && !pShell->ISA(SfxApplication) && !pShell->ISA(SfxViewFrame) )
    1159           0 :             return NULL;
    1160             : 
    1161           0 :     SfxItemPool &rPool = pShell->GetPool();
    1162           0 :     SfxRequest aReq( nId, nCallMode, rPool );
    1163           0 :     aReq.SetModifier( nModi );
    1164           0 :     if( ppItems )
    1165           0 :         while( *ppItems )
    1166           0 :             aReq.AppendItem( **ppItems++ );
    1167           0 :     if ( ppInternalArgs )
    1168             :     {
    1169           0 :         SfxAllItemSet aSet( rPool );
    1170           0 :         for ( const SfxPoolItem **pArg = ppInternalArgs; *pArg; ++pArg )
    1171           0 :             aSet.Put( **pArg );
    1172           0 :         aReq.SetInternalArgs_Impl( aSet );
    1173             :     }
    1174             : 
    1175           0 :     Execute_Impl( aReq, pSlot, pShell );
    1176             : 
    1177           0 :     const SfxPoolItem* pRet = aReq.GetReturnValue();
    1178           0 :     if ( !pRet )
    1179             :     {
    1180           0 :         SfxPoolItem *pVoid = new SfxVoidItem( nId );
    1181           0 :         DeleteItemOnIdle( pVoid );
    1182           0 :         pRet = pVoid;
    1183             :     }
    1184             : 
    1185           0 :     return pRet;
    1186             : }
    1187             : 
    1188          27 : void SfxBindings::Execute_Impl( SfxRequest& aReq, const SfxSlot* pSlot, SfxShell* pShell )
    1189             : {
    1190          27 :     SfxItemPool &rPool = pShell->GetPool();
    1191             : 
    1192          27 :     if ( SFX_KIND_ENUM == pSlot->GetKind() )
    1193             :     {
    1194             :         // for Enum-Slots, the Master has to be executed with the value
    1195             :         // of the enums
    1196           0 :         const SfxSlot *pRealSlot = pShell->GetInterface()->GetRealSlot(pSlot);
    1197           0 :         const sal_uInt16 nSlotId = pRealSlot->GetSlotId();
    1198           0 :         aReq.SetSlot( nSlotId );
    1199           0 :         aReq.AppendItem( SfxAllEnumItem( rPool.GetWhich(nSlotId), pSlot->GetValue() ) );
    1200           0 :         pDispatcher->_Execute( *pShell, *pRealSlot, aReq, aReq.GetCallMode() | SfxCallMode::RECORD );
    1201             :     }
    1202          27 :     else if ( SFX_KIND_ATTR == pSlot->GetKind() )
    1203             :     {
    1204             :         // Which value has to be mapped for Attribute slots
    1205          27 :         const sal_uInt16 nSlotId = pSlot->GetSlotId();
    1206          27 :         aReq.SetSlot( nSlotId );
    1207          27 :         if ( pSlot->IsMode(SfxSlotMode::TOGGLE) )
    1208             :         {
    1209             :             // The value is attached to a toggleable attribute (Bools)
    1210          11 :             sal_uInt16 nWhich = pSlot->GetWhich(rPool);
    1211          11 :             SfxItemSet aSet(rPool, nWhich, nWhich);
    1212          11 :             SfxStateFunc aFunc  = pSlot->GetStateFnc();
    1213          11 :             pShell->CallState( aFunc, aSet );
    1214             :             const SfxPoolItem *pOldItem;
    1215          11 :             SfxItemState eState = aSet.GetItemState(nWhich, true, &pOldItem);
    1216          11 :             if ( eState == SfxItemState::DISABLED )
    1217          27 :                 return;
    1218             : 
    1219          11 :             if ( SfxItemState::DEFAULT == eState && SfxItemPool::IsWhich(nWhich) )
    1220           0 :                 pOldItem = &aSet.Get(nWhich);
    1221             : 
    1222          22 :             if ( SfxItemState::SET == eState ||
    1223           0 :                  ( SfxItemState::DEFAULT == eState &&
    1224           0 :                    SfxItemPool::IsWhich(nWhich) &&
    1225             :                    pOldItem ) )
    1226             :             {
    1227          11 :                 if ( pOldItem->ISA(SfxBoolItem) )
    1228             :                 {
    1229             :                     // we can toggle Bools
    1230          10 :                     bool bOldValue = static_cast<const SfxBoolItem *>(pOldItem)->GetValue();
    1231          10 :                     SfxBoolItem *pNewItem = static_cast<SfxBoolItem*>(pOldItem->Clone());
    1232          10 :                     pNewItem->SetValue( !bOldValue );
    1233          10 :                     aReq.AppendItem( *pNewItem );
    1234          10 :                     delete pNewItem;
    1235             :                 }
    1236           2 :                 else if ( pOldItem->ISA(SfxEnumItemInterface) &&
    1237           1 :                         static_cast<const SfxEnumItemInterface *>(pOldItem)->HasBoolValue())
    1238             :                 {
    1239             :                     // and Enums with Bool-Interface
    1240             :                     SfxEnumItemInterface *pNewItem =
    1241           1 :                         static_cast<SfxEnumItemInterface*>(pOldItem->Clone());
    1242           1 :                     pNewItem->SetBoolValue(!static_cast<const SfxEnumItemInterface *>(pOldItem)->GetBoolValue());
    1243           1 :                     aReq.AppendItem( *pNewItem );
    1244           1 :                     delete pNewItem;
    1245             :                 }
    1246             :                 else {
    1247             :                     OSL_FAIL( "Toggle only for Enums and Bools allowed" );
    1248             :                 }
    1249             :             }
    1250           0 :             else if ( SfxItemState::DONTCARE == eState )
    1251             :             {
    1252             :                 // Create one Status-Item for each Factory
    1253           0 :                 SfxPoolItem *pNewItem = pSlot->GetType()->CreateItem();
    1254             :                 DBG_ASSERT( pNewItem, "Toggle to slot without ItemFactory" );
    1255           0 :                 pNewItem->SetWhich( nWhich );
    1256             : 
    1257           0 :                 if ( pNewItem->ISA(SfxBoolItem) )
    1258             :                 {
    1259             :                   // we can toggle Bools
    1260           0 :                     static_cast<SfxBoolItem*>(pNewItem)->SetValue( true );
    1261           0 :                     aReq.AppendItem( *pNewItem );
    1262             :                 }
    1263           0 :                 else if ( pNewItem->ISA(SfxEnumItemInterface) &&
    1264           0 :                         static_cast<SfxEnumItemInterface *>(pNewItem)->HasBoolValue())
    1265             :                 {
    1266             :                     // and Enums with Bool-Interface
    1267           0 :                     static_cast<SfxEnumItemInterface*>(pNewItem)->SetBoolValue(true);
    1268           0 :                     aReq.AppendItem( *pNewItem );
    1269             :                 }
    1270             :                 else {
    1271             :                     OSL_FAIL( "Toggle only for Enums and Bools allowed" );
    1272             :                 }
    1273           0 :                 delete pNewItem;
    1274             :             }
    1275             :             else {
    1276             :                 OSL_FAIL( "suspicious Toggle-Slot" );
    1277          11 :             }
    1278             :         }
    1279             : 
    1280          27 :         pDispatcher->_Execute( *pShell, *pSlot, aReq, aReq.GetCallMode() | SfxCallMode::RECORD );
    1281             :     }
    1282             :     else
    1283           0 :         pDispatcher->_Execute( *pShell, *pSlot, aReq, aReq.GetCallMode() | SfxCallMode::RECORD );
    1284             : }
    1285             : 
    1286             : 
    1287             : 
    1288        1256 : void SfxBindings::UpdateSlotServer_Impl()
    1289             : {
    1290             :     DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
    1291             : 
    1292             :     // synchronize
    1293        1256 :     pDispatcher->Flush();
    1294             : 
    1295        1256 :     if ( pImp->bAllMsgDirty )
    1296             :     {
    1297         878 :         if ( !nRegLevel )
    1298             :         {
    1299             :             ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame > xFrame
    1300         878 :                 ( pDispatcher->GetFrame()->GetFrame().GetFrameInterface(), UNO_QUERY );
    1301         878 :             pImp->bContextChanged = false;
    1302             :         }
    1303             :         else
    1304           0 :             pImp->bContextChanged = true;
    1305             :     }
    1306             : 
    1307      109906 :     for (size_t i = 0, nCount = pImp->pCaches->size(); i < nCount; ++i)
    1308             :     {
    1309      108650 :         SfxStateCache *pCache = (*pImp->pCaches)[i];
    1310             :         //GetSlotServer can modify pImp->pCaches
    1311      108650 :         pCache->GetSlotServer(*pDispatcher, pImp->xProv);
    1312             :     }
    1313        1256 :     pImp->bMsgDirty = pImp->bAllMsgDirty = false;
    1314             : 
    1315        1256 :     Broadcast( SfxSimpleHint(SFX_HINT_DOCCHANGED) );
    1316        1256 : }
    1317             : 
    1318             : 
    1319             : 
    1320       25758 : SfxItemSet* SfxBindings::CreateSet_Impl
    1321             : (
    1322             :     SfxStateCache*&         pCache,     // in: Status-Cache from nId
    1323             :     const SfxSlot*&         pRealSlot,  // out: RealSlot to nId
    1324             :     const SfxSlotServer**   pMsgServer, // out: Slot-Server to nId
    1325             :     SfxFoundCacheArr_Impl&  rFound      // out: List of Caches for Siblings
    1326             : )
    1327             : {
    1328             :     DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
    1329             : 
    1330             :     DBG_ASSERT( !pImp->bMsgDirty, "CreateSet_Impl with dirty MessageServer" );
    1331             :     assert(pDispatcher);
    1332             : 
    1333       25758 :     const SfxSlotServer* pMsgSvr = pCache->GetSlotServer(*pDispatcher, pImp->xProv);
    1334       25758 :     if (!pMsgSvr)
    1335        1842 :         return 0;
    1336             : 
    1337       23916 :     pRealSlot = 0;
    1338       23916 :     *pMsgServer = pMsgSvr;
    1339             : 
    1340       23916 :     sal_uInt16 nShellLevel = pMsgSvr->GetShellLevel();
    1341       23916 :     SfxShell *pShell = pDispatcher->GetShell( nShellLevel );
    1342       23916 :     if ( !pShell ) // rare GPF when browsing through update from Inet-Notify
    1343           0 :         return 0;
    1344             : 
    1345       23916 :     SfxItemPool &rPool = pShell->GetPool();
    1346             : 
    1347             :     // get the status method, which is served by the pCache
    1348       23916 :     SfxStateFunc pFnc = 0;
    1349       23916 :     const SfxInterface *pInterface = pShell->GetInterface();
    1350       23916 :     if ( SFX_KIND_ENUM == pMsgSvr->GetSlot()->GetKind() )
    1351             :     {
    1352         421 :         pRealSlot = pInterface->GetRealSlot(pMsgSvr->GetSlot());
    1353         421 :         pCache = GetStateCache( pRealSlot->GetSlotId() );
    1354             :     }
    1355             :     else
    1356       23495 :         pRealSlot = pMsgSvr->GetSlot();
    1357             : 
    1358             :     // Note: pCache can be NULL!
    1359             : 
    1360       23916 :     pFnc = pRealSlot->GetStateFnc();
    1361             : 
    1362             :     // the RealSlot is always on
    1363             :     SfxFoundCache_Impl *pFound = new SfxFoundCache_Impl(
    1364       23916 :         pRealSlot->GetSlotId(), pRealSlot->GetWhich(rPool), pRealSlot, pCache );
    1365       23916 :     rFound.push_back( pFound );
    1366             : 
    1367             :     // Search through the bindings for slots served by the same function. This ,    // will only affect slots which are present in the found interface.
    1368             : 
    1369             :     // The position of the  Statecaches in StateCache-Array
    1370       23916 :     sal_uInt16 nCachePos = pImp->nMsgPos;
    1371       23916 :     const SfxSlot *pSibling = pRealSlot->GetNextSlot();
    1372             : 
    1373             :     // the Slots ODF a interfaces ar linked in a circle
    1374      473368 :     while ( pSibling > pRealSlot )
    1375             :     {
    1376      425536 :         SfxStateFunc pSiblingFnc=0;
    1377             :         SfxStateCache *pSiblingCache =
    1378      425536 :                 GetStateCache( pSibling->GetSlotId(), &nCachePos );
    1379             : 
    1380             :         // Is the slot cached ?
    1381      425536 :         if ( pSiblingCache )
    1382             :         {
    1383       78759 :             const SfxSlotServer *pServ = pSiblingCache->GetSlotServer(*pDispatcher, pImp->xProv);
    1384       78759 :             if ( pServ && pServ->GetShellLevel() == nShellLevel )
    1385       74925 :                 pSiblingFnc = pServ->GetSlot()->GetStateFnc();
    1386             :         }
    1387             : 
    1388             :         // Does the slot have to be updated at all?
    1389      425536 :         bool bInsert = pSiblingCache && pSiblingCache->IsControllerDirty();
    1390             : 
    1391             :         // It is not enough to ask for the same shell!!
    1392      425536 :         bool bSameMethod = pSiblingCache && pFnc == pSiblingFnc;
    1393             : 
    1394             :         // If the slot is a non-dirty master slot, then maybe one of his slaves
    1395             :         // is dirty? Then the master slot is still inserted.
    1396      425536 :         if ( !bInsert && bSameMethod && pSibling->GetLinkedSlot() )
    1397             :         {
    1398             :             // Also check slave slots for Binding
    1399           0 :             const SfxSlot* pFirstSlave = pSibling->GetLinkedSlot();
    1400           0 :             for ( const SfxSlot *pSlaveSlot = pFirstSlave;
    1401           0 :                   !bInsert;
    1402             :                   pSlaveSlot = pSlaveSlot->GetNextSlot())
    1403             :             {
    1404             :                 // the slaves points to its master
    1405             :                 DBG_ASSERT(pSlaveSlot->GetLinkedSlot() == pSibling,
    1406             :                     "Wrong Master/Slave relationship!");
    1407             : 
    1408           0 :                 sal_uInt16 nCurMsgPos = pImp->nMsgPos;
    1409             :                 const SfxStateCache *pSlaveCache =
    1410           0 :                     GetStateCache( pSlaveSlot->GetSlotId(), &nCurMsgPos );
    1411             : 
    1412             :                 // Is the slave slot chached and dirty ?
    1413           0 :                 bInsert = pSlaveCache && pSlaveCache->IsControllerDirty();
    1414             : 
    1415             :                 // Slaves are chained together in a circle
    1416           0 :                 if (pSlaveSlot->GetNextSlot() == pFirstSlave)
    1417           0 :                     break;
    1418             :             }
    1419             :         }
    1420             : 
    1421      425536 :         if ( bInsert && bSameMethod )
    1422             :         {
    1423             :             SfxFoundCache_Impl *pFoundCache = new SfxFoundCache_Impl(
    1424      144474 :                 pSibling->GetSlotId(), pSibling->GetWhich(rPool),
    1425      144474 :                 pSibling, pSiblingCache );
    1426             : 
    1427       72237 :             rFound.push_back( pFoundCache );
    1428             :         }
    1429             : 
    1430      425536 :         pSibling = pSibling->GetNextSlot();
    1431             :     }
    1432             : 
    1433             :     // Create a Set from the ranges
    1434       23916 :     boost::scoped_array<sal_uInt16> pRanges(new sal_uInt16[rFound.size() * 2 + 1]);
    1435       23916 :     int j = 0;
    1436       23916 :     sal_uInt16 i = 0;
    1437      120853 :     while ( i < rFound.size() )
    1438             :     {
    1439       73021 :         pRanges[j++] = rFound[i].nWhichId;
    1440             :             // consecutive numbers
    1441       96153 :         for ( ; i < rFound.size()-1; ++i )
    1442       72237 :             if ( rFound[i].nWhichId+1 != rFound[i+1].nWhichId )
    1443       49105 :                 break;
    1444       73021 :         pRanges[j++] = rFound[i++].nWhichId;
    1445             :     }
    1446       23916 :     pRanges[j] = 0; // terminating NULL
    1447       23916 :     SfxItemSet *pSet = new SfxItemSet(rPool, pRanges.get());
    1448       23916 :     pRanges.reset();
    1449       23916 :     return pSet;
    1450             : }
    1451             : 
    1452             : 
    1453             : 
    1454       97995 : void SfxBindings::UpdateControllers_Impl
    1455             : (
    1456             :     const SfxInterface*         pIF,    // Id of the current serving Interface
    1457             :     const SfxFoundCache_Impl&   rFound, // Cache, Slot, Which etc.
    1458             :     const SfxPoolItem*          pItem,  // item to send to controller
    1459             :     SfxItemState                eState  // state of item
    1460             : )
    1461             : {
    1462             :     DBG_ASSERT( !rFound.pSlot || SFX_KIND_ENUM != rFound.pSlot->GetKind(),
    1463             :                 "direct update of enum slot isn't allowed" );
    1464             : 
    1465       97995 :     SfxStateCache* pCache = rFound.pCache;
    1466       97995 :     const SfxSlot* pSlot = rFound.pSlot;
    1467             :     DBG_ASSERT( !pCache || !pSlot || pCache->GetId() == pSlot->GetSlotId(), "SID mismatch" );
    1468             : 
    1469             :     // bound until now, the Controller to update the Slot.
    1470       97995 :     if ( pCache && pCache->IsControllerDirty() )
    1471             :     {
    1472       97995 :         if ( SfxItemState::DONTCARE == eState )
    1473             :         {
    1474             :             // ambiguous
    1475          10 :             pCache->SetState( SfxItemState::DONTCARE, reinterpret_cast<SfxPoolItem *>(-1) );
    1476             :         }
    1477      130568 :         else if ( SfxItemState::DEFAULT == eState &&
    1478       32583 :                     rFound.nWhichId > SFX_WHICH_MAX )
    1479             :         {
    1480             :             // no Status or Default but without Pool
    1481       27505 :             SfxVoidItem aVoid(0);
    1482       27505 :             pCache->SetState( SfxItemState::UNKNOWN, &aVoid );
    1483             :         }
    1484       70480 :         else if ( SfxItemState::DISABLED == eState )
    1485       12208 :             pCache->SetState(SfxItemState::DISABLED, 0);
    1486             :         else
    1487       58272 :             pCache->SetState(SfxItemState::DEFAULT, pItem);
    1488             :     }
    1489             : 
    1490             :     // Update the slots for so far available and bound Controllers for
    1491             :     // Slave-Slots (Enum-value)
    1492             :     DBG_ASSERT( !pSlot || 0 == pSlot->GetLinkedSlot() || !pItem ||
    1493             :                 pItem->ISA(SfxEnumItemInterface),
    1494             :                 "master slot with non-enum-type found" );
    1495       97995 :     const SfxSlot *pFirstSlave = pSlot ? pSlot->GetLinkedSlot() : 0;
    1496       97995 :     if ( pIF && pFirstSlave)
    1497             :     {
    1498             :         // Items cast on EnumItem
    1499             :         const SfxEnumItemInterface *pEnumItem =
    1500         421 :                 PTR_CAST(SfxEnumItemInterface,pItem);
    1501         421 :         if ( eState == SfxItemState::DEFAULT && !pEnumItem )
    1502           0 :             eState = SfxItemState::DONTCARE;
    1503             :         else
    1504         421 :             eState = SfxControllerItem::GetItemState( pEnumItem );
    1505             : 
    1506             :         // Iterate over all Slaves-Slots
    1507        6315 :         for ( const SfxSlot *pSlave = pFirstSlave; pSlave; pSlave = pSlave->GetNextSlot() )
    1508             :         {
    1509             :             DBG_ASSERT(pSlave, "Wrong SlaveSlot binding!");
    1510             :             DBG_ASSERT(SFX_KIND_ENUM == pSlave->GetKind(),"non enum slaves aren't allowed");
    1511             :             DBG_ASSERT(pSlave->GetMasterSlotId() == pSlot->GetSlotId(),"Wrong MasterSlot!");
    1512             : 
    1513             :             // Binding exist for function ?
    1514        6315 :             SfxStateCache *pEnumCache = GetStateCache( pSlave->GetSlotId() );
    1515        6315 :             if ( pEnumCache )
    1516             :             {
    1517        1232 :                 pEnumCache->Invalidate(false);
    1518             : 
    1519             :                 // HACK(CONTROL/SELECT Kram) ???
    1520        1232 :                 if ( eState == SfxItemState::DONTCARE && rFound.nWhichId == 10144 )
    1521             :                 {
    1522           0 :                     SfxVoidItem aVoid(0);
    1523           0 :                     pEnumCache->SetState( SfxItemState::UNKNOWN, &aVoid );
    1524             : 
    1525           0 :                     if (pSlave->GetNextSlot() == pFirstSlave)
    1526           0 :                         break;
    1527             : 
    1528           0 :                     continue;
    1529             :                 }
    1530             : 
    1531        1232 :                 if ( SfxItemState::DISABLED == eState || (pEnumItem && !pEnumItem->IsEnabled( pSlave->GetSlotId())) )
    1532             :                 {
    1533             :                     // disabled
    1534           0 :                     pEnumCache->SetState(SfxItemState::DISABLED, 0);
    1535             :                 }
    1536        1232 :                 else if ( SfxItemState::DEFAULT == eState && pEnumItem )
    1537             :                 {
    1538             :                     // Determine enum value
    1539        1232 :                     sal_uInt16 nValue = pEnumItem->GetEnumValue();
    1540        1232 :                     SfxBoolItem aBool( rFound.nWhichId, pSlave->GetValue() == nValue );
    1541        1232 :                     pEnumCache->SetState(SfxItemState::DEFAULT, &aBool);
    1542             :                 }
    1543             :                 else
    1544             :                 {
    1545             :                     // ambiguous
    1546           0 :                     pEnumCache->SetState( SfxItemState::DONTCARE, reinterpret_cast<SfxPoolItem *>(-1) );
    1547             :                 }
    1548             :             }
    1549             : 
    1550        6315 :             if (pSlave->GetNextSlot() == pFirstSlave)
    1551         421 :                 break;
    1552             :         }
    1553             :     }
    1554       97995 : }
    1555             : 
    1556        7190 : IMPL_LINK_TYPED( SfxBindings, NextJob, Timer *, pTimer, void )
    1557             : {
    1558        3595 :     NextJob_Impl(pTimer);
    1559        3595 : }
    1560             : 
    1561        3595 : bool SfxBindings::NextJob_Impl(Timer * pTimer)
    1562             : {
    1563             : #ifdef DBG_UTIL
    1564             :     // on Windows very often C++ Exceptions (GPF etc.) are caught by MSVCRT
    1565             :     // or another MS library try to get them here
    1566             :     try
    1567             :     {
    1568             : #endif
    1569        3595 :     const unsigned MAX_INPUT_DELAY = 200;
    1570             : 
    1571             :     DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
    1572             : 
    1573        3595 :     if ( Application::GetLastInputInterval() < MAX_INPUT_DELAY && pTimer )
    1574             :     {
    1575           0 :         pImp->aTimer.SetTimeout(TIMEOUT_UPDATING);
    1576           0 :         return true;
    1577             :     }
    1578             : 
    1579        3595 :     SfxApplication *pSfxApp = SfxGetpApp();
    1580             : 
    1581        3595 :     if( pDispatcher )
    1582        3595 :         pDispatcher->Update_Impl();
    1583             : 
    1584             :     // modifying the SfxObjectInterface-stack without SfxBindings => nothing to do
    1585        3595 :     SfxViewFrame* pFrame = pDispatcher ? pDispatcher->GetFrame() : NULL;
    1586        3595 :     if ( (pFrame && !pFrame->GetObjectShell()->AcceptStateUpdate()) || pSfxApp->IsDowning() || pImp->pCaches->empty() )
    1587             :     {
    1588           0 :         return true;
    1589             :     }
    1590        3595 :     if ( !pDispatcher || !pDispatcher->IsFlushed() )
    1591             :     {
    1592           0 :         return true;
    1593             :     }
    1594             : 
    1595             :     // if possible Update all server / happens in its own time slice
    1596        3595 :     if ( pImp->bMsgDirty )
    1597             :     {
    1598         657 :         UpdateSlotServer_Impl();
    1599         657 :         return false;
    1600             :     }
    1601             : 
    1602        2938 :     pImp->bAllDirty = false;
    1603        2938 :     pImp->aTimer.SetTimeout(TIMEOUT_UPDATING);
    1604             : 
    1605             :     // at least 10 loops and further if more jobs are available but no input
    1606        2938 :     bool bPreEmptive = pTimer && !pSfxApp->Get_Impl()->nInReschedule;
    1607        2938 :     sal_uInt16 nLoops = 10;
    1608        2938 :     pImp->bInNextJob = true;
    1609        2938 :     const sal_uInt16 nCount = pImp->pCaches->size();
    1610        6577 :     while ( pImp->nMsgPos < nCount )
    1611             :     {
    1612             :         // iterate through the bound functions
    1613        2938 :         bool bJobDone = false;
    1614       98592 :         while ( !bJobDone )
    1615             :         {
    1616       94953 :             SfxStateCache* pCache = (*pImp->pCaches)[pImp->nMsgPos];
    1617             :             DBG_ASSERT( pCache, "invalid SfxStateCache-position in job queue" );
    1618       94953 :             bool bWasDirty = pCache->IsControllerDirty();
    1619       94953 :             if ( bWasDirty )
    1620             :             {
    1621       24723 :                     Update_Impl( pCache );
    1622             :                     DBG_ASSERT( nCount == pImp->pCaches->size(),
    1623             :                             "Reschedule in StateChanged => buff" );
    1624             :             }
    1625             : 
    1626             :             // skip to next function binding
    1627       94953 :             ++pImp->nMsgPos;
    1628             : 
    1629             :             // keep job if it is not completed, but any input is available
    1630       94953 :             bJobDone = pImp->nMsgPos >= nCount;
    1631       94953 :             if ( bJobDone && pImp->bFirstRound )
    1632             :             {
    1633             : 
    1634             :                 // Update of the  preferred shell has been done, now may
    1635             :                 // also the others shells be updated
    1636          13 :                 bJobDone = false;
    1637          13 :                 pImp->bFirstRound = false;
    1638          13 :                 pImp->nMsgPos = 0;
    1639             :             }
    1640             : 
    1641       94953 :             if ( bWasDirty && !bJobDone && bPreEmptive && (--nLoops == 0) )
    1642             :             {
    1643        2237 :                 pImp->bInNextJob = false;
    1644        2237 :                 return false;
    1645             :             }
    1646             :         }
    1647             :     }
    1648             : 
    1649         701 :     pImp->nMsgPos = 0;
    1650             : 
    1651             :     // check for volatile slots
    1652         701 :     bool bVolatileSlotsPresent = false;
    1653       76438 :     for ( sal_uInt16 n = 0; n < nCount; ++n )
    1654             :     {
    1655       75737 :         SfxStateCache* pCache = (*pImp->pCaches)[n];
    1656       75737 :         const SfxSlotServer *pSlotServer = pCache->GetSlotServer(*pDispatcher, pImp->xProv);
    1657       75737 :         if ( pSlotServer && pSlotServer->GetSlot()->IsMode(SfxSlotMode::VOLATILE) )
    1658             :         {
    1659           0 :             pCache->Invalidate(false);
    1660           0 :             bVolatileSlotsPresent = true;
    1661             :         }
    1662             :     }
    1663             : 
    1664         701 :     if (bVolatileSlotsPresent)
    1665           0 :         pImp->aTimer.SetTimeout(TIMEOUT_IDLE);
    1666             :     else
    1667         701 :         pImp->aTimer.Stop();
    1668             : 
    1669             :     // Update round is finished
    1670         701 :     pImp->bInNextJob = false;
    1671         701 :     Broadcast(SfxSimpleHint(SFX_HINT_UPDATEDONE));
    1672         701 :     return true;
    1673             : #ifdef DBG_UTIL
    1674             :     }
    1675             :     catch (...)
    1676             :     {
    1677             :         OSL_FAIL("C++ exception caught!");
    1678             :         pImp->bInNextJob = false;
    1679             :     }
    1680             : 
    1681             :     return false;
    1682             : #endif
    1683             : }
    1684             : 
    1685             : 
    1686             : 
    1687      324595 : sal_uInt16 SfxBindings::EnterRegistrations(const char *pFile, int nLine)
    1688             : {
    1689             :     SAL_INFO(
    1690             :         "sfx.control",
    1691             :         std::setw(std::min(nRegLevel, sal_uInt16(8))) << ' ' << "this = " << this
    1692             :             << " Level = " << nRegLevel << " SfxBindings::EnterRegistrations "
    1693             :             << (pFile
    1694             :                 ? SAL_STREAM("File: " << pFile << " Line: " << nLine) : ""));
    1695             : 
    1696             :     // When bindings are locked, also lock sub bindings.
    1697      324595 :     if ( pImp->pSubBindings )
    1698             :     {
    1699           0 :         pImp->pSubBindings->ENTERREGISTRATIONS();
    1700             : 
    1701             :         // These EnterRegistrations are not "real" for the SubBindings
    1702           0 :         pImp->pSubBindings->pImp->nOwnRegLevel--;
    1703             : 
    1704             :         // Synchronize Bindings
    1705           0 :         pImp->pSubBindings->nRegLevel = nRegLevel + pImp->pSubBindings->pImp->nOwnRegLevel + 1;
    1706             :     }
    1707             : 
    1708      324595 :     pImp->nOwnRegLevel++;
    1709             : 
    1710             :     // check if this is the outer most level
    1711      324595 :     if ( ++nRegLevel == 1 )
    1712             :     {
    1713             :         // stop background-processing
    1714       94619 :         pImp->aTimer.Stop();
    1715             : 
    1716             :         // flush the cache
    1717       94619 :         pImp->nCachedFunc1 = 0;
    1718       94619 :         pImp->nCachedFunc2 = 0;
    1719             : 
    1720             :         // Mark if the all of the Caches have dissapered.
    1721       94619 :         pImp->bCtrlReleased = false;
    1722             :     }
    1723             : 
    1724      324595 :     return nRegLevel;
    1725             : }
    1726             : 
    1727             : 
    1728      318112 : void SfxBindings::LeaveRegistrations( sal_uInt16 nLevel, const char *pFile, int nLine )
    1729             : {
    1730             :     (void)nLevel; // unused variable
    1731             :     DBG_ASSERT( nRegLevel, "Leave without Enter" );
    1732             :     DBG_ASSERT( nLevel == USHRT_MAX || nLevel == nRegLevel, "wrong Leave" );
    1733             : 
    1734             :     // Only when the SubBindings are still locked by the Superbindings,
    1735             :     // remove this lock (i.e. if there are more locks than "real" ones)
    1736      318112 :     if ( pImp->pSubBindings && pImp->pSubBindings->nRegLevel > pImp->pSubBindings->pImp->nOwnRegLevel )
    1737             :     {
    1738             :         // Synchronize Bindings
    1739           0 :         pImp->pSubBindings->nRegLevel = nRegLevel + pImp->pSubBindings->pImp->nOwnRegLevel;
    1740             : 
    1741             :         // This LeaveRegistrations is not "real" for SubBindings
    1742           0 :         pImp->pSubBindings->pImp->nOwnRegLevel++;
    1743           0 :         pImp->pSubBindings->LEAVEREGISTRATIONS();
    1744             :     }
    1745             : 
    1746      318112 :     pImp->nOwnRegLevel--;
    1747             : 
    1748             :     // check if this is the outer most level
    1749      318112 :     if ( --nRegLevel == 0 && !SfxGetpApp()->IsDowning() )
    1750             :     {
    1751       94626 :         if ( pImp->bContextChanged )
    1752             :         {
    1753           0 :             pImp->bContextChanged = false;
    1754             :         }
    1755             : 
    1756       94626 :         SfxViewFrame* pFrame = pDispatcher->GetFrame();
    1757             : 
    1758             :         // If possible remove unused Caches, for example prepare PlugInInfo
    1759       94626 :         if ( pImp->bCtrlReleased )
    1760             :         {
    1761       52632 :             for ( sal_uInt16 nCache = pImp->pCaches->size(); nCache > 0; --nCache )
    1762             :             {
    1763             :                 // Get Cache via ::com::sun::star::sdbcx::Index
    1764       49606 :                 SfxStateCache *pCache = (*pImp->pCaches)[nCache-1];
    1765             : 
    1766             :                 // No interested Controller present
    1767       49606 :                 if ( pCache->GetItemLink() == 0 && !pCache->GetInternalController() )
    1768             :                 {
    1769             :                     // Remove Cache. Safety: first remove and then delete
    1770       14831 :                     pImp->pCaches->erase(pImp->pCaches->begin() + nCache - 1);
    1771       14831 :                     delete pCache;
    1772             :                 }
    1773             :             }
    1774             :         }
    1775             : 
    1776             :         // restart background-processing
    1777       94626 :         pImp->nMsgPos = 0;
    1778       94626 :         if ( !pFrame || !pFrame->GetObjectShell() )
    1779      321362 :             return;
    1780       91376 :         if ( pImp->pCaches && !pImp->pCaches->empty() )
    1781             :         {
    1782       87351 :             pImp->aTimer.Stop();
    1783       87351 :             pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
    1784       87351 :             pImp->aTimer.Start();
    1785             :         }
    1786             :     }
    1787             : 
    1788             :     SAL_INFO(
    1789             :         "sfx.control",
    1790             :         std::setw(std::min(nRegLevel, sal_uInt16(8))) << ' ' << "this = " << this
    1791             :             << " Level = " << nRegLevel << " SfxBindings::LeaveRegistrations "
    1792             :             << (pFile
    1793             :                 ? SAL_STREAM("File: " << pFile << " Line: " << nLine) : ""));
    1794             : }
    1795             : 
    1796             : 
    1797             : 
    1798        9649 : void SfxBindings::SetDispatcher( SfxDispatcher *pDisp )
    1799             : {
    1800        9649 :     SfxDispatcher *pOldDispat = pDispatcher;
    1801        9649 :     if ( pDisp != pDispatcher )
    1802             :     {
    1803        6501 :         if ( pOldDispat )
    1804             :         {
    1805        3247 :             SfxBindings* pBind = pOldDispat->GetBindings();
    1806        9741 :             while ( pBind )
    1807             :             {
    1808        3247 :                 if ( pBind->pImp->pSubBindings == this && pBind->pDispatcher != pDisp )
    1809           4 :                     pBind->SetSubBindings_Impl( NULL );
    1810        3247 :                 pBind = pBind->pImp->pSubBindings;
    1811             :             }
    1812             :         }
    1813             : 
    1814        6501 :         pDispatcher = pDisp;
    1815             : 
    1816        6501 :         ::com::sun::star::uno::Reference < ::com::sun::star::frame::XDispatchProvider > xProv;
    1817        6501 :         if ( pDisp )
    1818        6508 :             xProv = ::com::sun::star::uno::Reference < ::com::sun::star::frame::XDispatchProvider >
    1819        6508 :                                         ( pDisp->GetFrame()->GetFrame().GetFrameInterface(), UNO_QUERY );
    1820             : 
    1821        6501 :         SetDispatchProvider_Impl( xProv );
    1822        6501 :         InvalidateAll( true );
    1823        6501 :         InvalidateUnoControllers_Impl();
    1824             : 
    1825        6501 :         if ( pDispatcher && !pOldDispat )
    1826             :         {
    1827        3254 :             if ( pImp->pSubBindings && pImp->pSubBindings->pDispatcher != pOldDispat )
    1828             :             {
    1829             :                 OSL_FAIL( "SubBindings already set before activating!" );
    1830           0 :                 pImp->pSubBindings->ENTERREGISTRATIONS();
    1831             :             }
    1832        3254 :             LEAVEREGISTRATIONS();
    1833             :         }
    1834        3247 :         else if( !pDispatcher )
    1835             :         {
    1836        3247 :             ENTERREGISTRATIONS();
    1837        3247 :             if ( pImp->pSubBindings && pImp->pSubBindings->pDispatcher != pOldDispat )
    1838             :             {
    1839             :                 OSL_FAIL( "SubBindings still set even when deactivating!" );
    1840           0 :                 pImp->pSubBindings->LEAVEREGISTRATIONS();
    1841             :             }
    1842             :         }
    1843             : 
    1844        6501 :         Broadcast( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
    1845             : 
    1846        6501 :         if ( pDisp )
    1847             :         {
    1848        3254 :             SfxBindings* pBind = pDisp->GetBindings();
    1849        6508 :             while ( pBind && pBind != this )
    1850             :             {
    1851           4 :                 if ( !pBind->pImp->pSubBindings )
    1852             :                 {
    1853           4 :                     pBind->SetSubBindings_Impl( this );
    1854           4 :                     break;
    1855             :                 }
    1856             : 
    1857           0 :                 pBind = pBind->pImp->pSubBindings;
    1858             :             }
    1859        6501 :         }
    1860             :     }
    1861        9649 : }
    1862             : 
    1863             : 
    1864             : 
    1865           0 : void SfxBindings::ClearCache_Impl( sal_uInt16 nSlotId )
    1866             : {
    1867           0 :     SfxStateCache* pCache = GetStateCache(nSlotId);
    1868           0 :     if (!pCache)
    1869           0 :         return;
    1870           0 :     pCache->ClearCache();
    1871             : }
    1872             : 
    1873             : 
    1874           0 : void SfxBindings::StartUpdate_Impl( bool bComplete )
    1875             : {
    1876           0 :     if ( pImp->pSubBindings )
    1877           0 :         pImp->pSubBindings->StartUpdate_Impl( bComplete );
    1878             : 
    1879           0 :     if ( !bComplete )
    1880             :         // Update may be interrupted
    1881           0 :         NextJob_Impl(&pImp->aTimer);
    1882             :     else
    1883             :         // Update all slots in a row
    1884           0 :         NextJob_Impl(0);
    1885           0 : }
    1886             : 
    1887             : 
    1888             : 
    1889        4710 : SfxItemState SfxBindings::QueryState( sal_uInt16 nSlot, SfxPoolItem* &rpState )
    1890             : {
    1891        4710 :     ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch >  xDisp;
    1892        4710 :     SfxStateCache *pCache = GetStateCache( nSlot );
    1893        4710 :     if ( pCache )
    1894        4369 :         xDisp = pCache->GetDispatch();
    1895        4710 :     if ( xDisp.is() || !pCache )
    1896             :     {
    1897         341 :         const SfxSlot* pSlot = SfxSlotPool::GetSlotPool( pDispatcher->GetFrame() ).GetSlot( nSlot );
    1898         341 :         if ( !pSlot || !pSlot->pUnoName )
    1899           0 :             return SfxItemState::DISABLED;
    1900             : 
    1901         341 :         ::com::sun::star::util::URL aURL;
    1902         682 :         OUString aCmd( ".uno:" );
    1903         341 :         aURL.Protocol = aCmd;
    1904         341 :         aURL.Path = OUString::createFromAscii(pSlot->GetUnoName());
    1905         341 :         aCmd += aURL.Path;
    1906         341 :         aURL.Complete = aCmd;
    1907         341 :         aURL.Main = aCmd;
    1908             : 
    1909         341 :         if ( !xDisp.is() )
    1910         341 :             xDisp = pImp->xProv->queryDispatch( aURL, OUString(), 0 );
    1911             : 
    1912         341 :         if ( xDisp.is() )
    1913             :         {
    1914         341 :             ::com::sun::star::uno::Reference< ::com::sun::star::lang::XUnoTunnel > xTunnel( xDisp, ::com::sun::star::uno::UNO_QUERY );
    1915         341 :             SfxOfficeDispatch* pDisp = NULL;
    1916         341 :             if ( xTunnel.is() )
    1917             :             {
    1918         341 :                 sal_Int64 nImplementation = xTunnel->getSomething(SfxOfficeDispatch::impl_getStaticIdentifier());
    1919         341 :                 pDisp = reinterpret_cast< SfxOfficeDispatch* >( sal::static_int_cast< sal_IntPtr >( nImplementation ));
    1920             :             }
    1921             : 
    1922         341 :             if ( !pDisp )
    1923             :             {
    1924           0 :                 bool bDeleteCache = false;
    1925           0 :                 if ( !pCache )
    1926             :                 {
    1927           0 :                     pCache = new SfxStateCache( nSlot );
    1928           0 :                     pCache->GetSlotServer( *GetDispatcher_Impl(), pImp->xProv );
    1929           0 :                     bDeleteCache = true;
    1930             :                 }
    1931             : 
    1932           0 :                 SfxItemState eState = SfxItemState::SET;
    1933           0 :                 SfxPoolItem *pItem=NULL;
    1934           0 :                 BindDispatch_Impl *pBind = new BindDispatch_Impl( xDisp, aURL, pCache, pSlot );
    1935           0 :                 pBind->acquire();
    1936           0 :                 xDisp->addStatusListener( pBind, aURL );
    1937           0 :                 if ( !pBind->GetStatus().IsEnabled )
    1938             :                 {
    1939           0 :                     eState = SfxItemState::DISABLED;
    1940             :                 }
    1941             :                 else
    1942             :                 {
    1943           0 :                     ::com::sun::star::uno::Any aAny = pBind->GetStatus().State;
    1944           0 :                     ::com::sun::star::uno::Type pType = aAny.getValueType();
    1945             : 
    1946           0 :                     if ( pType == cppu::UnoType<bool>::get() )
    1947             :                     {
    1948           0 :                         bool bTemp = false;
    1949           0 :                         aAny >>= bTemp ;
    1950           0 :                         pItem = new SfxBoolItem( nSlot, bTemp );
    1951             :                     }
    1952           0 :                     else if ( pType == ::cppu::UnoType< ::cppu::UnoUnsignedShortType >::get() )
    1953             :                     {
    1954           0 :                         sal_uInt16 nTemp = 0;
    1955           0 :                         aAny >>= nTemp ;
    1956           0 :                         pItem = new SfxUInt16Item( nSlot, nTemp );
    1957             :                     }
    1958           0 :                     else if ( pType == cppu::UnoType<sal_uInt32>::get() )
    1959             :                     {
    1960           0 :                         sal_uInt32 nTemp = 0;
    1961           0 :                         aAny >>= nTemp ;
    1962           0 :                         pItem = new SfxUInt32Item( nSlot, nTemp );
    1963             :                     }
    1964           0 :                     else if ( pType == cppu::UnoType<OUString>::get() )
    1965             :                     {
    1966           0 :                         OUString sTemp ;
    1967           0 :                         aAny >>= sTemp ;
    1968           0 :                         pItem = new SfxStringItem( nSlot, sTemp );
    1969             :                     }
    1970             :                     else
    1971           0 :                         pItem = new SfxVoidItem( nSlot );
    1972             :                 }
    1973             : 
    1974           0 :                 xDisp->removeStatusListener( pBind, aURL );
    1975           0 :                 pBind->Release();
    1976           0 :                 rpState = pItem;
    1977           0 :                 if ( bDeleteCache )
    1978           0 :                     DELETEZ( pCache );
    1979           0 :                 return eState;
    1980         341 :             }
    1981         341 :         }
    1982             :     }
    1983             : 
    1984             :     // Then test at the dispatcher to check if the returned items from
    1985             :     // there are always DELETE_ON_IDLE, a copy of it has to be made in
    1986             :     // order to allow for transition of ownership.
    1987        4710 :     const SfxPoolItem *pItem = NULL;
    1988        4710 :     SfxItemState eState = pDispatcher->QueryState( nSlot, pItem );
    1989        4710 :     if ( eState == SfxItemState::SET )
    1990             :     {
    1991             :         DBG_ASSERT( pItem, "SfxItemState::SET but no item!" );
    1992           0 :         if ( pItem )
    1993           0 :             rpState = pItem->Clone();
    1994             :     }
    1995        4710 :     else if ( eState == SfxItemState::DEFAULT && pItem )
    1996             :     {
    1997        4710 :         rpState = pItem->Clone();
    1998             :     }
    1999             : 
    2000        4710 :     return eState;
    2001             : }
    2002             : 
    2003           8 : void SfxBindings::SetSubBindings_Impl( SfxBindings *pSub )
    2004             : {
    2005           8 :     if ( pImp->pSubBindings )
    2006             :     {
    2007           4 :         pImp->pSubBindings->SetDispatchProvider_Impl( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > () );
    2008           4 :         pImp->pSubBindings->pImp->pSuperBindings = NULL;
    2009             :     }
    2010             : 
    2011           8 :     pImp->pSubBindings = pSub;
    2012             : 
    2013           8 :     if ( pSub )
    2014             :     {
    2015           4 :         pImp->pSubBindings->SetDispatchProvider_Impl( pImp->xProv );
    2016           4 :         pSub->pImp->pSuperBindings = this;
    2017             :     }
    2018           8 : }
    2019             : 
    2020        9544 : SfxBindings* SfxBindings::GetSubBindings_Impl( bool bTop ) const
    2021             : {
    2022        9544 :     SfxBindings *pRet = pImp->pSubBindings;
    2023        9544 :     if ( bTop )
    2024             :     {
    2025           0 :         while ( pRet->pImp->pSubBindings )
    2026           0 :             pRet = pRet->pImp->pSubBindings;
    2027             :     }
    2028             : 
    2029        9544 :     return pRet;
    2030             : }
    2031             : 
    2032        3250 : void SfxBindings::SetWorkWindow_Impl( SfxWorkWindow* pWork )
    2033             : {
    2034        3250 :     pImp->pWorkWin = pWork;
    2035        3250 : }
    2036             : 
    2037        4080 : SfxWorkWindow* SfxBindings::GetWorkWindow_Impl() const
    2038             : {
    2039        4080 :     return pImp->pWorkWin;
    2040             : }
    2041             : 
    2042           0 : void SfxBindings::RegisterUnoController_Impl( SfxUnoControllerItem* pControl )
    2043             : {
    2044           0 :     if ( !pImp->pUnoCtrlArr )
    2045           0 :         pImp->pUnoCtrlArr = new SfxUnoControllerArr_Impl;
    2046           0 :     pImp->pUnoCtrlArr->push_back( pControl );
    2047           0 : }
    2048             : 
    2049           0 : void SfxBindings::ReleaseUnoController_Impl( SfxUnoControllerItem* pControl )
    2050             : {
    2051           0 :     if ( pImp->pUnoCtrlArr )
    2052             :     {
    2053             :         SfxUnoControllerArr_Impl::iterator it = std::find(
    2054           0 :             pImp->pUnoCtrlArr->begin(), pImp->pUnoCtrlArr->end(), pControl );
    2055           0 :         if ( it != pImp->pUnoCtrlArr->end() )
    2056             :         {
    2057           0 :             pImp->pUnoCtrlArr->erase( it );
    2058           0 :             return;
    2059             :         }
    2060             :     }
    2061             : 
    2062           0 :     if ( pImp->pSubBindings )
    2063           0 :         pImp->pSubBindings->ReleaseUnoController_Impl( pControl );
    2064             : }
    2065             : 
    2066       13002 : void SfxBindings::InvalidateUnoControllers_Impl()
    2067             : {
    2068       13002 :     if ( pImp->pUnoCtrlArr )
    2069             :     {
    2070           0 :         sal_uInt16 nCount = pImp->pUnoCtrlArr->size();
    2071           0 :         for ( sal_uInt16 n=nCount; n>0; n-- )
    2072             :         {
    2073           0 :             SfxUnoControllerItem *pCtrl = (*pImp->pUnoCtrlArr)[n-1];
    2074           0 :             ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener >  xRef( static_cast<cppu::OWeakObject*>(pCtrl), ::com::sun::star::uno::UNO_QUERY );
    2075           0 :             pCtrl->ReleaseDispatch();
    2076           0 :             pCtrl->GetNewDispatch();
    2077           0 :         }
    2078             :     }
    2079             : 
    2080       13002 :     if ( pImp->pSubBindings )
    2081           0 :         pImp->pSubBindings->InvalidateUnoControllers_Impl();
    2082       13002 : }
    2083             : 
    2084       11775 : bool SfxBindings::IsInUpdate() const
    2085             : {
    2086       11775 :     bool bInUpdate = pImp->bInUpdate;
    2087       11775 :     if ( !bInUpdate && pImp->pSubBindings )
    2088           0 :         bInUpdate = pImp->pSubBindings->IsInUpdate();
    2089       11775 :     return bInUpdate;
    2090             : }
    2091             : 
    2092         312 : void SfxBindings::SetVisibleState( sal_uInt16 nId, bool bShow )
    2093             : {
    2094         312 :     ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch >  xDisp;
    2095         312 :     SfxStateCache *pCache = GetStateCache( nId );
    2096         312 :     if ( pCache )
    2097           0 :         pCache->SetVisibleState( bShow );
    2098         312 : }
    2099             : 
    2100       10642 : void SfxBindings::SetActiveFrame( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > & rFrame )
    2101             : {
    2102       10642 :     if ( rFrame.is() || !pDispatcher )
    2103        3148 :         SetDispatchProvider_Impl( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > ( rFrame, ::com::sun::star::uno::UNO_QUERY ) );
    2104             :     else
    2105             :         SetDispatchProvider_Impl( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > (
    2106        7494 :             pDispatcher->GetFrame()->GetFrame().GetFrameInterface(), ::com::sun::star::uno::UNO_QUERY ) );
    2107       10642 : }
    2108             : 
    2109       10144 : const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > SfxBindings::GetActiveFrame() const
    2110             : {
    2111       10144 :     const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xFrame( pImp->xProv, ::com::sun::star::uno::UNO_QUERY );
    2112       10144 :     if ( xFrame.is() || !pDispatcher )
    2113       10134 :         return xFrame;
    2114             :     else
    2115          10 :         return pDispatcher->GetFrame()->GetFrame().GetFrameInterface();
    2116             : }
    2117             : 
    2118       17151 : void SfxBindings::SetDispatchProvider_Impl( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > & rProv )
    2119             : {
    2120       17151 :     bool bInvalidate = ( rProv != pImp->xProv );
    2121       17151 :     if ( bInvalidate )
    2122             :     {
    2123        6501 :         pImp->xProv = rProv;
    2124        6501 :         InvalidateAll( true );
    2125        6501 :         InvalidateUnoControllers_Impl();
    2126             :     }
    2127             : 
    2128       17151 :     if ( pImp->pSubBindings )
    2129           0 :         pImp->pSubBindings->SetDispatchProvider_Impl( pImp->xProv );
    2130       17151 : }
    2131             : 
    2132           0 : bool SfxBindings::ExecuteCommand_Impl( const OUString& rCommand )
    2133             : {
    2134           0 :     ::com::sun::star::util::URL aURL;
    2135           0 :     aURL.Complete = rCommand;
    2136           0 :     Reference< util::XURLTransformer > xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
    2137           0 :     xTrans->parseStrict( aURL );
    2138           0 :     ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch >  xDisp = pImp->xProv->queryDispatch( aURL, OUString(), 0 );
    2139           0 :     if ( xDisp.is() )
    2140             :     {
    2141           0 :         new SfxAsyncExec_Impl( aURL, xDisp );
    2142           0 :         return true;
    2143             :     }
    2144             : 
    2145           0 :     return false;
    2146             : }
    2147             : 
    2148          13 : com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > SfxBindings::GetRecorder() const
    2149             : {
    2150          13 :     return pImp->xRecorder;
    2151             : }
    2152             : 
    2153        3243 : void SfxBindings::SetRecorder_Impl( com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder >& rRecorder )
    2154             : {
    2155        3243 :     pImp->xRecorder = rRecorder;
    2156        3243 : }
    2157             : 
    2158           0 : void SfxBindings::ContextChanged_Impl()
    2159             : {
    2160           0 :     if ( !pImp->bInUpdate && ( !pImp->bContextChanged || !pImp->bAllMsgDirty ) )
    2161             :     {
    2162           0 :         InvalidateAll( true );
    2163             :     }
    2164           0 : }
    2165             : 
    2166      217428 : uno::Reference < frame::XDispatch > SfxBindings::GetDispatch( const SfxSlot* pSlot, const util::URL& aURL, bool bMasterCommand )
    2167             : {
    2168      217428 :     uno::Reference < frame::XDispatch > xRet;
    2169      217428 :     SfxStateCache* pCache = GetStateCache( pSlot->nSlotId );
    2170      217428 :     if ( pCache && !bMasterCommand )
    2171      151534 :         xRet = pCache->GetInternalDispatch();
    2172      217428 :     if ( !xRet.is() )
    2173             :     {
    2174             :         // dispatches for slaves are unbound, they don't have a state
    2175             :         SfxOfficeDispatch* pDispatch = bMasterCommand ?
    2176         118 :             new SfxOfficeDispatch( pDispatcher, pSlot, aURL ) :
    2177       80454 :             new SfxOfficeDispatch( *this, pDispatcher, pSlot, aURL );
    2178             : 
    2179       80336 :         pDispatch->SetMasterUnoCommand( bMasterCommand );
    2180       80336 :         xRet = uno::Reference < frame::XDispatch >( pDispatch );
    2181       80336 :         if ( !pCache )
    2182       65786 :             pCache = GetStateCache( pSlot->nSlotId );
    2183             : 
    2184             :         DBG_ASSERT( pCache, "No cache for OfficeDispatch!" );
    2185       80336 :         if ( pCache && !bMasterCommand )
    2186       80218 :             pCache->SetInternalDispatch( xRet );
    2187             :     }
    2188             : 
    2189      217428 :     return xRet;
    2190             : }
    2191             : 
    2192             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11