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

Generated by: LCOV version 1.10