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