xref: /aoo41x/main/sfx2/source/control/bindings.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sfx2.hxx"
30 
31 #include <hash_map>
32 #include <svl/itempool.hxx>
33 #include <svl/itemiter.hxx>
34 #include <svl/eitem.hxx>
35 #include <svl/aeitem.hxx>
36 #include <svl/intitem.hxx>
37 #include <svl/stritem.hxx>
38 #include <svl/visitem.hxx>
39 #include <com/sun/star/util/XURLTransformer.hpp>
40 #include <com/sun/star/frame/XDispatchProviderInterceptor.hpp>
41 #include <com/sun/star/frame/XDispatch.hpp>
42 #include <com/sun/star/frame/XDispatchProvider.hpp>
43 #include <com/sun/star/frame/XStatusListener.hpp>
44 #include <com/sun/star/frame/FrameSearchFlag.hpp>
45 #include <com/sun/star/frame/XDispatchProviderInterception.hpp>
46 #include <com/sun/star/frame/FeatureStateEvent.hpp>
47 #include <com/sun/star/frame/DispatchDescriptor.hpp>
48 #include <com/sun/star/frame/XController.hpp>
49 #include <comphelper/processfactory.hxx>
50 #include <svtools/itemdel.hxx>
51 
52 #ifndef GCC
53 #endif
54 
55 // wg. nInReschedule
56 #include "appdata.hxx"
57 #include <sfx2/bindings.hxx>
58 #include <sfx2/msg.hxx>
59 #include "statcach.hxx"
60 #include <sfx2/ctrlitem.hxx>
61 #include <sfx2/app.hxx>
62 #include <sfx2/dispatch.hxx>
63 #include <sfx2/request.hxx>
64 #include <sfx2/objface.hxx>
65 #include "sfxtypes.hxx"
66 #include "workwin.hxx"
67 #include <sfx2/unoctitm.hxx>
68 #include <sfx2/sfx.hrc>
69 #include <sfx2/sfxuno.hxx>
70 #include <sfx2/viewfrm.hxx>
71 #include <sfx2/objsh.hxx>
72 #include <sfx2/msgpool.hxx>
73 
74 #include <comphelper/uieventslogger.hxx>
75 #include <com/sun/star/frame/XModuleManager.hpp>
76 
77 
78 using namespace ::com::sun::star;
79 using namespace ::com::sun::star::uno;
80 using namespace ::com::sun::star::util;
81 
82 DBG_NAME(SfxBindingsMsgPos)
83 DBG_NAME(SfxBindingsUpdateServers)
84 DBG_NAME(SfxBindingsCreateSet)
85 DBG_NAME(SfxBindingsUpdateCtrl1)
86 DBG_NAME(SfxBindingsUpdateCtrl2)
87 DBG_NAME(SfxBindingsNextJob_Impl0)
88 DBG_NAME(SfxBindingsNextJob_Impl)
89 DBG_NAME(SfxBindingsUpdate_Impl)
90 DBG_NAME(SfxBindingsInvalidateAll)
91 
92 //====================================================================
93 
94 static sal_uInt16 nTimeOut = 300;
95 
96 #define TIMEOUT_FIRST       nTimeOut
97 #define TIMEOUT_UPDATING     20
98 #define TIMEOUT_IDLE       2500
99 
100 static sal_uInt32 nCache1 = 0;
101 static sal_uInt32 nCache2 = 0;
102 
103 typedef std::hash_map< sal_uInt16, bool > InvalidateSlotMap;
104 
105 //====================================================================
106 
107 DECL_PTRARRAY(SfxStateCacheArr_Impl, SfxStateCache*, 32, 16)
108 
109 //====================================================================
110 
111 class SfxAsyncExec_Impl
112 {
113     ::com::sun::star::util::URL aCommand;
114     ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > xDisp;
115     Timer           aTimer;
116 
117 public:
118 
119     SfxAsyncExec_Impl( const ::com::sun::star::util::URL& rCmd, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch >& rDisp )
120         : aCommand( rCmd )
121         , xDisp( rDisp )
122     {
123         aTimer.SetTimeoutHdl( LINK(this, SfxAsyncExec_Impl, TimerHdl) );
124         aTimer.SetTimeout( 0 );
125         aTimer.Start();
126     }
127 
128     DECL_LINK( TimerHdl, Timer*);
129 };
130 
131 IMPL_LINK(SfxAsyncExec_Impl, TimerHdl, Timer*, pTimer)
132 {
133     (void)pTimer; // unused
134     aTimer.Stop();
135 
136     Sequence<beans::PropertyValue> aSeq;
137     xDisp->dispatch( aCommand, aSeq );
138 
139     delete this;
140     return 0L;
141 }
142 
143 class SfxBindings_Impl
144 {
145 public:
146     ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchRecorder > xRecorder;
147     ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider >  xProv;
148     SfxUnoControllerArr_Impl*
149                             pUnoCtrlArr;
150     SfxWorkWindow*          pWorkWin;
151     SfxBindings*            pSubBindings;
152     SfxBindings*            pSuperBindings;
153     SfxStateCacheArr_Impl*  pCaches;        // je ein cache fuer jede gebundene
154     sal_uInt16                  nCachedFunc1;   // index der zuletzt gerufenen
155     sal_uInt16                  nCachedFunc2;   // index der vorletzt gerufenen
156     sal_uInt16                  nMsgPos;        // Message-Position, ab der zu aktualisieren ist
157     SfxPopupAction          ePopupAction;   // in DeleteFloatinWindow() abgefragt
158     sal_Bool                    bContextChanged;
159     sal_Bool                    bMsgDirty;      // wurde ein MessageServer invalidiert?
160     sal_Bool                    bAllMsgDirty;   // wurden die MessageServer invalidiert?
161     sal_Bool                    bAllDirty;      // nach InvalidateAll
162     sal_Bool                    bCtrlReleased;  // waehrend EnterRegistrations
163     AutoTimer               aTimer;         // fuer volatile Slots
164     sal_Bool                    bInUpdate;      // fuer Assertions
165     sal_Bool                    bInNextJob;     // fuer Assertions
166     sal_Bool                    bFirstRound;    // Erste Runde im Update
167     sal_uInt16                  nFirstShell;    // Shell, die in erster Runde bevorzugt wird
168     sal_uInt16                  nOwnRegLevel;   // z"ahlt die echten Locks, ohne die der SuperBindings
169     InvalidateSlotMap           m_aInvalidateSlots; // store slots which are invalidated while in update
170 };
171 
172 //--------------------------------------------------------------------
173 
174 struct SfxFoundCache_Impl
175 {
176     sal_uInt16          nSlotId;    // die Slot-Id
177     sal_uInt16          nWhichId;   // falls verf"ugbar die Which-Id, sonst nSlotId
178     const SfxSlot*  pSlot;      // Pointer auf den <Master-Slot>
179     SfxStateCache*  pCache;     // Pointer auf den StatusCache, ggf. 0
180 
181     SfxFoundCache_Impl():
182         nSlotId(0),
183         nWhichId(0),
184         pSlot(0),
185         pCache(0)
186     {}
187 
188     SfxFoundCache_Impl(SfxFoundCache_Impl&r):
189         nSlotId(r.nSlotId),
190         nWhichId(r.nWhichId),
191         pSlot(r.pSlot),
192         pCache(r.pCache)
193     {}
194 
195     SfxFoundCache_Impl(sal_uInt16 nS, sal_uInt16 nW, const SfxSlot *pS, SfxStateCache *pC ):
196         nSlotId(nS),
197         nWhichId(nW),
198         pSlot(pS),
199         pCache(pC)
200     {}
201 
202     int operator<( const SfxFoundCache_Impl &r ) const
203     { return nWhichId < r.nWhichId; }
204 
205     int operator==( const SfxFoundCache_Impl &r ) const
206     { return nWhichId== r.nWhichId; }
207 };
208 
209 //--------------------------------------------------------------------------
210 
211 SV_DECL_PTRARR_SORT_DEL(SfxFoundCacheArr_Impl, SfxFoundCache_Impl*, 16, 16 )
212 SV_IMPL_OP_PTRARR_SORT(SfxFoundCacheArr_Impl, SfxFoundCache_Impl*);
213 
214 //==========================================================================
215 
216 SfxBindings::SfxBindings()
217 :   pImp(new SfxBindings_Impl),
218     pDispatcher(0),
219     nRegLevel(1)    // geht erst auf 0, wenn Dispatcher gesetzt
220 {
221     pImp->nMsgPos = 0;
222     pImp->bAllMsgDirty = sal_True;
223     pImp->bContextChanged = sal_False;
224     pImp->bMsgDirty = sal_True;
225     pImp->bAllDirty = sal_True;
226     pImp->ePopupAction = SFX_POPUP_DELETE;
227     pImp->nCachedFunc1 = 0;
228     pImp->nCachedFunc2 = 0;
229     pImp->bCtrlReleased = sal_False;
230     pImp->bFirstRound = sal_False;
231     pImp->bInNextJob = sal_False;
232     pImp->bInUpdate = sal_False;
233     pImp->pSubBindings = NULL;
234     pImp->pSuperBindings = NULL;
235     pImp->pWorkWin = NULL;
236     pImp->pUnoCtrlArr = NULL;
237     pImp->nOwnRegLevel = nRegLevel;
238 
239     // all caches are valid (no pending invalidate-job)
240     // create the list of caches
241     pImp->pCaches = new SfxStateCacheArr_Impl;
242     pImp->aTimer.SetTimeoutHdl( LINK(this, SfxBindings, NextJob_Impl) );
243 }
244 
245 //====================================================================
246 
247 SfxBindings::~SfxBindings()
248 
249 /*  [Beschreibung]
250 
251     Destruktor der Klasse SfxBindings. Die eine, f"ur jede <SfxApplication>
252     existierende Instanz wird von der <SfxApplication> nach Ausf"urhung
253     von <SfxApplication::Exit()> automatisch zerst"ort.
254 
255     Noch existierende <SfxControllerItem> Instanzen, die bei dieser
256     SfxBindings Instanz angemeldet sind, werden im Destruktor
257     automatisch zerst"ort. Dies sind i.d.R. Floating-Toolboxen, Value-Sets
258     etc. Arrays von SfxControllerItems d"urfen zu diesem Zeitpunkt nicht
259     mehr exisitieren.
260 */
261 
262 {
263     // Die SubBindings sollen ja nicht gelocked werden !
264     pImp->pSubBindings = NULL;
265 
266     ENTERREGISTRATIONS();
267 
268     pImp->aTimer.Stop();
269     DeleteControllers_Impl();
270 
271     // Caches selbst l"oschen
272     sal_uInt16 nCount = pImp->pCaches->Count();
273     for ( sal_uInt16 nCache = 0; nCache < nCount; ++nCache )
274         delete pImp->pCaches->GetObject(nCache);
275 
276     DELETEZ( pImp->pWorkWin );
277 
278     delete pImp->pCaches;
279     delete pImp;
280 }
281 
282 //--------------------------------------------------------------------
283 
284 void SfxBindings::DeleteControllers_Impl()
285 {
286     // in der ersten Runde den SfxPopupWindows l"oschen
287     sal_uInt16 nCount = pImp->pCaches->Count();
288     sal_uInt16 nCache;
289     for ( nCache = 0; nCache < nCount; ++nCache )
290     {
291         // merken wo man ist
292         SfxStateCache *pCache = pImp->pCaches->GetObject(nCache);
293         sal_uInt16 nSlotId = pCache->GetId();
294 
295         // SfxPopupWindow l"oschen lassen
296         pCache->DeleteFloatingWindows();
297 
298         // da der Cache verkleinert worden sein kann, wiederaufsetzen
299         sal_uInt16 nNewCount = pImp->pCaches->Count();
300         if ( nNewCount < nCount )
301         {
302             nCache = GetSlotPos(nSlotId);
303             if ( nCache >= nNewCount ||
304                  nSlotId != pImp->pCaches->GetObject(nCache)->GetId() )
305                 --nCache;
306             nCount = nNewCount;
307         }
308     }
309 
310     // alle Caches l"oschen
311     for ( nCache = pImp->pCaches->Count(); nCache > 0; --nCache )
312     {
313         // Cache via ::com::sun::star::sdbcx::Index besorgen
314         SfxStateCache *pCache = pImp->pCaches->GetObject(nCache-1);
315 
316         // alle Controller in dem Cache unbinden
317         SfxControllerItem *pNext;
318         for ( SfxControllerItem *pCtrl = pCache->GetItemLink();
319               pCtrl; pCtrl = pNext )
320         {
321             pNext = pCtrl->GetItemLink();
322             pCtrl->UnBind();
323         }
324 
325         if ( pCache->GetInternalController() )
326             pCache->GetInternalController()->UnBind();
327 
328         // Cache l"oschen
329         if( nCache-1 < pImp->pCaches->Count() )
330             delete (*pImp->pCaches)[nCache-1];
331         pImp->pCaches->Remove(nCache-1, 1);
332     }
333 
334     if( pImp->pUnoCtrlArr )
335     {
336         sal_uInt16 nCtrlCount = pImp->pUnoCtrlArr->Count();
337         for ( sal_uInt16 n=nCtrlCount; n>0; n-- )
338         {
339             SfxUnoControllerItem *pCtrl = (*pImp->pUnoCtrlArr)[n-1];
340             pCtrl->ReleaseBindings();
341         }
342 
343         DBG_ASSERT( !pImp->pUnoCtrlArr->Count(), "UnoControllerItems nicht entfernt!" );
344         DELETEZ( pImp->pUnoCtrlArr );
345     }
346 }
347 
348 //--------------------------------------------------------------------
349 
350 SfxPopupAction SfxBindings::GetPopupAction_Impl() const
351 {
352     return pImp->ePopupAction;
353 }
354 
355 
356 //--------------------------------------------------------------------
357 
358 void SfxBindings::HidePopups( bool bHide )
359 {
360     // SfxPopupWindows hiden
361     HidePopupCtrls_Impl( bHide );
362     SfxBindings *pSub = pImp->pSubBindings;
363     while ( pSub )
364     {
365         pImp->pSubBindings->HidePopupCtrls_Impl( bHide );
366         pSub = pSub->pImp->pSubBindings;
367     }
368 
369     // SfxChildWindows hiden
370     DBG_ASSERT( pDispatcher, "HidePopups not allowed without dispatcher" );
371     if ( pImp->pWorkWin )
372         pImp->pWorkWin->HidePopups_Impl( bHide, sal_True );
373 }
374 
375 void SfxBindings::HidePopupCtrls_Impl( FASTBOOL bHide )
376 {
377     if ( bHide )
378     {
379         // SfxPopupWindows hiden
380         pImp->ePopupAction = SFX_POPUP_HIDE;
381     }
382     else
383     {
384         // SfxPopupWindows showen
385         pImp->ePopupAction = SFX_POPUP_SHOW;
386     }
387 
388     for ( sal_uInt16 nCache = 0; nCache < pImp->pCaches->Count(); ++nCache )
389         pImp->pCaches->GetObject(nCache)->DeleteFloatingWindows();
390     pImp->ePopupAction = SFX_POPUP_DELETE;
391 }
392 
393 //--------------------------------------------------------------------
394 
395 void SfxBindings::Update_Impl
396 (
397     SfxStateCache*  pCache      // der upzudatende SfxStatusCache
398 )
399 {
400     if( pCache->GetDispatch().is() && pCache->GetItemLink() )
401     {
402         pCache->SetCachedState(sal_True);
403         if ( !pCache->GetInternalController() )
404             return;
405     }
406 
407     if ( !pDispatcher )
408         return;
409     DBG_PROFSTART(SfxBindingsUpdate_Impl);
410 
411     // alle mit derselben Statusmethode zusammensammeln, die dirty sind
412     SfxDispatcher &rDispat = *pDispatcher;
413     const SfxSlot *pRealSlot = 0;
414     const SfxSlotServer* pMsgServer = 0;
415     SfxFoundCacheArr_Impl aFound;
416     SfxItemSet *pSet = CreateSet_Impl( pCache, pRealSlot, &pMsgServer, aFound );
417     sal_Bool bUpdated = sal_False;
418     if ( pSet )
419     {
420         // Status erfragen
421         if ( rDispat._FillState( *pMsgServer, *pSet, pRealSlot ) )
422         {
423             // Status posten
424             const SfxInterface *pInterface =
425                 rDispat.GetShell(pMsgServer->GetShellLevel())->GetInterface();
426             for ( sal_uInt16 nPos = 0; nPos < aFound.Count(); ++nPos )
427             {
428                 const SfxFoundCache_Impl *pFound = aFound[nPos];
429                 sal_uInt16 nWhich = pFound->nWhichId;
430                 const SfxPoolItem *pItem = 0;
431                 SfxItemState eState = pSet->GetItemState(nWhich, sal_True, &pItem);
432                 if ( eState == SFX_ITEM_DEFAULT && SfxItemPool::IsWhich(nWhich) )
433                     pItem = &pSet->Get(nWhich);
434                 UpdateControllers_Impl( pInterface, aFound[nPos], pItem, eState );
435             }
436             bUpdated = sal_True;
437         }
438 
439         delete pSet;
440     }
441 
442     if ( !bUpdated && pCache )
443     {
444         // Wenn pCache == NULL und kein SlotServer ( z.B. weil Dispatcher gelockt! ),
445         // darf nat"urlich kein Update versucht werden
446         SfxFoundCache_Impl aFoundCache(
447                             pCache->GetId(), 0,
448                             pRealSlot, pCache );
449         UpdateControllers_Impl( 0, &aFoundCache, 0, SFX_ITEM_DISABLED);
450     }
451 
452     DBG_PROFSTOP(SfxBindingsUpdate_Impl);
453 }
454 
455 //--------------------------------------------------------------------
456 
457 void SfxBindings::InvalidateSlotsInMap_Impl()
458 {
459     InvalidateSlotMap::const_iterator pIter = pImp->m_aInvalidateSlots.begin();
460     while ( pIter != pImp->m_aInvalidateSlots.end() )
461     {
462         Invalidate( pIter->first );
463         ++pIter;
464     }
465     pImp->m_aInvalidateSlots.clear();
466 }
467 
468 //--------------------------------------------------------------------
469 
470 void SfxBindings::AddSlotToInvalidateSlotsMap_Impl( sal_uInt16 nId )
471 {
472     pImp->m_aInvalidateSlots[nId] = sal_True;
473 }
474 
475 //--------------------------------------------------------------------
476 
477 void SfxBindings::Update
478 (
479     sal_uInt16      nId     // die gebundene und upzudatende Slot-Id
480 )
481 {
482     DBG_MEMTEST();
483     DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
484 
485 //!!TLX: Fuehrte zu Vorlagenkatalogstillstand
486 //  if ( nRegLevel )
487 //      return;
488 
489     if ( pDispatcher )
490         pDispatcher->Flush();
491 
492     if ( pImp->pSubBindings )
493         pImp->pSubBindings->Update( nId );
494 
495     SfxStateCache* pCache = GetStateCache( nId );
496     if ( pCache )
497     {
498         pImp->bInUpdate = sal_True;
499         if ( pImp->bMsgDirty )
500         {
501             UpdateSlotServer_Impl();
502             pCache = GetStateCache( nId );
503         }
504 
505         if (pCache)
506         {
507             sal_Bool bInternalUpdate = sal_True;
508             if( pCache->GetDispatch().is() && pCache->GetItemLink() )
509             {
510                 pCache->SetCachedState(sal_True);
511                 bInternalUpdate = ( pCache->GetInternalController() != 0 );
512             }
513 
514             if ( bInternalUpdate )
515             {
516                 // Status erfragen
517                 const SfxSlotServer* pMsgServer = pCache->GetSlotServer(*pDispatcher, pImp->xProv);
518                 if ( !pCache->IsControllerDirty() &&
519                     ( !pMsgServer ||
520                     !pMsgServer->GetSlot()->IsMode(SFX_SLOT_VOLATILE) ) )
521                 {
522                     pImp->bInUpdate = sal_False;
523                     InvalidateSlotsInMap_Impl();
524                     return;
525                 }
526                 if (!pMsgServer)
527                 {
528                     pCache->SetState(SFX_ITEM_DISABLED, 0);
529                     pImp->bInUpdate = sal_False;
530                     InvalidateSlotsInMap_Impl();
531                     return;
532                 }
533 
534                 Update_Impl(pCache);
535             }
536 
537             pImp->bAllDirty = sal_False;
538         }
539 
540         pImp->bInUpdate = sal_False;
541         InvalidateSlotsInMap_Impl();
542     }
543 }
544 
545 //--------------------------------------------------------------------
546 
547 void SfxBindings::Update()
548 {
549     DBG_MEMTEST();
550     DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
551 
552     if ( pImp->pSubBindings )
553         pImp->pSubBindings->Update();
554 
555     if ( pDispatcher )
556     {
557         if ( nRegLevel )
558             return;
559 
560         pImp->bInUpdate = sal_True;
561         pDispatcher->Flush();
562         pDispatcher->Update_Impl();
563         while ( !NextJob_Impl(0) )
564             ; // loop
565         pImp->bInUpdate = sal_False;
566         InvalidateSlotsInMap_Impl();
567     }
568 }
569 
570 //--------------------------------------------------------------------
571 
572 void SfxBindings::SetState
573 (
574     const SfxItemSet&   rSet    // zu setzende Status-Werte
575 )
576 {
577     // wenn gelockt, dann nur invalidieren
578     if ( nRegLevel )
579     {
580         SfxItemIter aIter(rSet);
581         for ( const SfxPoolItem *pItem = aIter.FirstItem();
582               pItem;
583               pItem = aIter.NextItem() )
584             Invalidate( pItem->Which() );
585     }
586     else
587     {
588         // Status d"urfen nur angenommen werden, wenn alle Slot-Pointer gesetzt sind
589         if ( pImp->bMsgDirty )
590             UpdateSlotServer_Impl();
591 
592         // "uber das ItemSet iterieren, falls Slot gebunden, updaten
593         //! Bug: WhichIter verwenden und ggf. VoidItems hochschicken
594         SfxItemIter aIter(rSet);
595         for ( const SfxPoolItem *pItem = aIter.FirstItem();
596               pItem;
597               pItem = aIter.NextItem() )
598         {
599             SfxStateCache* pCache =
600                     GetStateCache( rSet.GetPool()->GetSlotId(pItem->Which()) );
601             if ( pCache )
602             {
603                 // Status updaten
604                 if ( !pCache->IsControllerDirty() )
605                     pCache->Invalidate(sal_False);
606                 pCache->SetState( SFX_ITEM_AVAILABLE, pItem );
607 
608                 //! nicht implementiert: Updates von EnumSlots via MasterSlots
609             }
610         }
611     }
612 }
613 
614 //--------------------------------------------------------------------
615 
616 void SfxBindings::SetState
617 (
618     const SfxPoolItem&  rItem   // zu setzender Status-Wert
619 )
620 {
621     if ( nRegLevel )
622     {
623         Invalidate( rItem.Which() );
624     }
625     else
626     {
627         // Status d"urfen nur angenommen werden, wenn alle Slot-Pointer gesetzt sind
628         if ( pImp->bMsgDirty )
629             UpdateSlotServer_Impl();
630 
631         // falls der Slot gebunden ist, updaten
632         DBG_ASSERT( SfxItemPool::IsSlot( rItem.Which() ),
633                     "cannot set items with which-id" );
634         SfxStateCache* pCache = GetStateCache( rItem.Which() );
635         if ( pCache )
636         {
637             // Status updaten
638             if ( !pCache->IsControllerDirty() )
639                 pCache->Invalidate(sal_False);
640             pCache->SetState( SFX_ITEM_AVAILABLE, &rItem );
641 
642             //! nicht implementiert: Updates von EnumSlots via MasterSlots
643         }
644     }
645 }
646 
647 
648 //--------------------------------------------------------------------
649 
650 SfxStateCache* SfxBindings::GetAnyStateCache_Impl( sal_uInt16 nId )
651 {
652     SfxStateCache* pCache = GetStateCache( nId );
653     if ( !pCache && pImp->pSubBindings )
654         return pImp->pSubBindings->GetAnyStateCache_Impl( nId );
655     return pCache;
656 }
657 
658 SfxStateCache* SfxBindings::GetStateCache
659 (
660     sal_uInt16      nId         /*  Slot-Id, deren SfxStatusCache gefunden
661                                 werden soll */,
662     sal_uInt16*     pPos        /*  0 bzw. Position, ab der die Bindings
663                                 bin"ar durchsucht werden sollen. Liefert
664                                 die Position zur"uck, an der nId gefunden
665                                 wurde, bzw. an der es einfef"ugt werden
666                                 w"urde. */
667 )
668 {
669     DBG_MEMTEST();
670     DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
671     // is the specified function bound?
672     const sal_uInt16 nStart = ( pPos ? *pPos : 0 );
673     const sal_uInt16 nPos = GetSlotPos( nId, nStart );
674 
675     if ( nPos < pImp->pCaches->Count() &&
676          (*pImp->pCaches)[nPos]->GetId() == nId )
677     {
678         if ( pPos )
679             *pPos = nPos;
680         return (*pImp->pCaches)[nPos];
681     }
682     return 0;
683 }
684 
685 //--------------------------------------------------------------------
686 
687 void SfxBindings::InvalidateAll
688 (
689     sal_Bool    bWithMsg        /*  sal_True
690                                 Slot-Server als ung"ultig markieren
691 
692                                 sal_False
693                                 Slot-Server bleiben g"ultig */
694 )
695 {
696     DBG_PROFSTART(SfxBindingsInvalidateAll);
697     DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
698 
699     DBG_MEMTEST();
700 
701     if ( pImp->pSubBindings )
702         pImp->pSubBindings->InvalidateAll( bWithMsg );
703 
704     // ist schon alles dirty gesetzt oder downing => nicht zu tun
705     if ( !pDispatcher ||
706          ( pImp->bAllDirty && ( !bWithMsg || pImp->bAllMsgDirty ) ) ||
707          SFX_APP()->IsDowning() )
708     {
709         DBG_PROFSTOP(SfxBindingsInvalidateAll);
710         return;
711     }
712 
713     pImp->bAllMsgDirty = pImp->bAllMsgDirty || bWithMsg;
714     pImp->bMsgDirty = pImp->bMsgDirty || pImp->bAllMsgDirty || bWithMsg;
715     pImp->bAllDirty = sal_True;
716 
717     for ( sal_uInt16 n = 0; n < pImp->pCaches->Count(); ++n )
718         pImp->pCaches->GetObject(n)->Invalidate(bWithMsg);
719 /*
720     ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame > xFrame
721         ( pDispatcher->GetFrame()->GetFrame().GetFrameInterface(), UNO_QUERY );
722 
723     if ( bWithMsg && xFrame.is() )
724         xFrame->contextChanged();
725 */
726     pImp->nMsgPos = 0;
727     if ( !nRegLevel )
728     {
729         pImp->aTimer.Stop();
730         pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
731         pImp->aTimer.Start();
732 //      pImp->bFirstRound = sal_True;
733 //      pImp->nFirstShell = 0;
734     }
735 
736     DBG_PROFSTOP(SfxBindingsInvalidateAll);
737 }
738 
739 //--------------------------------------------------------------------
740 
741 void SfxBindings::Invalidate
742 (
743     const sal_uInt16* pIds      /*  numerisch sortiertes 0-terminiertes Array
744                                 von Slot-Ids (einzel, nicht als Paare!) */
745 )
746 {
747     DBG_PROFSTART(SfxBindingsInvalidateAll);
748 //  DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
749 
750     DBG_MEMTEST();
751 
752     if ( pImp->bInUpdate )
753     {
754         sal_Int32 i = 0;
755         while ( pIds[i] != 0 )
756             AddSlotToInvalidateSlotsMap_Impl( pIds[i++] );
757 
758         if ( pImp->pSubBindings )
759             pImp->pSubBindings->Invalidate( pIds );
760         return;
761     }
762 
763     if ( pImp->pSubBindings )
764         pImp->pSubBindings->Invalidate( pIds );
765 
766     // ist schon alles dirty gesetzt oder downing => nicht zu tun
767     if ( !pDispatcher || pImp->bAllDirty || SFX_APP()->IsDowning() )
768         return;
769 
770     // in immer kleiner werdenden Berichen bin"ar suchen
771     for ( sal_uInt16 n = GetSlotPos(*pIds);
772           *pIds && n < pImp->pCaches->Count();
773           n = GetSlotPos(*pIds, n) )
774     {
775         // falls SID "uberhaupt gebunden ist, den Cache invalidieren
776         SfxStateCache *pCache = pImp->pCaches->GetObject(n);
777         if ( pCache->GetId() == *pIds )
778             pCache->Invalidate(sal_False);
779 
780         // n"achste SID
781         if ( !*++pIds )
782             break;
783         DBG_ASSERT( *pIds > *(pIds-1), "pIds unsorted" );
784     }
785 
786     // falls nicht gelockt, Update-Timer starten
787     pImp->nMsgPos = 0;
788     if ( !nRegLevel )
789     {
790         pImp->aTimer.Stop();
791         pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
792         pImp->aTimer.Start();
793 //      pImp->bFirstRound = sal_True;
794 //      pImp->nFirstShell = 0;
795     }
796 
797     DBG_PROFSTOP(SfxBindingsInvalidateAll);
798 }
799 
800 //--------------------------------------------------------------------
801 
802 void SfxBindings::InvalidateShell
803 (
804     const SfxShell&     rSh             /*  Die <SfxShell>, deren Slot-Ids
805                                             invalidiert werden sollen. */,
806 
807     sal_Bool                bDeep           /*  sal_True
808                                             auch die, von der SfxShell
809                                             ererbten Slot-Ids werden invalidert
810 
811                                             sal_False
812                                             die ererbten und nicht "uberladenen
813                                             Slot-Ids werden invalidiert */
814                                             //! MI: z. Zt. immer bDeep
815 )
816 {
817     DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
818 
819     if ( pImp->pSubBindings )
820         pImp->pSubBindings->InvalidateShell( rSh, bDeep );
821 
822     if ( !pDispatcher || pImp->bAllDirty || SFX_APP()->IsDowning() )
823         return;
824 
825     DBG_PROFSTART(SfxBindingsInvalidateAll);
826     DBG_MEMTEST();
827 
828     // Jetzt schon flushen, wird in GetShellLevel(rSh) sowieso gemacht; wichtig,
829     // damit pImp->bAll(Msg)Dirty korrekt gesetzt ist
830     pDispatcher->Flush();
831 
832     if ( !pDispatcher ||
833          ( pImp->bAllDirty && pImp->bAllMsgDirty ) ||
834          SFX_APP()->IsDowning() )
835     {
836         // Wenn sowieso demn"achst alle Server geholt werden
837         return;
838     }
839 
840     // Level finden
841     sal_uInt16 nLevel = pDispatcher->GetShellLevel(rSh);
842     if ( nLevel != USHRT_MAX )
843     {
844         for ( sal_uInt16 n = 0; n < pImp->pCaches->Count(); ++n )
845         {
846             SfxStateCache *pCache = pImp->pCaches->GetObject(n);
847             const SfxSlotServer *pMsgServer =
848                 pCache->GetSlotServer(*pDispatcher, pImp->xProv);
849             if ( pMsgServer && pMsgServer->GetShellLevel() == nLevel )
850                 pCache->Invalidate(sal_False);
851         }
852         pImp->nMsgPos = 0;
853         if ( !nRegLevel )
854         {
855             pImp->aTimer.Stop();
856             pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
857             pImp->aTimer.Start();
858             pImp->bFirstRound = sal_True;
859             pImp->nFirstShell = nLevel;
860         }
861     }
862 
863     DBG_PROFSTOP(SfxBindingsInvalidateAll);
864 }
865 
866 //--------------------------------------------------------------------
867 
868 void SfxBindings::Invalidate
869 (
870     sal_uInt16 nId              // zu invalidierende Slot-Id
871 )
872 {
873     DBG_MEMTEST();
874 //  DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
875 
876     if ( pImp->bInUpdate )
877     {
878         AddSlotToInvalidateSlotsMap_Impl( nId );
879         if ( pImp->pSubBindings )
880             pImp->pSubBindings->Invalidate( nId );
881         return;
882     }
883 
884     if ( pImp->pSubBindings )
885         pImp->pSubBindings->Invalidate( nId );
886 
887     if ( !pDispatcher || pImp->bAllDirty || SFX_APP()->IsDowning() )
888         return;
889 
890     SfxStateCache* pCache = GetStateCache(nId);
891     if ( pCache )
892     {
893         pCache->Invalidate(sal_False);
894         pImp->nMsgPos = Min(GetSlotPos(nId), pImp->nMsgPos);
895         if ( !nRegLevel )
896         {
897             pImp->aTimer.Stop();
898             pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
899             pImp->aTimer.Start();
900         }
901     }
902 }
903 
904 //--------------------------------------------------------------------
905 
906 void SfxBindings::Invalidate
907 (
908     sal_uInt16  nId,                // zu invalidierende Slot-Id
909     sal_Bool    bWithItem,          // StateCache clearen ?
910     sal_Bool    bWithMsg            // SlotServer neu holen ?
911 )
912 {
913     DBG_MEMTEST();
914     DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
915 
916     if ( pImp->pSubBindings )
917         pImp->pSubBindings->Invalidate( nId, bWithItem, bWithMsg );
918 
919     if ( SFX_APP()->IsDowning() )
920         return;
921 
922     SfxStateCache* pCache = GetStateCache(nId);
923     if ( pCache )
924     {
925         if ( bWithItem )
926             pCache->ClearCache();
927         pCache->Invalidate(bWithMsg);
928 
929         if ( !pDispatcher || pImp->bAllDirty )
930             return;
931 
932         pImp->nMsgPos = Min(GetSlotPos(nId), pImp->nMsgPos);
933         if ( !nRegLevel )
934         {
935             pImp->aTimer.Stop();
936             pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
937             pImp->aTimer.Start();
938         }
939     }
940 }
941 
942 //--------------------------------------------------------------------
943 
944 sal_Bool SfxBindings::IsBound( sal_uInt16 nSlotId, sal_uInt16 nStartSearchAt )
945 {
946     DBG_MEMTEST();
947     DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
948     return GetStateCache(nSlotId, &nStartSearchAt ) != 0;
949 }
950 
951 //--------------------------------------------------------------------
952 
953 sal_uInt16 SfxBindings::GetSlotPos( sal_uInt16 nId, sal_uInt16 nStartSearchAt )
954 {
955     DBG_MEMTEST();
956     DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
957     DBG_PROFSTART(SfxBindingsMsgPos);
958 
959     // answer immediately if a function-seek comes repeated
960     if ( pImp->nCachedFunc1 < pImp->pCaches->Count() &&
961          (*pImp->pCaches)[pImp->nCachedFunc1]->GetId() == nId )
962     {
963         ++nCache1;
964         DBG_PROFSTOP(SfxBindingsMsgPos);
965         return pImp->nCachedFunc1;
966     }
967     if ( pImp->nCachedFunc2 < pImp->pCaches->Count() &&
968          (*pImp->pCaches)[pImp->nCachedFunc2]->GetId() == nId )
969     {
970         ++nCache2;
971 
972         // swap the caches
973         sal_uInt16 nTemp = pImp->nCachedFunc1;
974         pImp->nCachedFunc1 = pImp->nCachedFunc2;
975         pImp->nCachedFunc2 = nTemp;
976         DBG_PROFSTOP(SfxBindingsMsgPos);
977         return pImp->nCachedFunc1;
978     }
979 
980     // binary search, if not found, seek to target-position
981     if ( pImp->pCaches->Count() <= nStartSearchAt )
982     {
983         DBG_PROFSTOP(SfxBindingsMsgPos);
984         return 0;
985     }
986     if ( pImp->pCaches->Count() == (nStartSearchAt+1) )
987     {
988         DBG_PROFSTOP(SfxBindingsMsgPos);
989         return (*pImp->pCaches)[nStartSearchAt]->GetId() >= nId ? 0 : 1;
990     }
991     sal_uInt16 nLow = nStartSearchAt;
992     sal_uInt16 nMid = 0;
993     sal_uInt16 nHigh = 0;
994     sal_Bool bFound = sal_False;
995     nHigh = pImp->pCaches->Count() - 1;
996     while ( !bFound && nLow <= nHigh )
997     {
998         nMid = (nLow + nHigh) >> 1;
999         DBG_ASSERT( nMid < pImp->pCaches->Count(), "bsearch ist buggy" );
1000         int nDiff = (int) nId - (int) ( ((*pImp->pCaches)[nMid])->GetId() );
1001         if ( nDiff < 0)
1002         {   if ( nMid == 0 )
1003                 break;
1004             nHigh = nMid - 1;
1005         }
1006         else if ( nDiff > 0 )
1007         {   nLow = nMid + 1;
1008             if ( nLow == 0 )
1009                 break;
1010         }
1011         else
1012             bFound = sal_True;
1013     }
1014     sal_uInt16 nPos = bFound ? nMid : nLow;
1015     DBG_ASSERT( nPos <= pImp->pCaches->Count(), "" );
1016     DBG_ASSERT( nPos == pImp->pCaches->Count() ||
1017                 nId <= (*pImp->pCaches)[nPos]->GetId(), "" );
1018     DBG_ASSERT( nPos == nStartSearchAt ||
1019                 nId > (*pImp->pCaches)[nPos-1]->GetId(), "" );
1020     DBG_ASSERT( ( (nPos+1) >= pImp->pCaches->Count() ) ||
1021                 nId < (*pImp->pCaches)[nPos+1]->GetId(), "" );
1022     pImp->nCachedFunc2 = pImp->nCachedFunc1;
1023     pImp->nCachedFunc1 = nPos;
1024     DBG_PROFSTOP(SfxBindingsMsgPos);
1025     return nPos;
1026 }
1027 //--------------------------------------------------------------------
1028 void SfxBindings::RegisterInternal_Impl( SfxControllerItem& rItem )
1029 {
1030     Register_Impl( rItem, sal_True );
1031 
1032 }
1033 
1034 void SfxBindings::Register( SfxControllerItem& rItem )
1035 {
1036     Register_Impl( rItem, sal_False );
1037 }
1038 
1039 void SfxBindings::Register_Impl( SfxControllerItem& rItem, sal_Bool bInternal )
1040 {
1041     DBG_MEMTEST();
1042     DBG_ASSERT( nRegLevel > 0, "registration without EnterRegistrations" );
1043     DBG_ASSERT( !pImp->bInNextJob, "SfxBindings::Register while status-updating" );
1044 
1045     // insert new cache if it does not already exist
1046     sal_uInt16 nId = rItem.GetId();
1047     sal_uInt16 nPos = GetSlotPos(nId);
1048     if ( nPos >= pImp->pCaches->Count() ||
1049          (*pImp->pCaches)[nPos]->GetId() != nId )
1050     {
1051         SfxStateCache* pCache = new SfxStateCache(nId);
1052         pImp->pCaches->Insert( nPos, pCache );
1053         DBG_ASSERT( nPos == 0 ||
1054                     (*pImp->pCaches)[nPos]->GetId() >
1055                         (*pImp->pCaches)[nPos-1]->GetId(), "" );
1056         DBG_ASSERT( (nPos == pImp->pCaches->Count()-1) ||
1057                     (*pImp->pCaches)[nPos]->GetId() <
1058                         (*pImp->pCaches)[nPos+1]->GetId(), "" );
1059         pImp->bMsgDirty = sal_True;
1060     }
1061 
1062     // enqueue the new binding
1063     if ( bInternal )
1064     {
1065         (*pImp->pCaches)[nPos]->SetInternalController( &rItem );
1066     }
1067     else
1068     {
1069         SfxControllerItem *pOldItem = (*pImp->pCaches)[nPos]->ChangeItemLink(&rItem);
1070         rItem.ChangeItemLink(pOldItem);
1071     }
1072 }
1073 
1074 //--------------------------------------------------------------------
1075 
1076 void SfxBindings::Release( SfxControllerItem& rItem )
1077 {
1078     DBG_MEMTEST();
1079     DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
1080     //! DBG_ASSERT( nRegLevel > 0, "release without EnterRegistrations" );
1081     DBG_ASSERT( !pImp->bInNextJob, "SfxBindings::Release while status-updating" );
1082     ENTERREGISTRATIONS();
1083 
1084     // find the bound function
1085     sal_uInt16 nId = rItem.GetId();
1086     sal_uInt16 nPos = GetSlotPos(nId);
1087     SfxStateCache* pCache = (*pImp->pCaches)[nPos];
1088     if ( pCache->GetId() == nId )
1089     {
1090         if ( pCache->GetInternalController() == &rItem )
1091         {
1092             pCache->ReleaseInternalController();
1093         }
1094         else
1095         {
1096             // is this the first binding in the list?
1097             SfxControllerItem* pItem = pCache->GetItemLink();
1098             if ( pItem == &rItem )
1099                 pCache->ChangeItemLink( rItem.GetItemLink() );
1100             else
1101             {
1102                 // search the binding in the list
1103                 while ( pItem && pItem->GetItemLink() != &rItem )
1104                     pItem = pItem->GetItemLink();
1105 
1106                 // unlink it if it was found
1107                 if ( pItem )
1108                     pItem->ChangeItemLink( rItem.GetItemLink() );
1109             }
1110         }
1111 
1112         // was this the last controller?
1113         if ( pCache->GetItemLink() == 0 && !pCache->GetInternalController() )
1114         {
1115 #ifdef slow
1116             // remove the BoundFunc
1117             delete (*pImp->pCaches)[nPos];
1118             pImp->pCaches->Remove(nPos, 1);
1119 #endif
1120             pImp->bCtrlReleased = sal_True;
1121         }
1122     }
1123 
1124     LEAVEREGISTRATIONS();
1125 }
1126 
1127 //--------------------------------------------------------------------
1128 const SfxPoolItem* SfxBindings::ExecuteSynchron( sal_uInt16 nId, const SfxPoolItem** ppItems, sal_uInt16 nModi,
1129             const SfxPoolItem **ppInternalArgs )
1130 {
1131     DBG_MEMTEST();
1132     DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
1133 
1134     if( !nId || !pDispatcher )
1135         return NULL;
1136 
1137     return Execute_Impl( nId, ppItems, nModi, SFX_CALLMODE_SYNCHRON, ppInternalArgs );
1138 }
1139 
1140 sal_Bool SfxBindings::Execute( sal_uInt16 nId, const SfxPoolItem** ppItems, sal_uInt16 nModi, SfxCallMode nCallMode,
1141                         const SfxPoolItem **ppInternalArgs )
1142 {
1143     DBG_MEMTEST();
1144     DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
1145 
1146     if( !nId || !pDispatcher )
1147         return sal_False;
1148 
1149     const SfxPoolItem* pRet = Execute_Impl( nId, ppItems, nModi, nCallMode, ppInternalArgs );
1150     return ( pRet != 0 );
1151 }
1152 
1153 void SfxBindings::ExecuteGlobal_Impl( sal_uInt16 nId )
1154 {
1155     if( nId && pDispatcher )
1156         Execute_Impl( nId, NULL, 0, SFX_CALLMODE_ASYNCHRON, NULL, sal_True );
1157 }
1158 
1159 const SfxPoolItem* SfxBindings::Execute_Impl( sal_uInt16 nId, const SfxPoolItem** ppItems, sal_uInt16 nModi, SfxCallMode nCallMode,
1160                         const SfxPoolItem **ppInternalArgs, sal_Bool bGlobalOnly )
1161 {
1162     SfxStateCache *pCache = GetStateCache( nId );
1163     if ( !pCache )
1164     {
1165         SfxBindings *pBind = pImp->pSubBindings;
1166         while ( pBind )
1167         {
1168             if ( pBind->GetStateCache( nId ) )
1169                 return pBind->Execute_Impl( nId, ppItems, nModi, nCallMode, ppInternalArgs, bGlobalOnly );
1170             pBind = pBind->pImp->pSubBindings;
1171         };
1172     }
1173 
1174     SfxDispatcher &rDispatcher = *pDispatcher;
1175     rDispatcher.Flush();
1176     rDispatcher.GetFrame();  // -Wall is this required???
1177 
1178     // get SlotServer (Slot+ShellLevel) and Shell from cache
1179     sal_Bool bDeleteCache = sal_False;
1180     if ( !pCache )
1181     {
1182         // Execution of non cached slots (Accelerators don't use Controllers)
1183         // slot is uncached, use SlotCache to handle external dispatch providers
1184         pCache = new SfxStateCache( nId );
1185         pCache->GetSlotServer( rDispatcher, pImp->xProv );
1186         bDeleteCache = sal_True;
1187     }
1188 
1189     if ( pCache && pCache->GetDispatch().is() )
1190     {
1191 		DBG_ASSERT( !ppInternalArgs, "Internal args get lost when dispatched!" );
1192 
1193 		SfxItemPool &rPool = GetDispatcher()->GetFrame()->GetObjectShell()->GetPool();
1194 		SfxRequest aReq( nId, nCallMode, rPool );
1195 		aReq.SetModifier( nModi );
1196 		if( ppItems )
1197 			while( *ppItems )
1198 				aReq.AppendItem( **ppItems++ );
1199 
1200         // cache binds to an external dispatch provider
1201         pCache->Dispatch( aReq.GetArgs(), nCallMode == SFX_CALLMODE_SYNCHRON );
1202         if ( bDeleteCache )
1203             DELETEZ( pCache );
1204         SfxPoolItem *pVoid = new SfxVoidItem( nId );
1205         DeleteItemOnIdle( pVoid );
1206         return pVoid;
1207     }
1208 
1209     // slot is handled internally by SfxDispatcher
1210     if ( pImp->bMsgDirty )
1211         UpdateSlotServer_Impl();
1212 
1213     SfxShell *pShell=0;
1214     const SfxSlot *pSlot=0;
1215 
1216     // if slot was uncached, we should have created a cache in this method!
1217     DBG_ASSERT( pCache, "This code needs a cache!");
1218     const SfxSlotServer* pServer = pCache ? pCache->GetSlotServer( rDispatcher, pImp->xProv ) : 0;
1219     if ( !pServer )
1220     {
1221         return NULL;
1222     }
1223     else
1224     {
1225         pShell = rDispatcher.GetShell( pServer->GetShellLevel() );
1226         pSlot = pServer->GetSlot();
1227     }
1228 
1229     if ( bGlobalOnly )
1230         if ( !pShell->ISA(SfxModule) && !pShell->ISA(SfxApplication) && !pShell->ISA(SfxViewFrame) )
1231             return NULL;
1232 
1233     SfxItemPool &rPool = pShell->GetPool();
1234     SfxRequest aReq( nId, nCallMode, rPool );
1235     aReq.SetModifier( nModi );
1236     if( ppItems )
1237         while( *ppItems )
1238             aReq.AppendItem( **ppItems++ );
1239     if ( ppInternalArgs )
1240     {
1241         SfxAllItemSet aSet( rPool );
1242         for ( const SfxPoolItem **pArg = ppInternalArgs; *pArg; ++pArg )
1243             aSet.Put( **pArg );
1244         aReq.SetInternalArgs_Impl( aSet );
1245     }
1246 
1247     Execute_Impl( aReq, pSlot, pShell );
1248 
1249     const SfxPoolItem* pRet = aReq.GetReturnValue();
1250     if ( !pRet )
1251     {
1252         SfxPoolItem *pVoid = new SfxVoidItem( nId );
1253         DeleteItemOnIdle( pVoid );
1254         pRet = pVoid;
1255     }
1256 
1257     if ( bDeleteCache )
1258         delete pCache;
1259 
1260     return pRet;
1261 }
1262 
1263 void SfxBindings::Execute_Impl( SfxRequest& aReq, const SfxSlot* pSlot, SfxShell* pShell )
1264 {
1265     SfxItemPool &rPool = pShell->GetPool();
1266 
1267     if ( SFX_KIND_ENUM == pSlot->GetKind() )
1268     {
1269         // bei Enum-Slots muss der Master mit dem Wert des Enums executet werden
1270         const SfxSlot *pRealSlot = pShell->GetInterface()->GetRealSlot(pSlot);
1271         const sal_uInt16 nSlotId = pRealSlot->GetSlotId();
1272         aReq.SetSlot( nSlotId );
1273         aReq.AppendItem( SfxAllEnumItem( rPool.GetWhich(nSlotId), pSlot->GetValue() ) );
1274         pDispatcher->_Execute( *pShell, *pRealSlot, aReq, aReq.GetCallMode() | SFX_CALLMODE_RECORD );
1275     }
1276     else if ( SFX_KIND_ATTR == pSlot->GetKind() )
1277     {
1278         // bei Attr-Slots muss der Which-Wert gemapped werden
1279         const sal_uInt16 nSlotId = pSlot->GetSlotId();
1280         aReq.SetSlot( nSlotId );
1281         if ( pSlot->IsMode(SFX_SLOT_TOGGLE) )
1282         {
1283             // an togglebare-Attribs (Bools) wird der Wert angeheangt
1284             sal_uInt16 nWhich = pSlot->GetWhich(rPool);
1285             SfxItemSet aSet(rPool, nWhich, nWhich, 0);
1286             SfxStateFunc aFunc  = pSlot->GetStateFnc();
1287             pShell->CallState( aFunc, aSet );
1288             const SfxPoolItem *pOldItem;
1289             SfxItemState eState = aSet.GetItemState(nWhich, sal_True, &pOldItem);
1290             if ( eState == SFX_ITEM_DISABLED )
1291                 return;
1292 
1293             if ( SFX_ITEM_AVAILABLE == eState && SfxItemPool::IsWhich(nWhich) )
1294                 pOldItem = &aSet.Get(nWhich);
1295 
1296             if ( SFX_ITEM_SET == eState ||
1297                  ( SFX_ITEM_AVAILABLE == eState &&
1298                    SfxItemPool::IsWhich(nWhich) &&
1299                    pOldItem ) )
1300             {
1301                 if ( pOldItem->ISA(SfxBoolItem) )
1302                 {
1303                     // wir koennen Bools toggeln
1304                     sal_Bool bOldValue = ((const SfxBoolItem *)pOldItem)->GetValue();
1305                     SfxBoolItem *pNewItem = (SfxBoolItem*) (pOldItem->Clone());
1306                     pNewItem->SetValue( !bOldValue );
1307                     aReq.AppendItem( *pNewItem );
1308                     delete pNewItem;
1309                 }
1310                 else if ( pOldItem->ISA(SfxEnumItemInterface) &&
1311                         ((SfxEnumItemInterface *)pOldItem)->HasBoolValue())
1312                 {
1313                     // und Enums mit Bool-Interface
1314                     SfxEnumItemInterface *pNewItem =
1315                         (SfxEnumItemInterface*) (pOldItem->Clone());
1316                     pNewItem->SetBoolValue(!((SfxEnumItemInterface *)pOldItem)->GetBoolValue());
1317                     aReq.AppendItem( *pNewItem );
1318                     delete pNewItem;
1319                 }
1320                 else {
1321                     DBG_ERROR( "Toggle only for Enums and Bools allowed" );
1322                 }
1323             }
1324             else if ( SFX_ITEM_DONTCARE == eState )
1325             {
1326                 // ein Status-Item per Factory erzeugen
1327                 SfxPoolItem *pNewItem = pSlot->GetType()->CreateItem();
1328                 DBG_ASSERT( pNewItem, "Toggle an Slot ohne ItemFactory" );
1329                 pNewItem->SetWhich( nWhich );
1330 
1331                 if ( pNewItem->ISA(SfxBoolItem) )
1332                 {
1333                     // wir koennen Bools toggeln
1334                     ((SfxBoolItem*)pNewItem)->SetValue( sal_True );
1335                     aReq.AppendItem( *pNewItem );
1336                 }
1337                 else if ( pNewItem->ISA(SfxEnumItemInterface) &&
1338                         ((SfxEnumItemInterface *)pNewItem)->HasBoolValue())
1339                 {
1340                     // und Enums mit Bool-Interface
1341                     ((SfxEnumItemInterface*)pNewItem)->SetBoolValue(sal_True);
1342                     aReq.AppendItem( *pNewItem );
1343                 }
1344                 else {
1345                     DBG_ERROR( "Toggle only for Enums and Bools allowed" );
1346                 }
1347                 delete pNewItem;
1348             }
1349             else {
1350                 DBG_ERROR( "suspicious Toggle-Slot" );
1351             }
1352         }
1353 
1354         pDispatcher->_Execute( *pShell, *pSlot, aReq, aReq.GetCallMode() | SFX_CALLMODE_RECORD );
1355     }
1356     else
1357         pDispatcher->_Execute( *pShell, *pSlot, aReq, aReq.GetCallMode() | SFX_CALLMODE_RECORD );
1358 }
1359 
1360 //--------------------------------------------------------------------
1361 
1362 void SfxBindings::UpdateSlotServer_Impl()
1363 {
1364     DBG_PROFSTART(SfxBindingsUpdateServers);
1365     DBG_MEMTEST();
1366     DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
1367 
1368     // synchronisieren
1369     pDispatcher->Flush();
1370 //  pDispatcher->Update_Impl();
1371 
1372     if ( pImp->bAllMsgDirty )
1373     {
1374         if ( !nRegLevel )
1375         {
1376             ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame > xFrame
1377                 ( pDispatcher->GetFrame()->GetFrame().GetFrameInterface(), UNO_QUERY );
1378             //if ( xFrame.is() )
1379             //    xFrame->contextChanged();
1380             pImp->bContextChanged = sal_False;
1381         }
1382         else
1383             pImp->bContextChanged = sal_True;
1384     }
1385 
1386     const sal_uInt16 nCount = pImp->pCaches->Count();
1387     for(sal_uInt16 i = 0; i < nCount; ++i)
1388     {
1389         SfxStateCache *pCache = pImp->pCaches->GetObject(i);
1390         pCache->GetSlotServer(*pDispatcher, pImp->xProv);
1391     }
1392     pImp->bMsgDirty = pImp->bAllMsgDirty = sal_False;
1393 
1394     Broadcast( SfxSimpleHint(SFX_HINT_DOCCHANGED) );
1395 
1396     DBG_PROFSTOP(SfxBindingsUpdateServers);
1397 }
1398 
1399 //--------------------------------------------------------------------
1400 
1401 #ifdef WNT
1402 int __cdecl CmpUS_Impl(const void *p1, const void *p2)
1403 #else
1404 int CmpUS_Impl(const void *p1, const void *p2)
1405 #endif
1406 
1407 /*  [Beschreibung]
1408 
1409     Interne Vergleichsfunktion fuer qsort.
1410 */
1411 
1412 {
1413     return *(sal_uInt16 *)p1 - *(sal_uInt16 *)p2;
1414 }
1415 
1416 //--------------------------------------------------------------------
1417 
1418 SfxItemSet* SfxBindings::CreateSet_Impl
1419 (
1420     SfxStateCache*&             pCache,     // in: Status-Cache von nId
1421     const SfxSlot*&             pRealSlot,  // out: RealSlot zu nId
1422     const SfxSlotServer**    pMsgServer, // out: Slot-Server zu nId
1423     SfxFoundCacheArr_Impl&      rFound      // out: Liste der Caches der Siblings
1424 )
1425 {
1426     DBG_MEMTEST();
1427     DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
1428 
1429     DBG_ASSERT( !pImp->bMsgDirty, "CreateSet_Impl mit dirty MessageServer" );
1430 
1431     const SfxSlotServer* pMsgSvr = pCache->GetSlotServer(*pDispatcher, pImp->xProv);
1432     if(!pMsgSvr || !pDispatcher)
1433         return 0;
1434 
1435     DBG_PROFSTART(SfxBindingsCreateSet);
1436     pRealSlot = 0;
1437     *pMsgServer = pMsgSvr;
1438 
1439     sal_uInt16 nShellLevel = pMsgSvr->GetShellLevel();
1440     SfxShell *pShell = pDispatcher->GetShell( nShellLevel );
1441     if ( !pShell ) // seltener GPF beim Browsen durch Update aus Inet-Notify
1442         return 0;
1443 
1444     SfxItemPool &rPool = pShell->GetPool();
1445 
1446     // hole die Status-Methode, von der pCache bedient wird
1447     SfxStateFunc pFnc = 0;
1448     const SfxInterface *pInterface = pShell->GetInterface();
1449     if ( SFX_KIND_ENUM == pMsgSvr->GetSlot()->GetKind() )
1450     {
1451         pRealSlot = pInterface->GetRealSlot(pMsgSvr->GetSlot());
1452         pCache = GetStateCache( pRealSlot->GetSlotId() );
1453 //      DBG_ASSERT( pCache, "Kein Slotcache fuer den Masterslot gefunden!" );
1454     }
1455     else
1456         pRealSlot = pMsgSvr->GetSlot();
1457 
1458     //
1459     // Achtung: pCache darf auch NULL sein !!!
1460     //
1461 
1462     pFnc = pRealSlot->GetStateFnc();
1463 
1464     // der RealSlot ist immer drin
1465     const SfxFoundCache_Impl *pFound = new SfxFoundCache_Impl(
1466         pRealSlot->GetSlotId(), pRealSlot->GetWhich(rPool), pRealSlot, pCache );
1467     rFound.Insert( pFound );
1468 
1469     sal_uInt16 nSlot = pRealSlot->GetSlotId();
1470     if ( !(nSlot >= SID_VERB_START && nSlot <= SID_VERB_END) )
1471     {
1472         pInterface = pInterface->GetRealInterfaceForSlot( pRealSlot );
1473         DBG_ASSERT (pInterface,"Slot in angegebener Shell nicht gefunden!");
1474     }
1475 
1476     // Durchsuche die Bindings nach den von derselben Funktion bedienten Slots.
1477     // Daf"ur kommen nur Slots in Frage, die es im gefundenen Interface gibt.
1478 
1479     // Die Position des Statecaches im StateCache-Array
1480     sal_uInt16 nCachePos = pImp->nMsgPos;
1481     const SfxSlot *pSibling = pRealSlot->GetNextSlot();
1482 
1483     // Die Slots eines Interfaces sind im Kreis verkettet
1484     while ( pSibling > pRealSlot )
1485     {
1486         SfxStateFunc pSiblingFnc=0;
1487         SfxStateCache *pSiblingCache =
1488                 GetStateCache( pSibling->GetSlotId(), &nCachePos );
1489 
1490         // Ist der Slot "uberhaupt gecached ?
1491         if ( pSiblingCache )
1492         {
1493             const SfxSlotServer *pServ = pSiblingCache->GetSlotServer(*pDispatcher, pImp->xProv);
1494             if ( pServ && pServ->GetShellLevel() == nShellLevel )
1495                 pSiblingFnc = pServ->GetSlot()->GetStateFnc();
1496         }
1497 
1498         // Mu\s der Slot "uberhaupt upgedatet werden ?
1499         bool bInsert = pSiblingCache && pSiblingCache->IsControllerDirty();
1500 
1501         // Bugfix #26161#: Es reicht nicht, nach der selben Shell zu fragen !!
1502         bool bSameMethod = pSiblingCache && pFnc == pSiblingFnc;
1503 
1504         // Wenn der Slot ein nicht-dirty MasterSlot ist, dann ist vielleicht
1505         // einer seiner Slaves dirty ? Dann wird der Masterslot doch eingef"ugt.
1506         if ( !bInsert && bSameMethod && pSibling->GetLinkedSlot() )
1507         {
1508             // auch Slave-Slots auf Binding pru"fen
1509             const SfxSlot* pFirstSlave = pSibling->GetLinkedSlot();
1510             for ( const SfxSlot *pSlaveSlot = pFirstSlave;
1511                   !bInsert;
1512                   pSlaveSlot = pSlaveSlot->GetNextSlot())
1513             {
1514                 // Die Slaves zeigen auf ihren Master
1515                 DBG_ASSERT(pSlaveSlot->GetLinkedSlot() == pSibling,
1516                     "Falsche Master/Slave-Beziehung!");
1517 
1518                 sal_uInt16 nCurMsgPos = pImp->nMsgPos;
1519                 const SfxStateCache *pSlaveCache =
1520                     GetStateCache( pSlaveSlot->GetSlotId(), &nCurMsgPos );
1521 
1522                 // Ist der Slave-Slot gecached und dirty ?
1523                 bInsert = pSlaveCache && pSlaveCache->IsControllerDirty();
1524 
1525                 // Slaves sind untereinander im Kreis verkettet
1526                 if (pSlaveSlot->GetNextSlot() == pFirstSlave)
1527                     break;
1528             }
1529         }
1530 
1531         if ( bInsert && bSameMethod )
1532         {
1533             const SfxFoundCache_Impl *pFoundCache = new SfxFoundCache_Impl(
1534                 pSibling->GetSlotId(), pSibling->GetWhich(rPool),
1535                 pSibling, pSiblingCache );
1536 
1537             rFound.Insert( pFoundCache );
1538         }
1539 
1540         pSibling = pSibling->GetNextSlot();
1541     }
1542 
1543     // aus den Ranges ein Set erzeugen
1544     sal_uInt16 *pRanges = new sal_uInt16[rFound.Count() * 2 + 1];
1545     int j = 0;
1546     sal_uInt16 i = 0;
1547     while ( i < rFound.Count() )
1548     {
1549         pRanges[j++] = rFound[i]->nWhichId;
1550             // aufeinanderfolgende Zahlen
1551         for ( ; i < rFound.Count()-1; ++i )
1552             if ( rFound[i]->nWhichId+1 != rFound[i+1]->nWhichId )
1553                 break;
1554         pRanges[j++] = rFound[i++]->nWhichId;
1555     }
1556     pRanges[j] = 0; // terminierende NULL
1557     SfxItemSet *pSet = new SfxItemSet(rPool, pRanges);
1558     delete [] pRanges;
1559     DBG_PROFSTOP(SfxBindingsCreateSet);
1560     return pSet;
1561 }
1562 
1563 //--------------------------------------------------------------------
1564 
1565 void SfxBindings::UpdateControllers_Impl
1566 (
1567     const SfxInterface*         pIF,    // das diese Id momentan bedienende Interface
1568     const SfxFoundCache_Impl*   pFound, // Cache, Slot, Which etc.
1569     const SfxPoolItem*          pItem,  // item to send to controller
1570     SfxItemState                eState  // state of item
1571 )
1572 {
1573     DBG_ASSERT( !pFound->pSlot || SFX_KIND_ENUM != pFound->pSlot->GetKind(),
1574                 "direct update of enum slot isn't allowed" );
1575     DBG_PROFSTART(SfxBindingsUpdateCtrl1);
1576 
1577     SfxStateCache* pCache = pFound->pCache;
1578     const SfxSlot* pSlot = pFound->pSlot;
1579     DBG_ASSERT( !pCache || !pSlot || pCache->GetId() == pSlot->GetSlotId(), "SID mismatch" );
1580 
1581     // insofern gebunden, die Controller f"uer den Slot selbst updaten
1582     if ( pCache && pCache->IsControllerDirty() )
1583     {
1584         if ( SFX_ITEM_DONTCARE == eState )
1585         {
1586             // uneindeuting
1587             pCache->SetState( SFX_ITEM_DONTCARE, (SfxPoolItem *)-1 );
1588         }
1589         else if ( SFX_ITEM_DEFAULT == eState &&
1590                     pFound->nWhichId > SFX_WHICH_MAX )
1591         {
1592             // kein Status oder Default aber ohne Pool
1593             SfxVoidItem aVoid(0);
1594             pCache->SetState( SFX_ITEM_UNKNOWN, &aVoid );
1595         }
1596         else if ( SFX_ITEM_DISABLED == eState )
1597             pCache->SetState(SFX_ITEM_DISABLED, 0);
1598         else
1599             pCache->SetState(SFX_ITEM_AVAILABLE, pItem);
1600     }
1601 
1602     DBG_PROFSTOP(SfxBindingsUpdateCtrl1);
1603 
1604     // insofern vorhanden und gebunden, die Controller f"uer Slave-Slots
1605     // (Enum-Werte) des Slots updaten
1606     DBG_PROFSTART(SfxBindingsUpdateCtrl2);
1607     DBG_ASSERT( !pSlot || 0 == pSlot->GetLinkedSlot() || !pItem ||
1608                 pItem->ISA(SfxEnumItemInterface),
1609                 "master slot with non-enum-type found" );
1610     const SfxSlot *pFirstSlave = pSlot ? pSlot->GetLinkedSlot() : 0;
1611     if ( pIF && pFirstSlave)
1612     {
1613         // Items auf EnumItem casten
1614         const SfxEnumItemInterface *pEnumItem =
1615                 PTR_CAST(SfxEnumItemInterface,pItem);
1616         if ( eState == SFX_ITEM_AVAILABLE && !pEnumItem )
1617             eState = SFX_ITEM_DONTCARE;
1618         else
1619             eState = SfxControllerItem::GetItemState( pEnumItem );
1620 
1621         // "uber alle Slaves-Slots iterieren
1622         for ( const SfxSlot *pSlave = pFirstSlave; pSlave; pSlave = pSlave->GetNextSlot() )
1623         {
1624             DBG_ASSERT(pSlave, "Falsche SlaveSlot-Verkettung!");
1625             DBG_ASSERT(SFX_KIND_ENUM == pSlave->GetKind(),"non enum slaves aren't allowed");
1626             DBG_ASSERT(pSlave->GetMasterSlotId() == pSlot->GetSlotId(),"falscher MasterSlot!");
1627 
1628             // ist die Funktion gebunden?
1629             SfxStateCache *pEnumCache = GetStateCache( pSlave->GetSlotId() );
1630             if ( pEnumCache )
1631             {
1632                 pEnumCache->Invalidate(sal_False);
1633 
1634                 HACK(CONTROL/SELECT Kram)
1635                 if ( eState == SFX_ITEM_DONTCARE && pFound->nWhichId == 10144 )
1636                 {
1637                     SfxVoidItem aVoid(0);
1638                     pEnumCache->SetState( SFX_ITEM_UNKNOWN, &aVoid );
1639 
1640                     if (pSlave->GetNextSlot() == pFirstSlave)
1641                         break;
1642 
1643                     continue;
1644                 }
1645 
1646                 if ( SFX_ITEM_DISABLED == eState || !pEnumItem->IsEnabled( pSlave->GetSlotId()) )
1647                 {
1648                     // disabled
1649                     pEnumCache->SetState(SFX_ITEM_DISABLED, 0);
1650                 }
1651                 else if ( SFX_ITEM_AVAILABLE == eState )
1652                 {
1653                     // enum-Wert ermitteln
1654                     sal_uInt16 nValue = pEnumItem->GetEnumValue();
1655                     SfxBoolItem aBool( pFound->nWhichId, pSlave->GetValue() == nValue );
1656                     pEnumCache->SetState(SFX_ITEM_AVAILABLE, &aBool);
1657                 }
1658                 else
1659                 {
1660                     // uneindeuting
1661                     pEnumCache->SetState( SFX_ITEM_DONTCARE, (SfxPoolItem *)-1 );
1662                 }
1663             }
1664 
1665             if (pSlave->GetNextSlot() == pFirstSlave)
1666                 break;
1667         }
1668     }
1669 
1670     DBG_PROFSTOP(SfxBindingsUpdateCtrl2);
1671 }
1672 
1673 
1674 //--------------------------------------------------------------------
1675 
1676 IMPL_LINK( SfxBindings, NextJob_Impl, Timer *, pTimer )
1677 {
1678 #ifdef DBG_UTIL
1679     // on Windows very often C++ Exceptions (GPF etc.) are caught by MSVCRT or another MS library
1680     // try to get them here
1681     try
1682     {
1683 #endif
1684     const unsigned MAX_INPUT_DELAY = 200;
1685 
1686     DBG_MEMTEST();
1687     DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
1688 
1689     DBG_PROFSTART(SfxBindingsNextJob_Impl0);
1690 
1691     if ( Application::GetLastInputInterval() < MAX_INPUT_DELAY && pTimer )
1692     {
1693         pImp->aTimer.SetTimeout(TIMEOUT_UPDATING);
1694         return sal_True;
1695     }
1696 
1697     SfxApplication *pSfxApp = SFX_APP();
1698 
1699     if( pDispatcher )
1700         pDispatcher->Update_Impl();
1701 
1702     // modifying the SfxObjectInterface-stack without SfxBindings => nothing to do
1703     SfxViewFrame* pFrame = pDispatcher->GetFrame();
1704     //<!--Modified by PengYunQuan for Validity Cell Range Picker
1705 	//if ( (pFrame && pFrame->GetObjectShell()->IsInModalMode()) || pSfxApp->IsDowning() || !pImp->pCaches->Count() )
1706     if ( (pFrame && !pFrame->GetObjectShell()->AcceptStateUpdate()) || pSfxApp->IsDowning() || !pImp->pCaches->Count() )
1707     //-->Modified by PengYunQuan for Validity Cell Range Picker
1708 	{
1709         DBG_PROFSTOP(SfxBindingsNextJob_Impl0);
1710         return sal_True;
1711     }
1712     if ( !pDispatcher || !pDispatcher->IsFlushed() )
1713     {
1714         DBG_PROFSTOP(SfxBindingsNextJob_Impl0);
1715         return sal_True;
1716     }
1717 
1718     // gfs. alle Server aktualisieren / geschieht in eigener Zeitscheibe
1719     if ( pImp->bMsgDirty )
1720     {
1721         UpdateSlotServer_Impl();
1722         DBG_PROFSTOP(SfxBindingsNextJob_Impl0);
1723         return sal_False;
1724     }
1725 
1726     DBG_PROFSTOP(SfxBindingsNextJob_Impl0);
1727     DBG_PROFSTART(SfxBindingsNextJob_Impl);
1728     pImp->bAllDirty = sal_False;
1729     pImp->aTimer.SetTimeout(TIMEOUT_UPDATING);
1730 
1731     // at least 10 loops and further if more jobs are available but no input
1732     bool bPreEmptive = pTimer && !pSfxApp->Get_Impl()->nInReschedule;
1733     sal_uInt16 nLoops = 10;
1734     pImp->bInNextJob = sal_True;
1735     const sal_uInt16 nCount = pImp->pCaches->Count();
1736     while ( pImp->nMsgPos < nCount )
1737     {
1738         // iterate through the bound functions
1739         sal_Bool bJobDone = sal_False;
1740         while ( !bJobDone )
1741         {
1742             SfxStateCache* pCache = (*pImp->pCaches)[pImp->nMsgPos];
1743             DBG_ASSERT( pCache, "invalid SfxStateCache-position in job queue" );
1744             sal_Bool bWasDirty = pCache->IsControllerDirty();
1745             if ( bWasDirty )
1746             {
1747 /*
1748                 sal_Bool bSkip = sal_False;
1749                 if ( pImp->bFirstRound )
1750                 {
1751                     // Falls beim Update eine Shell vorgezogen werden soll,
1752                     // kommt in einer ersten Update-Runde nur diese dran
1753                     const SfxSlotServer *pMsgServer =
1754                         pCache->GetSlotServer(*pDispatcher, pImp->xProv);
1755                     if ( pMsgServer &&
1756                         pMsgServer->GetShellLevel() != pImp->nFirstShell )
1757                             bSkip = sal_True;
1758                 }
1759 
1760                 if ( !bSkip )
1761                 {
1762 */
1763                     Update_Impl( pCache );
1764                     DBG_ASSERT( nCount == pImp->pCaches->Count(),
1765                             "Reschedule in StateChanged => buff" );
1766 //              }
1767             }
1768 
1769             // skip to next function binding
1770             ++pImp->nMsgPos;
1771 
1772             // keep job if it is not completed, but any input is available
1773             bJobDone = pImp->nMsgPos >= nCount;
1774             if ( bJobDone && pImp->bFirstRound )
1775             {
1776                 // Update der bevorzugten Shell ist gelaufen, nun d"urfen
1777                 // auch die anderen
1778                 bJobDone = sal_False;
1779                 pImp->bFirstRound = sal_False;
1780                 pImp->nMsgPos = 0;
1781             }
1782 
1783             if ( bWasDirty && !bJobDone && bPreEmptive && (--nLoops == 0) )
1784             {
1785                 DBG_PROFSTOP(SfxBindingsNextJob_Impl);
1786                 pImp->bInNextJob = sal_False;
1787                 return sal_False;
1788             }
1789         }
1790     }
1791 
1792     pImp->nMsgPos = 0;
1793 
1794 	// check for volatile slots
1795 	bool bVolatileSlotsPresent = false;
1796     for ( sal_uInt16 n = 0; n < nCount; ++n )
1797     {
1798         SfxStateCache* pCache = (*pImp->pCaches)[n];
1799         const SfxSlotServer *pSlotServer = pCache->GetSlotServer(*pDispatcher, pImp->xProv);
1800         if ( pSlotServer && pSlotServer->GetSlot()->IsMode(SFX_SLOT_VOLATILE) )
1801 		{
1802             pCache->Invalidate(sal_False);
1803 			bVolatileSlotsPresent = true;
1804 		}
1805     }
1806 
1807 	if (bVolatileSlotsPresent)
1808 		pImp->aTimer.SetTimeout(TIMEOUT_IDLE);
1809 	else
1810 		pImp->aTimer.Stop();
1811 
1812     // Update-Runde ist beendet
1813     pImp->bInNextJob = sal_False;
1814     Broadcast(SfxSimpleHint(SFX_HINT_UPDATEDONE));
1815     DBG_PROFSTOP(SfxBindingsNextJob_Impl);
1816     return sal_True;
1817 #ifdef DBG_UTIL
1818     }
1819     catch (...)
1820     {
1821         DBG_ERROR("C++ exception caught!");
1822         pImp->bInNextJob = sal_False;
1823     }
1824 
1825     return sal_False;
1826 #endif
1827 }
1828 
1829 //--------------------------------------------------------------------
1830 
1831 sal_uInt16 SfxBindings::EnterRegistrations(const char *pFile, int nLine)
1832 {
1833     (void)pFile;
1834     (void)nLine;
1835     DBG_MEMTEST();
1836 #ifdef DBG_UTIL
1837     ByteString aMsg;
1838     aMsg.Fill( Min(nRegLevel, sal_uInt16(8) ) );
1839     aMsg += "this = ";
1840     aMsg += ByteString::CreateFromInt32((long)this);
1841     aMsg += " Level = ";
1842     aMsg += ByteString::CreateFromInt32(nRegLevel);
1843     aMsg += " SfxBindings::EnterRegistrations ";
1844     if(pFile) {
1845         aMsg += "File: ";
1846         aMsg += pFile;
1847         aMsg += " Line: ";
1848         aMsg += ByteString::CreateFromInt32(nLine);
1849     }
1850 //    FILE* pLog = fopen( "c:\\bindings.log", "a+w" );
1851 //    fwrite( aMsg.GetBuffer(), 1, aMsg.Len(), pLog );
1852 //    fclose( pLog );
1853     DbgTrace( aMsg.GetBuffer() );
1854 #endif
1855 
1856     // Wenn Bindings gelockt werden, auch SubBindings locken
1857     if ( pImp->pSubBindings )
1858     {
1859         pImp->pSubBindings->ENTERREGISTRATIONS();
1860 
1861         // Dieses EnterRegistrations ist f"ur die SubBindings kein "echtes"
1862         pImp->pSubBindings->pImp->nOwnRegLevel--;
1863 
1864         // Bindings synchronisieren
1865         pImp->pSubBindings->nRegLevel = nRegLevel + pImp->pSubBindings->pImp->nOwnRegLevel + 1;
1866     }
1867 
1868     pImp->nOwnRegLevel++;
1869 
1870     // check if this is the outer most level
1871     if ( ++nRegLevel == 1 )
1872     {
1873         // stop background-processing
1874         pImp->aTimer.Stop();
1875 
1876         // flush the cache
1877         pImp->nCachedFunc1 = 0;
1878         pImp->nCachedFunc2 = 0;
1879 
1880         // merken, ob ganze Caches verschwunden sind
1881         pImp->bCtrlReleased = sal_False;
1882     }
1883 
1884     return nRegLevel;
1885 }
1886 //--------------------------------------------------------------------
1887 
1888 void SfxBindings::LeaveRegistrations( sal_uInt16 nLevel, const char *pFile, int nLine )
1889 {
1890     (void)nLevel; // unused variable
1891     (void)pFile;
1892     (void)nLine;
1893     DBG_MEMTEST();
1894     DBG_ASSERT( nRegLevel, "Leave without Enter" );
1895     DBG_ASSERT( nLevel == USHRT_MAX || nLevel == nRegLevel, "wrong Leave" );
1896 
1897     // Nur wenn die SubBindings noch von den SuperBindings gelockt sind, diesen Lock entfernen
1898     // ( d.h. wenn es mehr Locks als "echte" Locks dort gibt )
1899     if ( pImp->pSubBindings && pImp->pSubBindings->nRegLevel > pImp->pSubBindings->pImp->nOwnRegLevel )
1900     {
1901         // Bindings synchronisieren
1902         pImp->pSubBindings->nRegLevel = nRegLevel + pImp->pSubBindings->pImp->nOwnRegLevel;
1903 
1904         // Dieses LeaveRegistrations ist f"ur die SubBindings kein "echtes"
1905         pImp->pSubBindings->pImp->nOwnRegLevel++;
1906         pImp->pSubBindings->LEAVEREGISTRATIONS();
1907     }
1908 
1909     pImp->nOwnRegLevel--;
1910 
1911     // check if this is the outer most level
1912     if ( --nRegLevel == 0 && !SFX_APP()->IsDowning() )
1913     {
1914         if ( pImp->bContextChanged )
1915         {
1916             pImp->bContextChanged = sal_False;
1917             /*
1918             ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame > xFrame
1919                 ( pDispatcher->GetFrame()->GetFrame().GetFrameInterface(), UNO_QUERY );
1920             if ( xFrame.is() )
1921                 xFrame->contextChanged();*/
1922         }
1923 
1924 #ifndef slow
1925         SfxViewFrame* pFrame = pDispatcher->GetFrame();
1926 
1927         // ggf unbenutzte Caches entfernen bzw. PlugInInfo aufbereiten
1928         if ( pImp->bCtrlReleased )
1929         {
1930             for ( sal_uInt16 nCache = pImp->pCaches->Count(); nCache > 0; --nCache )
1931             {
1932                 // Cache via ::com::sun::star::sdbcx::Index besorgen
1933                 SfxStateCache *pCache = pImp->pCaches->GetObject(nCache-1);
1934 
1935                 // kein Controller mehr interessiert
1936                 if ( pCache->GetItemLink() == 0 && !pCache->GetInternalController() )
1937                 {
1938                     // Cache entfernen. Safety: first remove and then delete
1939                     SfxStateCache* pSfxStateCache = (*pImp->pCaches)[nCache-1];
1940                     pImp->pCaches->Remove(nCache-1, 1);
1941                     delete pSfxStateCache;
1942                 }
1943                 else
1944                 {
1945                     // neue Controller mit den alten Items benachrichtigen
1946                     //!pCache->SetCachedState();
1947                 }
1948             }
1949         }
1950 #endif
1951         // restart background-processing
1952         pImp->nMsgPos = 0;
1953         if ( !pFrame || !pFrame->GetObjectShell() )
1954             return;
1955         if ( pImp->pCaches && pImp->pCaches->Count() )
1956         {
1957             pImp->aTimer.Stop();
1958             pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
1959             pImp->aTimer.Start();
1960 //          pImp->bFirstRound = sal_True;
1961         }
1962     }
1963 
1964 #ifdef DBG_UTIL
1965     ByteString aMsg;
1966     aMsg.Fill( Min(nRegLevel, sal_uInt16(8)) );
1967     aMsg += "this = ";
1968     aMsg += ByteString::CreateFromInt32((long)this);
1969     aMsg += " Level = ";
1970     aMsg += ByteString::CreateFromInt32(nRegLevel);
1971     aMsg += " SfxBindings::LeaveRegistrations ";
1972     if(pFile) {
1973         aMsg += "File: ";
1974         aMsg += pFile;
1975         aMsg += " Line: ";
1976         aMsg += ByteString::CreateFromInt32(nLine);
1977     }
1978 //    FILE* pLog = fopen( "c:\\bindings.log", "a+w" );
1979 //    fwrite( aMsg.GetBuffer(), 1, aMsg.Len(), pLog );
1980 //    fclose( pLog );
1981     DbgTrace( aMsg.GetBuffer() );
1982 #endif
1983 }
1984 
1985 //--------------------------------------------------------------------
1986 
1987 const SfxSlot* SfxBindings::GetSlot(sal_uInt16 nSlotId)
1988 {
1989     DBG_MEMTEST();
1990     DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
1991 
1992     // syncronisieren
1993     pDispatcher->Flush();
1994     if ( pImp->bMsgDirty )
1995         UpdateSlotServer_Impl();
1996 
1997     // get the cache for the specified function; return if not bound
1998     SfxStateCache* pCache = GetStateCache(nSlotId);
1999     return pCache && pCache->GetSlotServer(*pDispatcher, pImp->xProv)?
2000             pCache->GetSlotServer(*pDispatcher, pImp->xProv)->GetSlot(): 0;
2001 }
2002 
2003 //--------------------------------------------------------------------
2004 
2005 void SfxBindings::SetDispatcher( SfxDispatcher *pDisp )
2006 {
2007     SfxDispatcher *pOldDispat = pDispatcher;
2008     if ( pDisp != pDispatcher )
2009     {
2010         if ( pOldDispat )
2011         {
2012             SfxBindings* pBind = pOldDispat->GetBindings();
2013             while ( pBind )
2014             {
2015                 if ( pBind->pImp->pSubBindings == this && pBind->pDispatcher != pDisp )
2016                     pBind->SetSubBindings_Impl( NULL );
2017                 pBind = pBind->pImp->pSubBindings;
2018             }
2019         }
2020 
2021         pDispatcher = pDisp;
2022 
2023         ::com::sun::star::uno::Reference < ::com::sun::star::frame::XDispatchProvider > xProv;
2024         if ( pDisp )
2025             xProv = ::com::sun::star::uno::Reference < ::com::sun::star::frame::XDispatchProvider >
2026                                         ( pDisp->GetFrame()->GetFrame().GetFrameInterface(), UNO_QUERY );
2027 
2028         SetDispatchProvider_Impl( xProv );
2029         InvalidateAll( sal_True );
2030         InvalidateUnoControllers_Impl();
2031 
2032         if ( pDispatcher && !pOldDispat )
2033         {
2034             if ( pImp->pSubBindings && pImp->pSubBindings->pDispatcher != pOldDispat )
2035             {
2036                 DBG_ERROR( "SubBindings vor Aktivieren schon gesetzt!" );
2037                 pImp->pSubBindings->ENTERREGISTRATIONS();
2038             }
2039             LEAVEREGISTRATIONS();
2040         }
2041         else if( !pDispatcher )
2042         {
2043             ENTERREGISTRATIONS();
2044             if ( pImp->pSubBindings && pImp->pSubBindings->pDispatcher != pOldDispat )
2045             {
2046                 DBG_ERROR( "SubBindings im Deaktivieren immer noch gesetzt!" );
2047                 pImp->pSubBindings->LEAVEREGISTRATIONS();
2048             }
2049         }
2050 
2051         Broadcast( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
2052 
2053         if ( pDisp )
2054         {
2055             SfxBindings* pBind = pDisp->GetBindings();
2056             while ( pBind && pBind != this )
2057             {
2058                 if ( !pBind->pImp->pSubBindings )
2059                 {
2060                     pBind->SetSubBindings_Impl( this );
2061                     break;
2062                 }
2063 
2064                 pBind = pBind->pImp->pSubBindings;
2065             }
2066         }
2067     }
2068 }
2069 
2070 //--------------------------------------------------------------------
2071 
2072 void SfxBindings::ClearCache_Impl( sal_uInt16 nSlotId )
2073 {
2074     GetStateCache(nSlotId)->ClearCache();
2075 }
2076 
2077 //--------------------------------------------------------------------
2078 void SfxBindings::StartUpdate_Impl( sal_Bool bComplete )
2079 {
2080     if ( pImp->pSubBindings )
2081         pImp->pSubBindings->StartUpdate_Impl( bComplete );
2082 
2083     if ( !bComplete )
2084         // Update darf unterbrochen werden
2085         NextJob_Impl(&pImp->aTimer);
2086     else
2087         // alle Slots am St"uck updaten
2088         NextJob_Impl(0);
2089 }
2090 
2091 //-------------------------------------------------------------------------
2092 
2093 SfxItemState SfxBindings::QueryState( sal_uInt16 nSlot, SfxPoolItem* &rpState )
2094 {
2095     ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch >  xDisp;
2096     SfxStateCache *pCache = GetStateCache( nSlot );
2097     if ( pCache )
2098         xDisp = pCache->GetDispatch();
2099     if ( xDisp.is() || !pCache )
2100     {
2101         const SfxSlot* pSlot = SfxSlotPool::GetSlotPool( pDispatcher->GetFrame() ).GetSlot( nSlot );
2102         if ( !pSlot || !pSlot->pUnoName )
2103             return SFX_ITEM_DISABLED;
2104 
2105         ::com::sun::star::util::URL aURL;
2106         ::rtl::OUString aCmd( DEFINE_CONST_UNICODE(".uno:"));
2107         aURL.Protocol = aCmd;
2108         aURL.Path = ::rtl::OUString::createFromAscii(pSlot->GetUnoName());
2109         aCmd += aURL.Path;
2110         aURL.Complete = aCmd;
2111         aURL.Main = aCmd;
2112 
2113         if ( !xDisp.is() )
2114             xDisp = pImp->xProv->queryDispatch( aURL, ::rtl::OUString(), 0 );
2115 
2116         if ( xDisp.is() )
2117         {
2118             ::com::sun::star::uno::Reference< ::com::sun::star::lang::XUnoTunnel > xTunnel( xDisp, ::com::sun::star::uno::UNO_QUERY );
2119             SfxOfficeDispatch* pDisp = NULL;
2120             if ( xTunnel.is() )
2121             {
2122                 sal_Int64 nImplementation = xTunnel->getSomething(SfxOfficeDispatch::impl_getStaticIdentifier());
2123                 pDisp = reinterpret_cast< SfxOfficeDispatch* >( sal::static_int_cast< sal_IntPtr >( nImplementation ));
2124             }
2125 
2126             if ( !pDisp )
2127             {
2128                 sal_Bool bDeleteCache = sal_False;
2129                 if ( !pCache )
2130                 {
2131                     pCache = new SfxStateCache( nSlot );
2132                     pCache->GetSlotServer( *GetDispatcher_Impl(), pImp->xProv );
2133                     bDeleteCache = sal_True;
2134                 }
2135 
2136                 SfxItemState eState = SFX_ITEM_SET;
2137                 SfxPoolItem *pItem=NULL;
2138                 BindDispatch_Impl *pBind = new BindDispatch_Impl( xDisp, aURL, pCache, pSlot );
2139                 pBind->acquire();
2140                 xDisp->addStatusListener( pBind, aURL );
2141                 if ( !pBind->GetStatus().IsEnabled )
2142                 {
2143                     eState = SFX_ITEM_DISABLED;
2144                 }
2145                 else
2146                 {
2147                     ::com::sun::star::uno::Any aAny = pBind->GetStatus().State;
2148                     ::com::sun::star::uno::Type pType = aAny.getValueType();
2149 
2150                     if ( pType == ::getBooleanCppuType() )
2151                     {
2152                         sal_Bool bTemp = false;
2153                         aAny >>= bTemp ;
2154                         pItem = new SfxBoolItem( nSlot, bTemp );
2155                     }
2156                     else if ( pType == ::getCppuType((const sal_uInt16*)0) )
2157                     {
2158                         sal_uInt16 nTemp = 0;
2159                         aAny >>= nTemp ;
2160                         pItem = new SfxUInt16Item( nSlot, nTemp );
2161                     }
2162                     else if ( pType == ::getCppuType((const sal_uInt32*)0) )
2163                     {
2164                         sal_uInt32 nTemp = 0;
2165                         aAny >>= nTemp ;
2166                         pItem = new SfxUInt32Item( nSlot, nTemp );
2167                     }
2168                     else if ( pType == ::getCppuType((const ::rtl::OUString*)0) )
2169                     {
2170                         ::rtl::OUString sTemp ;
2171                         aAny >>= sTemp ;
2172                         pItem = new SfxStringItem( nSlot, sTemp );
2173                     }
2174                     else
2175                         pItem = new SfxVoidItem( nSlot );
2176                 }
2177 
2178                 xDisp->removeStatusListener( pBind, aURL );
2179                 pBind->Release();
2180                 rpState = pItem;
2181                 if ( bDeleteCache )
2182                     DELETEZ( pCache );
2183                 return eState;
2184             }
2185         }
2186     }
2187 
2188     // Dann am Dispatcher testen; da die von dort zur"uckgegebenen Items immer
2189     // DELETE_ON_IDLE sind, mu\s eine Kopie davon gezogen werden, um einen
2190     // Eigent"umer"ubergang zu erm"oglichen
2191     const SfxPoolItem *pItem = NULL;
2192     SfxItemState eState = pDispatcher->QueryState( nSlot, pItem );
2193     if ( eState == SFX_ITEM_SET )
2194     {
2195         DBG_ASSERT( pItem, "SFX_ITEM_SET aber kein Item!" );
2196         if ( pItem )
2197             rpState = pItem->Clone();
2198     }
2199     else if ( eState == SFX_ITEM_AVAILABLE && pItem )
2200     {
2201         rpState = pItem->Clone();
2202     }
2203 
2204     return eState;
2205 }
2206 
2207 void SfxBindings::SetSubBindings_Impl( SfxBindings *pSub )
2208 {
2209     if ( pImp->pSubBindings )
2210     {
2211         pImp->pSubBindings->SetDispatchProvider_Impl( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > () );
2212         pImp->pSubBindings->pImp->pSuperBindings = NULL;
2213     }
2214 
2215     pImp->pSubBindings = pSub;
2216 
2217     if ( pSub )
2218     {
2219         pImp->pSubBindings->SetDispatchProvider_Impl( pImp->xProv );
2220         pSub->pImp->pSuperBindings = this;
2221     }
2222 }
2223 
2224 SfxBindings* SfxBindings::GetSubBindings_Impl( sal_Bool bTop ) const
2225 {
2226     SfxBindings *pRet = pImp->pSubBindings;
2227     if ( bTop )
2228     {
2229         while ( pRet->pImp->pSubBindings )
2230             pRet = pRet->pImp->pSubBindings;
2231     }
2232 
2233     return pRet;
2234 }
2235 
2236 void SfxBindings::SetWorkWindow_Impl( SfxWorkWindow* pWork )
2237 {
2238     pImp->pWorkWin = pWork;
2239 }
2240 
2241 SfxWorkWindow* SfxBindings::GetWorkWindow_Impl() const
2242 {
2243     return pImp->pWorkWin;
2244 }
2245 
2246 void SfxBindings::RegisterUnoController_Impl( SfxUnoControllerItem* pControl )
2247 {
2248     if ( !pImp->pUnoCtrlArr )
2249         pImp->pUnoCtrlArr = new SfxUnoControllerArr_Impl;
2250     pImp->pUnoCtrlArr->Insert( pControl, pImp->pUnoCtrlArr->Count() );
2251 }
2252 
2253 void SfxBindings::ReleaseUnoController_Impl( SfxUnoControllerItem* pControl )
2254 {
2255     if ( pImp->pUnoCtrlArr )
2256     {
2257         sal_uInt16 nPos = pImp->pUnoCtrlArr->GetPos( pControl );
2258         if ( nPos != 0xFFFF )
2259         {
2260             pImp->pUnoCtrlArr->Remove( nPos );
2261             return;
2262         }
2263     }
2264 
2265     if ( pImp->pSubBindings )
2266         pImp->pSubBindings->ReleaseUnoController_Impl( pControl );
2267 }
2268 
2269 void SfxBindings::InvalidateUnoControllers_Impl()
2270 {
2271     if ( pImp->pUnoCtrlArr )
2272     {
2273         sal_uInt16 nCount = pImp->pUnoCtrlArr->Count();
2274         for ( sal_uInt16 n=nCount; n>0; n-- )
2275         {
2276             SfxUnoControllerItem *pCtrl = (*pImp->pUnoCtrlArr)[n-1];
2277             ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener >  xRef( (::cppu::OWeakObject*)pCtrl, ::com::sun::star::uno::UNO_QUERY );
2278             pCtrl->ReleaseDispatch();
2279             pCtrl->GetNewDispatch();
2280         }
2281     }
2282 
2283     if ( pImp->pSubBindings )
2284         pImp->pSubBindings->InvalidateUnoControllers_Impl();
2285 }
2286 
2287 sal_Bool SfxBindings::IsInUpdate() const
2288 {
2289     sal_Bool bInUpdate = pImp->bInUpdate;
2290     if ( !bInUpdate && pImp->pSubBindings )
2291         bInUpdate = pImp->pSubBindings->IsInUpdate();
2292     return bInUpdate;
2293 }
2294 
2295 void SfxBindings::SetVisibleState( sal_uInt16 nId, sal_Bool bShow )
2296 {
2297     ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch >  xDisp;
2298     SfxStateCache *pCache = GetStateCache( nId );
2299     if ( pCache )
2300         pCache->SetVisibleState( bShow );
2301 }
2302 
2303 void SfxBindings::SetActiveFrame( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > & rFrame )
2304 {
2305     if ( rFrame.is() || !pDispatcher )
2306         SetDispatchProvider_Impl( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > ( rFrame, ::com::sun::star::uno::UNO_QUERY ) );
2307     else
2308         SetDispatchProvider_Impl( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > (
2309             pDispatcher->GetFrame()->GetFrame().GetFrameInterface(), ::com::sun::star::uno::UNO_QUERY ) );
2310 }
2311 
2312 const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > SfxBindings::GetActiveFrame() const
2313 {
2314     const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xFrame( pImp->xProv, ::com::sun::star::uno::UNO_QUERY );
2315     if ( xFrame.is() || !pDispatcher )
2316         return xFrame;
2317     else
2318         return pDispatcher->GetFrame()->GetFrame().GetFrameInterface();
2319 }
2320 
2321 void SfxBindings::SetDispatchProvider_Impl( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > & rProv )
2322 {
2323     sal_Bool bInvalidate = ( rProv != pImp->xProv );
2324     if ( bInvalidate )
2325     {
2326         pImp->xProv = rProv;
2327         InvalidateAll( sal_True );
2328         InvalidateUnoControllers_Impl();
2329     }
2330 
2331     if ( pImp->pSubBindings )
2332         pImp->pSubBindings->SetDispatchProvider_Impl( pImp->xProv );
2333 }
2334 
2335 const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > & SfxBindings::GetDispatchProvider_Impl() const
2336 {
2337     return pImp->xProv;
2338 }
2339 
2340 SystemWindow* SfxBindings::GetSystemWindow() const
2341 {
2342     SfxViewFrame *pFrame = pDispatcher->GetFrame();
2343     while ( pFrame->GetParentViewFrame_Impl() )
2344         pFrame = pFrame->GetParentViewFrame_Impl();
2345     SfxViewFrame* pTop = pFrame->GetTopViewFrame();
2346     return pTop->GetFrame().GetTopWindow_Impl();
2347 }
2348 
2349 sal_Bool SfxBindings::ExecuteCommand_Impl( const String& rCommand )
2350 {
2351     ::com::sun::star::util::URL aURL;
2352     aURL.Complete = rCommand;
2353     Reference < XURLTransformer > xTrans( ::comphelper::getProcessServiceFactory()->createInstance( rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer" )), UNO_QUERY );
2354     xTrans->parseStrict( aURL );
2355     ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch >  xDisp = pImp->xProv->queryDispatch( aURL, ::rtl::OUString(), 0 );
2356     if ( xDisp.is() )
2357     {
2358         if(::comphelper::UiEventsLogger::isEnabled()) //#i88653#
2359         {
2360             ::rtl::OUString sAppName;
2361             try
2362             {
2363                 static ::rtl::OUString our_aModuleManagerName = ::rtl::OUString::createFromAscii("com.sun.star.frame.ModuleManager");
2364                 ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceManager =
2365                     ::comphelper::getProcessServiceFactory();
2366                 ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModuleManager > xModuleManager(
2367                     xServiceManager->createInstance(our_aModuleManagerName)
2368                     , ::com::sun::star::uno::UNO_QUERY_THROW);
2369                 ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame > xFrame(
2370                     pDispatcher->GetFrame()->GetFrame().GetFrameInterface(), UNO_QUERY_THROW);
2371                 sAppName = xModuleManager->identify(xFrame);
2372             } catch(::com::sun::star::uno::Exception&) {}
2373             Sequence<beans::PropertyValue> source;
2374             ::comphelper::UiEventsLogger::appendDispatchOrigin(source, sAppName, ::rtl::OUString::createFromAscii("SfxAsyncExec"));
2375             ::comphelper::UiEventsLogger::logDispatch(aURL, source);
2376         }
2377         new SfxAsyncExec_Impl( aURL, xDisp );
2378         return sal_True;
2379     }
2380 
2381     return sal_False;
2382 }
2383 
2384 com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > SfxBindings::GetRecorder() const
2385 {
2386     return pImp->xRecorder;
2387 }
2388 
2389 void SfxBindings::SetRecorder_Impl( com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder >& rRecorder )
2390 {
2391     pImp->xRecorder = rRecorder;
2392 }
2393 
2394 void SfxBindings::ContextChanged_Impl()
2395 {
2396     if ( !pImp->bInUpdate && ( !pImp->bContextChanged || !pImp->bAllMsgDirty ) )
2397     {
2398         InvalidateAll( sal_True );
2399     }
2400 }
2401 
2402 uno::Reference < frame::XDispatch > SfxBindings::GetDispatch( const SfxSlot* pSlot, const util::URL& aURL, sal_Bool bMasterCommand )
2403 {
2404     uno::Reference < frame::XDispatch > xRet;
2405     SfxStateCache* pCache = GetStateCache( pSlot->nSlotId );
2406     if ( pCache && !bMasterCommand )
2407         xRet = pCache->GetInternalDispatch();
2408     if ( !xRet.is() )
2409     {
2410         // dispatches for slaves are unbound, they don't have a state
2411         SfxOfficeDispatch* pDispatch = bMasterCommand ?
2412             new SfxOfficeDispatch( pDispatcher, pSlot, aURL ) :
2413             new SfxOfficeDispatch( *this, pDispatcher, pSlot, aURL );
2414 
2415         pDispatch->SetMasterUnoCommand( bMasterCommand );
2416         xRet = uno::Reference < frame::XDispatch >( pDispatch );
2417         if ( !pCache )
2418             pCache = GetStateCache( pSlot->nSlotId );
2419 
2420         DBG_ASSERT( pCache, "No cache for OfficeDispatch!" );
2421         if ( pCache && !bMasterCommand )
2422             pCache->SetInternalDispatch( xRet );
2423     }
2424 
2425     return xRet;
2426 }
2427