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