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

Generated by: LCOV version 1.10