xref: /trunk/main/sfx2/source/control/dispatch.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sfx2.hxx"
30 #include <com/sun/star/beans/XPropertySet.hpp>
31 #include <com/sun/star/frame/XDispatchRecorderSupplier.hpp>
32 #include <com/sun/star/frame/XLayoutManager.hpp>
33 #include <svl/itempool.hxx>
34 #include <svl/itemiter.hxx>
35 #include <svl/whiter.hxx>
36 #include <svl/intitem.hxx>
37 #ifndef _SFXEITEM_HXX //autogen
38 #include <svl/eitem.hxx>
39 #endif
40 #include <svl/undo.hxx>
41 #ifndef _WRKWIN_HXX //autogen
42 #include <vcl/wrkwin.hxx>
43 #endif
44 #include <svtools/ttprops.hxx>
45 #include <stdio.h>
46 #include <stdarg.h>
47 #include <stdlib.h>             // wg. bsearch
48 
49 #define _SVSTDARR_ULONGS
50 #include <svl/svstdarr.hxx>
51 #include <svtools/helpopt.hxx>
52 #include <com/sun/star/frame/XLayoutManager.hpp>
53 #include <com/sun/star/beans/XPropertySet.hpp>
54 
55 #ifndef GCC
56 #endif
57 
58 // wg. nAutoPageID
59 #include "appdata.hxx"
60 #include "sfx2/sfxhelp.hxx"
61 #include <sfx2/dispatch.hxx>
62 #include <sfx2/minstack.hxx>
63 #include <sfx2/msg.hxx>
64 #include <sfx2/objface.hxx>
65 #include <sfx2/bindings.hxx>
66 #include <sfx2/request.hxx>
67 #include <sfx2/app.hxx>
68 #include <sfx2/hintpost.hxx>
69 #include "slotserv.hxx"
70 #include <sfx2/ipclient.hxx>
71 #include "sfxtypes.hxx"
72 #include <sfx2/viewfrm.hxx>
73 #include <sfx2/viewsh.hxx>
74 #include <sfx2/childwin.hxx>
75 #include <sfx2/docfac.hxx>
76 #include <sfx2/msgpool.hxx>
77 #include <sfx2/module.hxx>
78 #include <sfx2/viewfrm.hxx>
79 #include <sfx2/sfxuno.hxx>
80 #include <sfx2/docfile.hxx>
81 #include <sfx2/mnumgr.hxx>
82 #include "workwin.hxx"
83 
84 namespace css = ::com::sun::star;
85 
86 //==================================================================
87 DBG_NAME(SfxDispatcherFlush)
88 DBG_NAME(SfxDispatcherFillState)
89 
90 //==================================================================
91 typedef SfxRequest* SfxRequestPtr;
92 SV_IMPL_PTRARR( SfxItemPtrArray, SfxPoolItemPtr );
93 SV_DECL_PTRARR_DEL( SfxRequestPtrArray, SfxRequestPtr, 4, 4 )
94 SV_IMPL_PTRARR( SfxRequestPtrArray, SfxRequestPtr );
95 
96 DECL_PTRSTACK(SfxShellStack_Impl, SfxShell*, 8, 4 );
97 //==================================================================
98 
99 struct SfxToDo_Impl
100 {
101     SfxShell*           pCluster;
102     bool                bPush;
103     bool                bDelete;
104     bool                bUntil;
105 
106     SfxToDo_Impl()
107         : pCluster(0)
108         , bPush(false)
109         , bDelete(false)
110         , bUntil(false)
111                 {}
112     SfxToDo_Impl( bool bOpPush, bool bOpDelete, bool bOpUntil, SfxShell& rCluster )
113         : pCluster(&rCluster)
114         , bPush(bOpPush)
115         , bDelete(bOpDelete)
116         , bUntil(bOpUntil)
117                 {}
118     ~SfxToDo_Impl(){}
119 
120     bool operator==( const SfxToDo_Impl& rWith ) const
121     { return pCluster==rWith.pCluster && bPush==rWith.bPush; }
122 };
123 
124 DECL_OBJSTACK(SfxToDoStack_Impl, SfxToDo_Impl, 8, 4);
125 IMPL_OBJSTACK(SfxToDoStack_Impl, SfxToDo_Impl);
126 
127 struct SfxObjectBars_Impl
128 {
129     sal_uInt32          nResId; // Resource - und ConfigId der Toolbox
130     sal_uInt16          nMode;  // spezielle Sichtbarkeitsflags
131     String              aName;
132     SfxInterface*       pIFace;
133 
134     SfxObjectBars_Impl() :
135         nResId( 0 )
136     {}
137 };
138 
139 //------------------------------------------------------------------
140 
141 struct SfxDispatcher_Impl
142 {
143     SfxRequestPtrArray      aReqArr;
144     const SfxSlotServer* pCachedServ1;       // zuletzt gerufene Message
145     const SfxSlotServer* pCachedServ2;       // vorletzt gerufene Message
146     SfxShellStack_Impl      aStack;             // aktive Funktionalitaet
147     Timer                   aTimer;             // fuers flushen
148     SfxToDoStack_Impl       aToDoStack;         // nicht abgearb. Push/Pop
149     SfxViewFrame*           pFrame;             // 0 oder zugeh"or. Frame
150     SfxDispatcher*          pParent;            // z.B. AppDispatcher, ggf. 0
151     SfxHintPosterRef        xPoster;            // asynchrones Execute
152     sal_Bool                    bFlushing;          // sal_True waehrend Flush //?
153     sal_Bool                    bUpdated;           // Update_Impl gelaufen
154     sal_Bool                    bLocked;            // kein Execute
155     sal_Bool                    bInvalidateOnUnlock;// da fragte jemand
156     sal_Bool                    bActive;            // nicht verwechseln mit gesetzt!
157     sal_Bool*                   pInCallAliveFlag;   // dem Stack den Dtor anzeigen
158     SfxObjectBars_Impl      aObjBars[SFX_OBJECTBAR_MAX];
159     SfxObjectBars_Impl      aFixedObjBars[SFX_OBJECTBAR_MAX];
160     SvULongs                aChildWins;
161     sal_uInt32                  nEventId;           // EventId UserEvent
162     sal_Bool                    bUILocked;          // Update abgeklemmt (!zappeln)
163     sal_Bool                    bNoUI;              // UI nur vom Parent Dispatcher
164     sal_Bool                    bReadOnly;          // Dokument ist ReadOnly
165     sal_Bool                    bQuiet;             // nur parent dispatcher verwenden
166     sal_Bool                    bModal;             // nur Slots vom Parent-Dispatcher
167 
168     sal_Bool                    bFilterEnabling;    // sal_True=filter enabled slots, 2==ReadOnlyDoc uebersteuert
169     sal_uInt16                  nFilterCount;       // Anzahl der SIDs in pFilterSIDs
170     const sal_uInt16*           pFilterSIDs;        // sortiertes Array von SIDs
171     sal_uInt16                  nStandardMode;      // ExecuteMode f. PlugInDispatcher
172     SvUShorts*              pDisableList;
173     sal_uInt32                  nDisableFlags;
174 };
175 
176 #define NO_OBJECTBAR    0
177 #define OWN_OBJECTBAR   1
178 #define OTHER_OBJECTBAR 2
179 
180 //------------------------------------------------------------------
181 
182 #define SFX_FLUSH_TIMEOUT    50
183 
184 //====================================================================
185 sal_Bool SfxDispatcher::IsLocked( sal_uInt16 ) const
186 
187 /*  [Beschreibung]
188 
189     Mit dieser Methode kann festgestellt werden, ob der SfxDispatcher
190     gesperrt oder freigegeben ist. Ein gesperrter SfxDispatcher
191     f"uhrt keine <SfxRequest>s mehr aus und liefert keine
192     Status-Informationen mehr. Er verh"alt sich so als w"aren alle
193     Slots disabled.
194 
195     Der Dispatcher gilt auch als gesperrt, wenn alle Dispatcher
196     gelockt sind (<SfxApplication::LockDispatcher()>) oder der zugeh"orige
197     Top-Frame im modal-mode ist und der angegebene Slot Frame-spezifisch
198     (also nicht von der Application) bedient wird.
199 */
200 
201 {
202     return pImp->bLocked;
203 }
204 
205 //--------------------------------------------------------------------
206 sal_Bool SfxDispatcher::IsAppDispatcher() const
207 
208 /*  [Beschreibung]
209 
210     Mit dieser Methode l"a\st sich festellen, ob der SfxDispacher der
211     Applikations-Dispatcher ist.
212 
213 
214     [R"uckgabewert]
215 
216     sal_Bool                sal_True
217                         Es ist der Applikations-Dispatcher.
218 
219                         sal_False
220                         Es ist ein Dispatcher eines SfxViewFrame.
221 */
222 
223 {
224     return !pImp->pFrame;
225 }
226 
227 //--------------------------------------------------------------------
228 int SfxDispatcher::Call_Impl( SfxShell& rShell, const SfxSlot &rSlot, SfxRequest &rReq, sal_Bool bRecord )
229 
230 /*  [Beschreibung]
231 
232     Hilfsfunktion zum pr"ufen, ob ein Slot executed werden darf und
233     der Execution selbst.
234 */
235 
236 {
237     SFX_STACK(SfxDispatcher::Call_Impl);
238 
239     // darf der Slot gerufen werden (i.S.v. enabled)
240     if ( rSlot.IsMode(SFX_SLOT_FASTCALL) || rShell.CanExecuteSlot_Impl(rSlot) )
241     {
242         if ( GetFrame() )
243         {
244             // ggf. Recording anwerfen
245             com::sun::star::uno::Reference< com::sun::star::frame::XFrame > xFrame(
246                     GetFrame()->GetFrame().GetFrameInterface(),
247                     com::sun::star::uno::UNO_QUERY);
248 
249             com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet > xSet(
250                     xFrame,
251                     com::sun::star::uno::UNO_QUERY);
252 
253             if ( xSet.is() )
254             {
255                 com::sun::star::uno::Any aProp = xSet->getPropertyValue(::rtl::OUString::createFromAscii("DispatchRecorderSupplier"));
256                 com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorderSupplier > xSupplier;
257                 com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > xRecorder;
258                 aProp >>= xSupplier;
259                 if(xSupplier.is())
260                     xRecorder = xSupplier->getDispatchRecorder();
261 
262                 if ( bRecord && xRecorder.is() && !rSlot.IsMode(SFX_SLOT_NORECORD) )
263                     rReq.Record_Impl( rShell, rSlot, xRecorder, GetFrame() );
264             }
265         }
266 
267         // Alles holen, was gebraucht wird, da der Slot den Execute evtl. nicht
268         // "uberlebt, falls es ein 'Pseudoslot' f"ur Macros oder Verben ist
269         sal_Bool bAutoUpdate = rSlot.IsMode(SFX_SLOT_AUTOUPDATE);
270 
271         // API-Call-Klammerung und Document-Lock w"ahrend des Calls
272         {
273             // 'this' mu\s im Dtor bescheid sagen
274             sal_Bool bThisDispatcherAlive = sal_True;
275             sal_Bool *pOldInCallAliveFlag = pImp->pInCallAliveFlag;
276             pImp->pInCallAliveFlag = &bThisDispatcherAlive;
277 
278             SfxViewFrame* pView = GetFrame();
279             if ( !pView )
280                 pView = SfxViewFrame::Current();
281             if ( pView )
282             {
283                 rtl::OString aCmd(".uno:");
284                 aCmd += rSlot.GetUnoName();
285                 SfxHelp::OpenHelpAgent( &pView->GetFrame(), aCmd );
286             }
287 
288             SfxExecFunc pFunc = rSlot.GetExecFnc();
289             rShell.CallExec( pFunc, rReq );
290 
291             // falls 'this' noch lebt
292             if ( bThisDispatcherAlive )
293                 pImp->pInCallAliveFlag = pOldInCallAliveFlag;
294             else
295             {
296                 if ( pOldInCallAliveFlag )
297                 {
298                     // auch verschachtelte Stack-Frames sch"utzen
299                     *pOldInCallAliveFlag = sal_False;
300                 }
301 
302                 // do nothing after this object is dead
303                 return rReq.IsDone();
304             }
305         }
306 
307         if ( rReq.IsDone() )
308         {
309             SfxBindings *pBindings = GetBindings();
310 
311             // bei AutoUpdate sofort updaten; "Pseudoslots" d"urfen nicht
312             // Autoupdate sein!
313             if ( bAutoUpdate && pBindings )
314             {
315                 const SfxSlot* pSlave = rSlot.GetLinkedSlot();
316                 if (pSlave)
317                 {
318                     // bei Enum-Slots irgendeinen gebundenen Slave-Slot nehmen
319                     while (!pBindings->IsBound(pSlave->GetSlotId()) && pSlave != &rSlot )
320                         pSlave = pSlave->GetLinkedSlot();
321                     pBindings->Invalidate(pSlave->GetSlotId());
322                     pBindings->Update(pSlave->GetSlotId());
323                 }
324                 else
325                 {
326                     pBindings->Invalidate(rSlot.GetSlotId());
327                     pBindings->Update(rSlot.GetSlotId());
328                 }
329             }
330 
331             return sal_True;
332         }
333     }
334 
335     return sal_False;
336 }
337 
338 //====================================================================
339 void SfxDispatcher::Construct_Impl( SfxDispatcher* pParent )
340 {
341     pImp = new SfxDispatcher_Impl;
342     bFlushed = sal_True;
343     SfxApplication *pSfxApp = SFX_APP();
344 
345     pImp->pCachedServ1 = 0;
346     pImp->pCachedServ2 = 0;
347     pImp->bFlushing = sal_False;
348     pImp->bUpdated = sal_False;
349     pImp->bLocked = sal_False;
350     pImp->bActive = sal_False;
351     pImp->pParent = NULL;
352     pImp->bUILocked = sal_False;
353     pImp->bNoUI = sal_False;
354     pImp->bReadOnly = sal_False;
355     pImp->bQuiet = sal_False;
356     pImp->bModal = sal_False;
357     pImp->pInCallAliveFlag = 0;
358     pImp->bFilterEnabling = sal_False;
359     pImp->nFilterCount = 0;
360     pImp->pFilterSIDs = 0;
361     pImp->nStandardMode = 0;
362     pImp->pDisableList = pSfxApp->GetDisabledSlotList_Impl();
363     pImp->nDisableFlags = 0;
364 
365     pImp->pParent = pParent;
366 
367     pImp->bInvalidateOnUnlock = sal_False;
368 
369     for (sal_uInt16 n=0; n<SFX_OBJECTBAR_MAX; n++)
370         pImp->aObjBars[n].nResId = 0;
371 
372     GenLink aGenLink( LINK(this, SfxDispatcher, PostMsgHandler) );
373 
374     pImp->xPoster = new SfxHintPoster(aGenLink);
375 
376     pImp->aTimer.SetTimeout(SFX_FLUSH_TIMEOUT);
377     pImp->aTimer.SetTimeoutHdl( LINK(this, SfxDispatcher, EventHdl_Impl ) );
378 }
379 
380 SfxDispatcher::SfxDispatcher( SfxDispatcher* pParent )
381 {
382     Construct_Impl( pParent );
383     pImp->pFrame = 0;
384 }
385 
386 SfxDispatcher::SfxDispatcher( SfxViewFrame *pViewFrame )
387 
388 /*  [Beschreibung]
389 
390     Der Konstruktor der Klasse SfxDispatcher legt einen leeren Stack
391     von <SfxShell>-Pointern an. Er ist initial nicht gelockt und gilt als
392     geflusht.
393 */
394 
395 {
396     if ( pViewFrame )
397     {
398         SfxViewFrame *pFrame = pViewFrame->GetParentViewFrame();
399         if ( pFrame )
400             Construct_Impl(  pFrame->GetDispatcher() );
401         else
402             Construct_Impl( 0 );
403     }
404     else
405         Construct_Impl( 0 );
406     pImp->pFrame = pViewFrame;
407 }
408 
409 //====================================================================
410 SfxDispatcher::~SfxDispatcher()
411 
412 /*  [Beschreibung]
413 
414     Der Destruktor der Klasse SfxDispatcher darf nicht gerufen werden,
415     wenn die SfxDispatcher-Instanz aktiv ist. Es d"urfen sich allerdings
416     noch <SfxShell>-Pointer auf dem Stack befinden.
417 */
418 
419 {
420 #ifdef DBG_UTIL
421     ByteString sTemp( "Delete Dispatcher " );
422     sTemp += ByteString::CreateFromInt64( (sal_uIntPtr)this );
423     DBG_TRACE( sTemp.GetBuffer() );
424     DBG_ASSERT( !pImp->bActive, "deleting active Dispatcher" );
425 #endif
426 
427     // Damit in LeaveRegistrations kein Timer per Reschedule in PlugComm
428     // zuschlaegt
429     pImp->aTimer.Stop();
430     pImp->xPoster->SetEventHdl( Link() );
431 
432     // die Stack-Varialblem in Call_Impl benachrichtigen
433     if ( pImp->pInCallAliveFlag )
434         *pImp->pInCallAliveFlag = sal_False;
435 
436     // Bindings und App besorgen
437     SfxApplication *pSfxApp = SFX_APP();
438     SfxBindings* pBindings = GetBindings();
439 
440 //  if (pImp->nEventId)
441 //      pSfxApp->RemoveEventHdl(pImp->nEventId);
442 
443     // wenn noch nicht flushed, die Bindings wiederbeleben
444     if ( pBindings && !pSfxApp->IsDowning() && !bFlushed )
445         pBindings->DLEAVEREGISTRATIONS();
446 
447     // ggf. bei den Bindings abmelden
448     while ( pBindings )
449     {
450         if ( pBindings->GetDispatcher_Impl() == this)
451             pBindings->SetDispatcher(0);
452         pBindings = pBindings->GetSubBindings_Impl();
453     }
454 
455     delete pImp;
456 }
457 
458 //====================================================================
459 void SfxDispatcher::Pop
460 (
461     SfxShell&   rShell,     /*  Die vom Stack zu nehmende SfxShell-Instanz. */
462 
463     sal_uInt16      nMode       /*  SFX_SHELL_POP_UNTIL
464                                 Es werden auch alle "uber 'rShell' liegenenden
465                                 SfxShell's vom Stack genommen.
466 
467                                 SFX_SHELL_POP_DELETE
468                                 Alle tats"achlich vom Stack genommenen
469                                 SfxShells werden gel"oscht.
470 
471                                 SFX_SHELL_PUSH (InPlace use only)
472                                 Die Shell wird gepusht. */
473 )
474 /*  [Beschreibung]
475 
476     Mit dieser Methode wird eine oder mehrere <SfxShell> vom SfxDispatcher
477     gepoppt. Die SfxShell wird zun"achst zum poppen vermerkt und
478     es wird ein Timer aufgesetzt. Erst bei Ablauf des Timers wird
479     tats"achlich gepoppt (<SfxDispatcher::Flush()>) und die <SfxBindings>
480     werden invalidiert. W"ahrend der Timer l"auft gleichen sich
481     entgegengesetzte Push und Pop Befehle mit derselben SfxShell aus.
482 */
483 
484 {
485     DBG_MEMTEST();
486     DBG_ASSERT( rShell.GetInterface(),
487                 "pushing SfxShell without previous RegisterInterface()" );
488 
489     bool bDelete = (nMode & SFX_SHELL_POP_DELETE) == SFX_SHELL_POP_DELETE;
490     bool bUntil = (nMode & SFX_SHELL_POP_UNTIL) == SFX_SHELL_POP_UNTIL;
491     bool bPush = (nMode & SFX_SHELL_PUSH) == SFX_SHELL_PUSH;
492 
493     SfxApplication *pSfxApp = SFX_APP();
494 
495 #ifdef DBG_UTIL
496     ByteString aMsg( "-SfxDispatcher(" );
497     aMsg += ByteString::CreateFromInt64( (sal_uIntPtr) this );
498     aMsg += bPush ? ")::Push(" : ")::Pop(";
499     if ( rShell.GetInterface() )
500         aMsg += rShell.GetInterface()->GetClassName();
501     else
502         aMsg += ByteString::CreateFromInt64( (sal_uIntPtr) &rShell );
503     aMsg += bDelete ? ") with delete" : ")";
504     if ( bUntil ) aMsg += " (up to)";
505     DbgTrace( aMsg.GetBuffer() );
506 #endif
507 
508     // gleiche Shell wie on-Top des ToDo-Stacks?
509     if ( pImp->aToDoStack.Count() && pImp->aToDoStack.Top().pCluster == &rShell )
510     {
511         // inverse Actions heben sich auf
512         if ( pImp->aToDoStack.Top().bPush != bPush )
513             pImp->aToDoStack.Pop();
514         else
515         {
516             DBG_ASSERT( bPush, "SfxInterface pushed more than once" );
517             DBG_ASSERT( !bPush, "SfxInterface popped more than once" );
518         }
519     }
520     else
521     {
522         // ::com::sun::star::chaos::Action merken
523         pImp->aToDoStack.Push( SfxToDo_Impl(bPush, bDelete, bUntil, rShell) );
524         if ( bFlushed )
525         {
526             DBG_TRACE("Unflushed dispatcher!");
527             bFlushed = sal_False;
528             pImp->bUpdated = sal_False;
529 
530             // Bindings schlafen legen
531             SfxBindings* pBindings = GetBindings();
532             if ( pBindings )
533                 pBindings->DENTERREGISTRATIONS();
534         }
535     }
536 
537     if ( !pSfxApp->IsDowning() && pImp->aToDoStack.Count() )
538     {
539         //! if (SFX_APP()->AnyInput(INPUT_KEYBOARD | INPUT_MOUSE) )
540         //! AnyInput haut nicht hin; hier muss noch ein Kriterium gefunden
541         //! werden. Solange wieder immer mit Timer.
542 
543         if (sal_True)
544         {
545             // Kein sofortiges Update gewuenscht
546             pImp->aTimer.SetTimeout(SFX_FLUSH_TIMEOUT);
547             pImp->aTimer.SetTimeoutHdl( LINK(this, SfxDispatcher, EventHdl_Impl ) );
548             pImp->aTimer.Start();
549         }
550         else
551         {
552             // Schnellstmoegliches Update (sollte Normalfall sein)
553             pImp->aTimer.Stop();
554             GetpApp()->PostUserEvent(pImp->nEventId, (void*)0);
555         }
556     }
557     else
558     {
559         // doch nichts zu tun
560         pImp->aTimer.Stop();
561 
562         // ggf. Bindings wieder aufwecken
563         if ( !pImp->aToDoStack.Count() )
564         {
565             SfxBindings* pBindings = GetBindings();
566             if ( pBindings )
567                 pBindings->DLEAVEREGISTRATIONS();
568         }
569     }
570 }
571 
572 //--------------------------------------------------------------------
573 
574 IMPL_LINK_INLINE_START( SfxDispatcher, EventHdl_Impl, void *, pvoid )
575 
576 /*  [Beschreibung]
577 
578     Dieser Handler wird nach <SfxDispatcher::Invalidate()> oder Bewegungen
579     auf dem Stack (<SfxDispatcher::Push()> und <SfxDispatcher::Pop()) gerufen.
580 
581     Er flusht den Stack, falls er dirty ist, f"uhrt also die ausstehenden
582     Push und Pop Befehle tats"achlich aus.
583 */
584 
585 {
586     (void)pvoid; // unused
587     DBG_MEMTEST();
588 
589     Flush();
590     Update_Impl();
591     SfxBindings* pBindings = GetBindings();
592     if ( pBindings )
593         pBindings->StartUpdate_Impl(sal_False);
594     return 0;
595 }
596 IMPL_LINK_INLINE_END( SfxDispatcher, EventHdl_Impl, void *, pvoid )
597 
598 //--------------------------------------------------------------------
599 sal_Bool SfxDispatcher::CheckVirtualStack( const SfxShell& rShell, sal_Bool bDeep )
600 
601 /*  [Beschreibung]
602 
603     Mit dieser Methode kann gepr"uft werden, ob sich die <SfxShell> rShell
604     auf dem Stack befindet, wenn er geflusht w"are. Dabei wird der
605     SfxDispatcher jedoch nicht tats"achlich geflusht.
606 
607     Diese Methode ist u.a. dazu gedacht, Assertions zu erm"oglichen, ohne
608     als Seiteneffekt den SfxDispathcer flushen zu m"ussen.
609 */
610 
611 {
612     DBG_MEMTEST();
613     SFX_STACK(SfxDispatcher::CheckVirtualStack);
614 
615     SfxShellStack_Impl aStack( pImp->aStack );
616     for ( short nToDo = pImp->aToDoStack.Count()-1; nToDo >= 0; --nToDo )
617     {
618         SfxToDo_Impl aToDo( pImp->aToDoStack.Top(nToDo) );
619         if ( aToDo.bPush )
620             aStack.Push( (SfxShell*) aToDo.pCluster );
621         else
622         {
623             SfxShell* pPopped = 0;
624             do
625             {
626                 DBG_ASSERT( aStack.Count(), "popping from empty stack" );
627                 pPopped = aStack.Pop();
628             }
629             while ( aToDo.bUntil && pPopped != aToDo.pCluster );
630             DBG_ASSERT( pPopped == aToDo.pCluster, "popping unpushed SfxInterface" );
631         }
632     }
633 
634     sal_Bool bReturn;
635     if ( bDeep )
636         bReturn = aStack.Contains(&rShell);
637     else
638         bReturn = aStack.Top() == &rShell;
639     return bReturn;
640 }
641 
642 //--------------------------------------------------------------------
643 sal_uInt16 SfxDispatcher::GetShellLevel( const SfxShell& rShell )
644 
645 /*  [Beschreibung]
646 
647     Ermittelt die Position einer SfxShell im Stack des Dispatchers.
648     Dazu wird dieser ggf. zuvor geflusht.
649 
650 
651     [Rueckgabewert]
652 
653     sal_uInt16                      == USRT_MAX
654                                 Die SfxShell befindet sich nicht auf
655                                 diesem SfxDispatcher.
656 
657                                 < USHRT_MAX
658                                 Position der SfxShell auf dem Dispatcher
659                                 von oben mit 0 beginnend gez"ahlt.
660 */
661 
662 {
663     DBG_MEMTEST();
664     SFX_STACK(SfxDispatcher::GetShellLevel);
665     Flush();
666 
667     for ( sal_uInt16 n = 0; n < pImp->aStack.Count(); ++n )
668         if ( pImp->aStack.Top( n ) == &rShell )
669             return n;
670     if ( pImp->pParent )
671     {
672         sal_uInt16 nRet = pImp->pParent->GetShellLevel(rShell);
673         if ( nRet == USHRT_MAX )
674             return nRet;
675         return  nRet + pImp->aStack.Count();
676     }
677 
678     return USHRT_MAX;
679 }
680 
681 //--------------------------------------------------------------------
682 SfxShell *SfxDispatcher::GetShell(sal_uInt16 nIdx) const
683 
684 /*  [Beschreibung]
685 
686     Liefert einen Pointer auf die <SfxShell>, welche sich an der Position
687     nIdx (von oben, letzt-gepushte liegt bei 0) auf dem Stack befindet.
688 
689     Dabei wird der SfxDispatcher nicht geflusht.
690 
691     Ist der Stack nicht tief genug, wird ein 0-Pointer zur"uckgegeben.
692 */
693 
694 {
695     DBG_MEMTEST();
696 
697     sal_uInt16 nShellCount = pImp->aStack.Count();
698     if ( nIdx < nShellCount )
699         return pImp->aStack.Top(nIdx);
700     else if ( pImp->pParent )
701         return pImp->pParent->GetShell( nIdx - nShellCount );
702     return 0;
703 }
704 
705 //--------------------------------------------------------------------
706 SfxBindings* SfxDispatcher::GetBindings() const
707 
708 /*  [Beschreibung]
709 
710     Diese Methode liefert einen Pointer auf die <SfxBindings> Instanz
711     zur"uck, an die der SfxDispatcher gerade gebunden ist. Ein SfxDispatcher
712     ist nur dann an SfxBindings gebunden, wenn er <UI-aktiv> ist. Ist
713     er nicht UI-aktiv, wird ein 0-Pointer zur"uckgegeben.
714 
715     Der zur"uckgegebene Pointer ist nur im <unmittelbaren Kontext> des
716     Methodenaufrufs g"ultig.
717 */
718 
719 {
720     if ( pImp->pFrame )
721         return &pImp->pFrame->GetBindings();
722     else
723         return NULL;
724 }
725 
726 //--------------------------------------------------------------------
727 SfxViewFrame* SfxDispatcher::GetFrame() const
728 
729 /*  [Beschreibung]
730 
731     Liefert einen Pointer auf die <SfxViewFrame> Instanz, der dieser
732     SfxDispatcher geh"ort. Falls es sich um den Applikations-Dispatcher
733     handelt, wird ein 0-Pointer zur"uckgegeben.
734 */
735 
736 {
737     DBG_MEMTEST();
738     return pImp->pFrame;
739 }
740 
741 //--------------------------------------------------------------------
742 void SfxDispatcher::DoActivate_Impl( sal_Bool bMDI, SfxViewFrame* /* pOld */ )
743 
744 /*  [Beschreibung]
745 
746     Diese Methode steuert das Aktivieren eines Dispatchers.
747 
748     Da der Applikations-Dispatcher immer aktiv ist, entweder als
749     Unterdispatcher des <SfxViewFrame>-Dispatchers oder selbst, wird
750     er nie als ganzes Aktiviert, sondern nur seine einzelnen <SfxShell>s
751     bei <SfxDispatcher::Push(SfxShell&)>.
752 
753     Beim Aktivieren eines SfxDispatchers wird an allen auf seinem
754     Stack befindlichen SfxShells, beginnend mit der untersten, der Handler
755     <SfxShell::Activate(sal_Bool)> gerufen.
756 */
757 
758 {
759     DBG_MEMTEST();
760     SFX_STACK(SfxDispatcher::DoActivate);
761     if ( bMDI )
762     {
763         #ifdef DBG_UTIL
764         ByteString sTemp("Activate Dispatcher ");
765         sTemp += ByteString::CreateFromInt64( (sal_uIntPtr) this );
766         DBG_TRACE(sTemp.GetBuffer());
767         DBG_ASSERT( !pImp->bActive, "Activate-Fehler" );
768         #endif
769         pImp->bActive = sal_True;
770         pImp->bUpdated = sal_False;
771         SfxBindings* pBindings = GetBindings();
772         if ( pBindings )
773         {
774             pBindings->SetDispatcher(this);
775             pBindings->SetActiveFrame( pImp->pFrame->GetFrame().GetFrameInterface() );
776         }
777     }
778     else
779     {
780         #ifdef DBG_UTIL
781         ByteString sTemp("Non-MDI-Activate Dispatcher");
782         sTemp += ByteString::CreateFromInt64( (sal_uIntPtr) this );
783         DBG_TRACE( sTemp.GetBuffer() );
784         #endif
785     }
786 
787     if ( IsAppDispatcher() )
788         return;
789 
790     for ( int i = int(pImp->aStack.Count()) - 1; i >= 0; --i )
791         pImp->aStack.Top( (sal_uInt16) i )->DoActivate_Impl(pImp->pFrame, bMDI);
792 
793     if ( bMDI && pImp->pFrame )
794     {
795         //SfxWorkWindow *pWorkWin = pImp->pFrame->GetFrame().GetWorkWindow_Impl();
796         SfxBindings *pBind = GetBindings();
797         while ( pBind )
798         {
799             pBind->HidePopupCtrls_Impl( sal_False );
800             pBind = pBind->GetSubBindings_Impl();
801         }
802 
803         pImp->pFrame->GetFrame().GetWorkWindow_Impl()->HidePopups_Impl( sal_False, sal_False, 1 );
804     }
805 
806     if ( pImp->aToDoStack.Count() )
807     {
808         if (sal_True)
809         {
810             // Kein sofortiges Update gewuenscht
811             pImp->aTimer.SetTimeout(SFX_FLUSH_TIMEOUT);
812             pImp->aTimer.SetTimeoutHdl( LINK(this, SfxDispatcher, EventHdl_Impl ) );
813             pImp->aTimer.Start();
814         }
815         else
816         {
817             // Schnellstmoegliches Update (sollte Normalfall sein)
818             pImp->aTimer.Stop();
819             GetpApp()->PostUserEvent(pImp->nEventId, (void*)0);
820         }
821     }
822 }
823 
824 void SfxDispatcher::DoParentActivate_Impl()
825 {
826     for ( int i = int(pImp->aStack.Count()) - 1; i >= 0; --i )
827         pImp->aStack.Top( (sal_uInt16) i )->ParentActivate();
828 }
829 
830 //--------------------------------------------------------------------
831 void SfxDispatcher::DoDeactivate_Impl( sal_Bool bMDI, SfxViewFrame* pNew )
832 
833 /*  [Beschreibung]
834 
835     Diese Methode steuert das Deaktivieren eines Dispatchers.
836 
837     Da der Applikations-Dispatcher immer aktiv ist, entweder als
838     Unterdispatcher des <SfxViewFrame>-Dispatchers oder selbst, wird
839     er nie als ganzes Deaktiviert, sondern nur seine einzelnen <SfxShell>s
840     bei <SfxDispatcher::Pop(SfxShell&)>.
841 
842     Beim Deaktivieren eines SfxDispatchers wird an allen auf seinem
843     Stack befindlichen SfxShells, beginnend mit der obersten, der Handler
844     <SfxShell::Deactivate(sal_Bool)> gerufen.
845 */
846 
847 {
848     DBG_MEMTEST();
849     SFX_STACK(SfxDispatcher::DoDeactivate);
850 
851     SfxApplication *pSfxApp = SFX_APP();
852 
853     if ( bMDI )
854     {
855         DBG_TRACE(ByteString("Deactivate Dispatcher ").Append(ByteString::CreateFromInt64( (sal_uIntPtr) this )).GetBuffer());
856         DBG_ASSERT( pImp->bActive, "Deactivate-Fehler" );
857         pImp->bActive = sal_False;
858 
859         if ( pImp->pFrame && !(pImp->pFrame->GetObjectShell()->IsInPlaceActive() ) )
860         {
861             SfxWorkWindow *pWorkWin = pImp->pFrame->GetFrame().GetWorkWindow_Impl();
862             if ( pWorkWin )
863             {
864                 for (sal_uInt16 n=0; n<pImp->aChildWins.Count();)
865                 {
866                     SfxChildWindow *pWin = pWorkWin->GetChildWindow_Impl( (sal_uInt16) ( pImp->aChildWins[n] & 0xFFFF ) );
867                     if (!pWin || (pWin && pWin->GetAlignment() == SFX_ALIGN_NOALIGNMENT))
868                         pImp->aChildWins.Remove(n);
869                     else
870                         n++;
871                 }
872             }
873         }
874     }
875     else {
876         DBG_TRACE( ByteString ("Non-MDI-DeActivate Dispatcher").Append(ByteString::CreateFromInt64( (sal_uIntPtr) this )).GetBuffer() );
877     }
878 
879     if ( IsAppDispatcher() && !pSfxApp->IsDowning() )
880         return;
881 
882     for ( sal_uInt16 i = 0; i < pImp->aStack.Count(); ++i )
883         pImp->aStack.Top(i)->DoDeactivate_Impl(pImp->pFrame, bMDI);
884 
885     sal_Bool bHidePopups = bMDI && pImp->pFrame;
886     if ( pNew && pImp->pFrame )
887     {
888         com::sun::star::uno::Reference< com::sun::star::frame::XFrame > xOldFrame(
889             pNew->GetFrame().GetFrameInterface()->getCreator(), com::sun::star::uno::UNO_QUERY );
890 
891         com::sun::star::uno::Reference< com::sun::star::frame::XFrame > xMyFrame(
892             GetFrame()->GetFrame().GetFrameInterface(), com::sun::star::uno::UNO_QUERY );
893 
894         if ( xOldFrame == xMyFrame )
895             bHidePopups = sal_False;
896     }
897 
898     if ( bHidePopups )
899     {
900         //SfxWorkWindow *pWorkWin = pImp->pFrame->GetFrame().GetWorkWindow_Impl();
901         SfxBindings *pBind = GetBindings();
902         while ( pBind )
903         {
904             pBind->HidePopupCtrls_Impl( sal_True );
905             pBind = pBind->GetSubBindings_Impl();
906         }
907 
908         pImp->pFrame->GetFrame().GetWorkWindow_Impl()->HidePopups_Impl( sal_True, sal_False, 1 );
909     }
910 
911     Flush();
912 }
913 
914 void SfxDispatcher::DoParentDeactivate_Impl()
915 {
916     for ( int i = int(pImp->aStack.Count()) - 1; i >= 0; --i )
917         pImp->aStack.Top( (sal_uInt16) i )->ParentDeactivate();
918 }
919 
920 //--------------------------------------------------------------------
921 int SfxDispatcher::GetShellAndSlot_Impl
922 (
923     sal_uInt16          nSlot,      // die zu suchende Slot-Id
924     SfxShell**      ppShell,    // die SfxShell, welche nSlot z.Zt. bedient
925     const SfxSlot** ppSlot,     // der SfxSlot, welcher nSlot z.Zt. bedient
926     sal_Bool            bOwnShellsOnly,
927     sal_Bool            bModal,     // trotz ModalMode
928     sal_Bool        bRealSlot
929 )
930 
931 /*  [Beschreibung]
932 
933     Diese Methode sucht im SfxDispatcher nach der <SfxShell>, von der
934     die Slot-Id nSlot zur Zeit bedient wird. Dazu wird der Dispatcher
935     zuvor geflusht.
936 
937 
938     [R"uckgabewert]
939 
940     int                 sal_True
941                         Die SfxShell wurde gefunden, ppShell und ppSlot
942                         sind g"ultig.
943 
944                         sal_True
945                         Die SfxShell wurde nicht gefunden, ppShell und ppSlot
946                         sind ung"ultig.
947 */
948 
949 {
950     SFX_STACK(SfxDispatcher::GetShellAndSlot_Impl);
951 
952     Flush();
953     SfxSlotServer aSvr;
954     if ( _FindServer(nSlot, aSvr, bModal) )
955     {
956         if ( bOwnShellsOnly && aSvr.GetShellLevel() >= pImp->aStack.Count() )
957             return sal_False;
958 
959         *ppShell = GetShell(aSvr.GetShellLevel());
960         *ppSlot = aSvr.GetSlot();
961         if ( 0 == (*ppSlot)->GetExecFnc() && bRealSlot )
962             *ppSlot = (*ppShell)->GetInterface()->GetRealSlot(*ppSlot);
963         // Check only real slots as enum slots don't have an execute function!
964         if ( bRealSlot && ((0 == *ppSlot) || (0 == (*ppSlot)->GetExecFnc()) ))
965             return sal_False;
966 
967 #ifdef DBG_UTILx
968         ByteString aMsg( nSlot );
969         aMsg += " found in ";
970         aMsg += (*ppShell)->GetInterface()->GetClassName();
971         DbgTrace( aMsg.GetBuffer() );
972 #endif
973 
974         return sal_True;
975     }
976 
977 #ifdef DBG_UTILx
978     ByteString aMsg( nSlot );
979     aMsg += " not found";
980     DbgTrace( aMsg.GetBuffer() );
981 #endif
982 
983     return sal_False;
984 }
985 
986 /*
987 struct Executer : public SfxHint
988 {
989     SfxRequest *pRequest;
990     const SfxSlot* pSlot;
991     sal_uInt16 nLevel;
992 
993     Executer( SfxRequest* pReq, const SfxSlot* p, sal_uInt16 n )
994         :  pRequest( pReq )
995         , pSlot(p)
996         , nLevel(n)
997         {}
998     ~Executer()
999     {delete pRequest;}
1000 };
1001 */
1002 
1003 //--------------------------------------------------------------------
1004 void SfxDispatcher::_Execute
1005 (
1006     SfxShell&       rShell,     // zu rufende <SfxShell>
1007     const SfxSlot&  rSlot,      // zu rufender <SfxSlot>
1008     SfxRequest&     rReq,       // auszuf"uhrende Funktion (Id und optional Parameter)
1009     SfxCallMode     eCallMode   // synchron, asynchron oder wie beim Slot angegeben
1010 )
1011 
1012 /*  [Beschreibung]
1013 
1014     Diese Methode f"uhrt einen Request "uber einen gecachten <Slot-Server>
1015     aus.
1016 */
1017 
1018 {
1019     DBG_MEMTEST();
1020     DBG_ASSERT( !pImp->bFlushing, "recursive call to dispatcher" );
1021     DBG_ASSERT( !pImp->aToDoStack.Count(), "unprepared InPlace _Execute" );
1022 
1023     if ( IsLocked( rSlot.GetSlotId() ) )
1024         return;
1025 
1026     if ( (eCallMode & SFX_CALLMODE_ASYNCHRON) ||
1027          ( !(eCallMode & SFX_CALLMODE_SYNCHRON) &&
1028            rSlot.IsMode(SFX_SLOT_ASYNCHRON) ) )
1029     {
1030         SfxDispatcher *pDispat = this;
1031         while ( pDispat )
1032         {
1033             sal_uInt16 nShellCount = pDispat->pImp->aStack.Count();
1034             for ( sal_uInt16 n=0; n<nShellCount; n++ )
1035             {
1036                 if ( &rShell == pDispat->pImp->aStack.Top(n) )
1037                 {
1038                     if ( eCallMode & SFX_CALLMODE_RECORD )
1039                         rReq.AllowRecording( sal_True );
1040                     pDispat->pImp->xPoster->Post(new SfxRequest(rReq));
1041 //                    pDispat->pImp->xPoster->Post(new Executer(new SfxRequest(rReq), &rSlot, n ));
1042                     return;
1043                 }
1044             }
1045 
1046             pDispat = pDispat->pImp->pParent;
1047         }
1048     }
1049     else
1050         Call_Impl( rShell, rSlot, rReq, SFX_CALLMODE_RECORD==(eCallMode&SFX_CALLMODE_RECORD) );
1051 }
1052 
1053 //--------------------------------------------------------------------
1054 void MappedPut_Impl( SfxAllItemSet &rSet, const SfxPoolItem &rItem )
1055 
1056 /*  [Beschreibung]
1057 
1058     Hilfsfunktion zum putten von rItem unter der im Pool des Item-Sets
1059     rSet geltenden Which-Id.
1060 */
1061 
1062 {
1063     // mit ggf. gemappter Which-Id putten
1064     const SfxItemPool *pPool = rSet.GetPool();
1065     sal_uInt16 nWhich = rItem.Which();
1066 #ifdef TF_POOLABLE
1067     if ( pPool->IsSlot(nWhich) )
1068 #else
1069     if ( pPool->HasMap() && pPool->IsSlot(nWhich) )
1070 #endif
1071         nWhich = pPool->GetWhich(nWhich);
1072     rSet.Put( rItem, nWhich );
1073 }
1074 
1075 //--------------------------------------------------------------------
1076 
1077 #ifndef SFX_USE_BINDINGS
1078 #define SFX_USE_BINDINGS 0x8000
1079 #endif
1080 
1081 sal_uInt16 SfxDispatcher::ExecuteFunction( sal_uInt16 nSlot, SfxPoolItem **pArgs,
1082                                        sal_uInt16 nMode )
1083 {
1084     if ( !nMode )
1085         nMode = pImp->nStandardMode;
1086 
1087     // via Bindings/Interceptor? (dann ist der Returnwert nicht exakt)
1088     sal_Bool bViaBindings = SFX_USE_BINDINGS == ( nMode & SFX_USE_BINDINGS );
1089     nMode &= ~sal_uInt16(SFX_USE_BINDINGS);
1090     if ( bViaBindings && GetBindings() )
1091         return GetBindings()->Execute( nSlot, (const SfxPoolItem **) pArgs, nMode )
1092                 ? EXECUTE_POSSIBLE
1093                 : EXECUTE_NO;
1094 
1095     // sonst via Dispatcher
1096     if ( IsLocked(nSlot) )
1097         return 0;
1098     SfxShell *pShell = 0;
1099     SfxCallMode eCall = SFX_CALLMODE_SYNCHRON;
1100     sal_uInt16 nRet = EXECUTE_NO;
1101     const SfxSlot *pSlot = 0;
1102     if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, sal_False, sal_False ) )
1103     {
1104         // Ausf"uhrbarkeit vorher testen
1105         if ( pSlot->IsMode( SFX_SLOT_FASTCALL ) ||
1106             pShell->CanExecuteSlot_Impl( *pSlot ) )
1107                 nRet = EXECUTE_POSSIBLE;
1108 
1109         if ( nMode == EXECUTEMODE_ASYNCHRON )
1110             eCall = SFX_CALLMODE_ASYNCHRON;
1111         else if ( nMode == EXECUTEMODE_DIALOGASYNCHRON && pSlot->IsMode( SFX_SLOT_HASDIALOG ) )
1112             eCall = SFX_CALLMODE_ASYNCHRON;
1113         else if ( pSlot->GetMode() & SFX_SLOT_ASYNCHRON )
1114             eCall = SFX_CALLMODE_ASYNCHRON;
1115         sal_Bool bDone = sal_False;
1116         if ( pArgs && *pArgs )
1117         {
1118             SfxAllItemSet aSet( pShell->GetPool() );
1119             for ( SfxPoolItem **pArg = pArgs; *pArg; ++pArg )
1120                 MappedPut_Impl( aSet, **pArg );
1121             SfxRequest aReq( nSlot, eCall, aSet );
1122             _Execute( *pShell, *pSlot, aReq, eCall );
1123             bDone = aReq.IsDone();
1124         }
1125         else
1126         {
1127             SfxRequest aReq( nSlot, eCall, pShell->GetPool() );
1128             _Execute( *pShell, *pSlot, aReq, eCall );
1129             bDone = aReq.IsDone();
1130         }
1131     }
1132 
1133     return nRet;
1134 }
1135 
1136 sal_uInt16 SfxDispatcher::ExecuteFunction( sal_uInt16 nSlot, const SfxItemSet& rArgs,
1137                                        sal_uInt16 nMode )
1138 {
1139     if ( !nMode )
1140         nMode = pImp->nStandardMode;
1141 
1142 /*
1143     // at the moment not implemented
1144     // via Bindings/Interceptor? (dann ist der Returnwert nicht exakt)
1145     sal_Bool bViaBindings = SFX_USE_BINDINGS == ( nMode & SFX_USE_BINDINGS );
1146     nMode &= ~sal_uInt16(SFX_USE_BINDINGS);
1147     if ( bViaBindings && GetBindings() )
1148         return GetBindings()->Execute( nSlot, rArgs, nMode )
1149                 ? EXECUTE_POSSIBLE
1150                 : EXECUTE_NO;
1151 */
1152     // sonst via Dispatcher
1153     if ( IsLocked(nSlot) )
1154         return 0;
1155     SfxShell *pShell = 0;
1156     SfxCallMode eCall = SFX_CALLMODE_SYNCHRON;
1157     sal_uInt16 nRet = EXECUTE_NO;
1158     const SfxSlot *pSlot = 0;
1159     if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, sal_False, sal_False ) )
1160     {
1161         // Ausf"uhrbarkeit vorher testen
1162         if ( pSlot->IsMode( SFX_SLOT_FASTCALL ) ||
1163             pShell->CanExecuteSlot_Impl( *pSlot ) )
1164                 nRet = EXECUTE_POSSIBLE;
1165 
1166         if ( nMode == EXECUTEMODE_ASYNCHRON )
1167             eCall = SFX_CALLMODE_ASYNCHRON;
1168         else if ( nMode == EXECUTEMODE_DIALOGASYNCHRON && pSlot->IsMode( SFX_SLOT_HASDIALOG ) )
1169             eCall = SFX_CALLMODE_ASYNCHRON;
1170         else if ( pSlot->GetMode() & SFX_SLOT_ASYNCHRON )
1171             eCall = SFX_CALLMODE_ASYNCHRON;
1172         sal_Bool bDone = sal_False;
1173             SfxRequest aReq( nSlot, eCall, rArgs );
1174             _Execute( *pShell, *pSlot, aReq, eCall );
1175             bDone = aReq.IsDone();
1176     }
1177 
1178     return nRet;
1179 }
1180 
1181 sal_uInt16 SfxDispatcher::GetSlotId( const String& rCommand )
1182 {
1183     const SfxSlot *pSlot = GetSlot( rCommand );
1184     if ( pSlot )
1185         return pSlot->GetSlotId();
1186     return 0;
1187 }
1188 
1189 const SfxSlot* SfxDispatcher::GetSlot( const String& rCommand )
1190 {
1191     // Anzahl der Shells auf den verkettenten Dispatchern z"ahlen
1192     Flush();
1193     sal_uInt16 nTotCount = pImp->aStack.Count();
1194     if ( pImp->pParent )
1195     {
1196         SfxDispatcher *pParent = pImp->pParent;
1197         while ( pParent )
1198         {
1199             nTotCount = nTotCount + pParent->pImp->aStack.Count();
1200             pParent = pParent->pImp->pParent;
1201         }
1202     }
1203 
1204     const SfxSlot *pSlot=NULL;
1205     sal_uInt16 nFirstShell = 0;
1206     for ( sal_uInt16 i = nFirstShell; i < nTotCount; ++i )
1207     {
1208         SfxShell *pObjShell = GetShell(i);
1209         SfxInterface *pIFace = pObjShell->GetInterface();
1210         pSlot = pIFace->GetSlot( rCommand );
1211         if ( pSlot )
1212             return pSlot;
1213     }
1214 
1215     return 0;
1216 }
1217 
1218 //--------------------------------------------------------------------
1219 int SfxExecuteItem::operator==( const SfxPoolItem& rItem ) const
1220 {
1221     SfxExecuteItem& rArg = (SfxExecuteItem& )rItem;
1222     sal_uInt16 nCount = Count();
1223     if( nCount != rArg.Count() )
1224         return sal_False;
1225     while( nCount -- )
1226         if( *GetObject( nCount ) != *rArg.GetObject( nCount ) )
1227             return sal_False;
1228     return  eCall == rArg.eCall;
1229 }
1230 
1231 //--------------------------------------------------------------------
1232 SfxPoolItem* SfxExecuteItem::Clone( SfxItemPool* ) const
1233 {
1234     return new SfxExecuteItem( *this );
1235 }
1236 
1237 //--------------------------------------------------------------------
1238 SfxExecuteItem::SfxExecuteItem( const SfxExecuteItem& rArg )
1239     : SfxItemPtrArray(), SfxPoolItem( rArg ), nModifier( 0 )
1240 {
1241     eCall = rArg.eCall;
1242     nSlot = rArg.nSlot;
1243     sal_uInt16 nCount = rArg.Count();
1244     for( sal_uInt16 nPos = 0; nPos < nCount; nPos++ )
1245         Insert( rArg[ nPos ]->Clone(), nPos );
1246 }
1247 
1248 //--------------------------------------------------------------------
1249 SfxExecuteItem::SfxExecuteItem(
1250     sal_uInt16 nWhichId, sal_uInt16 nSlotP, SfxCallMode eModeP,
1251     const SfxPoolItem*  pArg1, ... ) :
1252     SfxPoolItem( nWhichId ), nSlot( nSlotP ), eCall( eModeP ), nModifier( 0 )
1253 {
1254     va_list pVarArgs;
1255     va_start( pVarArgs, pArg1 );
1256     for ( const SfxPoolItem *pArg = pArg1; pArg;
1257           pArg = va_arg( pVarArgs, const SfxPoolItem* ) )
1258         Insert( pArg->Clone(), Count() );
1259     va_end(pVarArgs);
1260 }
1261 
1262 //--------------------------------------------------------------------
1263 SfxExecuteItem::SfxExecuteItem(
1264     sal_uInt16 nWhichId, sal_uInt16 nSlotP, SfxCallMode eModeP )
1265     : SfxPoolItem( nWhichId ), nSlot( nSlotP ), eCall( eModeP ), nModifier( 0 )
1266 {
1267 }
1268 
1269 //--------------------------------------------------------------------
1270 const SfxPoolItem* SfxDispatcher::Execute( const SfxExecuteItem& rItem )
1271 {
1272     const SfxPoolItem** pPtr = new const SfxPoolItem*[ rItem.Count() + 1 ];
1273     for( sal_uInt16 nPos = rItem.Count(); nPos--; )
1274         pPtr[ nPos ] = rItem.GetObject( nPos );
1275     pPtr[ rItem.Count() ] = 0;
1276     const SfxPoolItem* pRet = Execute(
1277         rItem.GetSlot(), rItem.GetCallMode(), pPtr, rItem.GetModifier() );
1278 
1279     delete [] (SfxPoolItem**)pPtr;
1280 
1281     return pRet;
1282 }
1283 
1284 //--------------------------------------------------------------------
1285 const SfxPoolItem*  SfxDispatcher::Execute(
1286     sal_uInt16 nSlot,
1287     SfxCallMode nCall,
1288     SfxItemSet* pArgs,
1289     SfxItemSet* pInternalArgs,
1290     sal_uInt16 nModi)
1291 {
1292     if ( IsLocked(nSlot) )
1293         return 0;
1294 
1295     SfxShell *pShell = 0;
1296     const SfxSlot *pSlot = 0;
1297     if ( GetShellAndSlot_Impl( nSlot,  &pShell, &pSlot, sal_False,
1298                                SFX_CALLMODE_MODAL==(nCall&SFX_CALLMODE_MODAL) ) )
1299     {
1300         SfxAllItemSet aSet( pShell->GetPool() );
1301         if ( pArgs )
1302         {
1303             SfxItemIter aIter(*pArgs);
1304             for ( const SfxPoolItem *pArg = aIter.FirstItem();
1305                 pArg;
1306                 pArg = aIter.NextItem() )
1307                 MappedPut_Impl( aSet, *pArg );
1308         }
1309         SfxRequest aReq( nSlot, nCall, aSet );
1310         if (pInternalArgs)
1311             aReq.SetInternalArgs_Impl( *pInternalArgs );
1312         aReq.SetModifier( nModi );
1313 
1314         _Execute( *pShell, *pSlot, aReq, nCall );
1315         return aReq.GetReturnValue();
1316     }
1317     return 0;
1318 }
1319 
1320 //--------------------------------------------------------------------
1321 const SfxPoolItem* SfxDispatcher::Execute
1322 (
1323     sal_uInt16 nSlot,               // die Id der auszufuehrenden Funktion
1324     SfxCallMode eCall,          // SFX_CALLMODE_SYNCRHON, ..._ASYNCHRON oder ..._SLOT
1325     const SfxPoolItem **pArgs,  // 0-terminiertes C-Array von Parametern
1326     sal_uInt16 nModi,
1327     const SfxPoolItem **pInternalArgs // 0-terminiertes C-Array von Parametern
1328 )
1329 
1330 /*  [Beschreibung]
1331 
1332     Methode zum Ausf"uhren eines <SfxSlot>s "uber die Slot-Id.
1333 
1334 
1335     [R"uckgabewert]
1336 
1337     const SfxPoolItem*      Pointer auf ein bis zum n"achsten Durchlauf
1338                             der Message-Loop g"ultiges SfxPoolItem,
1339                             welches den R"uckgabewert enth"alt.
1340 
1341                             Oder ein 0-Pointer, wenn die Funktion nicht
1342                             ausgef"uhrt wurde (z.B. Abbruch durch den
1343                             Benutzer).
1344 */
1345 
1346 {
1347     if ( IsLocked(nSlot) )
1348         return 0;
1349 
1350     SfxShell *pShell = 0;
1351     const SfxSlot *pSlot = 0;
1352     if ( GetShellAndSlot_Impl( nSlot,  &pShell, &pSlot, sal_False,
1353                                SFX_CALLMODE_MODAL==(eCall&SFX_CALLMODE_MODAL) ) )
1354     {
1355         SfxRequest* pReq;
1356         if ( pArgs && *pArgs )
1357         {
1358             SfxAllItemSet aSet( pShell->GetPool() );
1359             for ( const SfxPoolItem **pArg = pArgs; *pArg; ++pArg )
1360                 MappedPut_Impl( aSet, **pArg );
1361             pReq = new SfxRequest( nSlot, eCall, aSet );
1362         }
1363         else
1364             pReq =  new SfxRequest( nSlot, eCall, pShell->GetPool() );
1365         pReq->SetModifier( nModi );
1366         if( pInternalArgs && *pInternalArgs)
1367         {
1368             SfxAllItemSet aSet( SFX_APP()->GetPool() );
1369             for ( const SfxPoolItem **pArg = pInternalArgs; *pArg; ++pArg )
1370                 aSet.Put( **pArg );
1371             pReq->SetInternalArgs_Impl( aSet );
1372         }
1373         _Execute( *pShell, *pSlot, *pReq, eCall );
1374         const SfxPoolItem* pRet = pReq->GetReturnValue();
1375         delete pReq; return pRet;
1376     }
1377     return 0;
1378 }
1379 
1380 //--------------------------------------------------------------------
1381 const SfxPoolItem* SfxDispatcher::Execute
1382 (
1383     sal_uInt16 nSlot,               // die Id der auszufuehrenden Funktion
1384     SfxCallMode eCall,          // SFX_CALLMODE_SYNCRHON, ..._ASYNCHRON oder ..._SLOT
1385     const SfxItemSet &rArgs     // <SfxItemSet> mit Parametern
1386 )
1387 
1388 /*  [Beschreibung]
1389 
1390     Methode zum Ausf"uhren eines <SfxSlot>s "uber die Slot-Id.
1391 
1392 
1393     [R"uckgabewert]
1394 
1395     const SfxPoolItem*      Pointer auf ein bis zum n"achsten Durchlauf
1396                             der Message-Loop g"ultiges SfxPoolItem,
1397                             welches den R"uckgabewert enth"alt.
1398 
1399                             Oder ein 0-Pointer, wenn die Funktion nicht
1400                             ausgef"uhrt wurde (z.B. Abbruch durch den
1401                             Benutzer).
1402 */
1403 
1404 {
1405     return Execute( nSlot, eCall, 0, rArgs );
1406 }
1407 
1408 //--------------------------------------------------------------------
1409 const SfxPoolItem*  SfxDispatcher::Execute
1410 (
1411     sal_uInt16 nSlot,
1412     SfxCallMode eCall,
1413     sal_uInt16 nModi,
1414     const SfxItemSet &rArgs
1415 )
1416 {
1417     if ( IsLocked(nSlot) )
1418         return 0;
1419 
1420     SfxShell *pShell = 0;
1421     const SfxSlot *pSlot = 0;
1422     if ( GetShellAndSlot_Impl( nSlot,  &pShell, &pSlot, sal_False,
1423                                SFX_CALLMODE_MODAL==(eCall&SFX_CALLMODE_MODAL) ) )
1424     {
1425         SfxAllItemSet aSet( pShell->GetPool() );
1426         SfxItemIter aIter(rArgs);
1427         for ( const SfxPoolItem *pArg = aIter.FirstItem();
1428               pArg;
1429               pArg = aIter.NextItem() )
1430             MappedPut_Impl( aSet, *pArg );
1431         SfxRequest aReq( nSlot, eCall, aSet );
1432         aReq.SetModifier( nModi );
1433         _Execute( *pShell, *pSlot, aReq, eCall );
1434         return aReq.GetReturnValue();
1435     }
1436     return 0;
1437 }
1438 
1439 //--------------------------------------------------------------------
1440 const SfxPoolItem* SfxDispatcher::_Execute
1441 (
1442     sal_uInt16              nSlot,      // die Id der auszufuehrenden Funktion
1443     SfxCallMode         eCall,      // SFX_CALLMODE_SYNCRHON, ..._ASYNCHRON oder ..._SLOT
1444     va_list             pVarArgs,   // Parameterliste ab 2. Parameter
1445     const SfxPoolItem*  pArg1       // erster Parameter
1446 )
1447 
1448 /*  [Beschreibung]
1449 
1450     Methode zum Ausf"uhren eines <SfxSlot>s "uber die Slot-Id.
1451 
1452 
1453     [R"uckgabewert]
1454 
1455     const SfxPoolItem*      Pointer auf ein bis zum n"achsten Durchlauf
1456                             der Message-Loop g"ultiges SfxPoolItem,
1457                             welches den R"uckgabewert enth"alt.
1458 
1459                             Oder ein 0-Pointer, wenn die Funktion nicht
1460                             ausgef"uhrt wurde (z.B. Abbruch durch den
1461                             Benutzer).
1462 */
1463 
1464 {
1465     if ( IsLocked(nSlot) )
1466         return 0;
1467 
1468     SfxShell *pShell = 0;
1469     const SfxSlot *pSlot = 0;
1470     if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, sal_False,
1471                                SFX_CALLMODE_MODAL==(eCall&SFX_CALLMODE_MODAL) ) )
1472     {
1473        SfxAllItemSet aSet( pShell->GetPool() );
1474 
1475        for ( const SfxPoolItem *pArg = pArg1;
1476              pArg;
1477              pArg = va_arg( pVarArgs, const SfxPoolItem* ) )
1478            MappedPut_Impl( aSet, *pArg );
1479 
1480        SfxRequest aReq( nSlot, eCall, aSet );
1481        _Execute( *pShell, *pSlot, aReq, eCall );
1482        return aReq.GetReturnValue();
1483     }
1484     return 0;
1485 }
1486 
1487 //--------------------------------------------------------------------
1488 const SfxPoolItem* SfxDispatcher::Execute
1489 (
1490     sal_uInt16              nSlot,      // die Id der auszufuehrenden Funktion
1491     SfxCallMode         eCall,      // SFX_CALLMODE_SYNCRHON, ..._ASYNCHRON oder ..._SLOT
1492     const SfxPoolItem*  pArg1,      // erster Parameter
1493     ...                             // 0-terminiertes Liste Parametern
1494 )
1495 
1496 /*  [Beschreibung]
1497 
1498     Methode zum Ausf"uhren eines <SfxSlot>s "uber die Slot-Id.
1499 
1500 
1501     [Anmerkung]
1502 
1503     Die Parameter werden kopiert, k"onnen daher als Adresse von
1504     Stack-Objekten "ubergeben werden.
1505 
1506 
1507     [R"uckgabewert]
1508 
1509     const SfxPoolItem*      Pointer auf ein bis zum n"achsten Durchlauf
1510                             der Message-Loop g"ultiges SfxPoolItem,
1511                             welches den R"uckgabewert enth"alt.
1512 
1513                             Oder ein 0-Pointer, wenn die Funktion nicht
1514                             ausgef"uhrt wurde (z.B. Abbruch durch den
1515                             Benutzer).
1516 
1517 
1518     [Beispiel]
1519 
1520     pDispatcher->Execute( SID_OPENDOCUMENT, SFX_CALLMODE_SYNCHRON,
1521         &SfxStringItem( SID_FILE_NAME, "\\tmp\\temp.sdd" ),
1522         &SfxStringItem( SID_FILTER_NAME, "StarDraw Presentation" ),
1523         &SfxBoolItem( SID_DOC_READONLY, sal_False ),
1524         0L );
1525 */
1526 
1527 {
1528     if ( IsLocked(nSlot) )
1529         return 0;
1530 
1531     SfxShell *pShell = 0;
1532     const SfxSlot *pSlot = 0;
1533     if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, sal_False,
1534                                SFX_CALLMODE_MODAL==(eCall&SFX_CALLMODE_MODAL) ) )
1535     {
1536        SfxAllItemSet aSet( pShell->GetPool() );
1537 
1538        va_list pVarArgs;
1539        va_start( pVarArgs, pArg1 );
1540        for ( const SfxPoolItem *pArg = pArg1;
1541              pArg;
1542              pArg = va_arg( pVarArgs, const SfxPoolItem* ) )
1543            MappedPut_Impl( aSet, *pArg );
1544        va_end(pVarArgs);
1545 
1546        SfxRequest aReq( nSlot, eCall, aSet );
1547        _Execute( *pShell, *pSlot, aReq, eCall );
1548        return aReq.GetReturnValue();
1549     }
1550     return 0;
1551 }
1552 
1553 //--------------------------------------------------------------------
1554 
1555 IMPL_LINK( SfxDispatcher, PostMsgHandler, SfxRequest*, pReq )
1556 
1557 /*  [Beschreibung]
1558 
1559     Hilfsmethode zum Empfangen der asynchron auszuf"uhrenden <SfxRequest>s.
1560 */
1561 
1562 {
1563     DBG_MEMTEST();
1564     DBG_ASSERT( !pImp->bFlushing, "recursive call to dispatcher" );
1565     SFX_STACK(SfxDispatcher::PostMsgHandler);
1566 
1567     // ist auch der Pool noch nicht gestorben?
1568 //    SfxRequest* pReq = pExec->pRequest;
1569     if ( !pReq->IsCancelled() )
1570     {
1571         if ( !IsLocked(pReq->GetSlot()) )
1572         {
1573             Flush();
1574             SfxSlotServer aSvr;
1575             if ( _FindServer(pReq->GetSlot(), aSvr, HACK(x) sal_True ) )
1576 //            SfxShell *pShell = GetShell(pExec->nLevel);
1577 //            if ( pShell && pShell->GetInterface()->GetSlot( pExec->pSlot->GetSlotId() ) )
1578             {
1579                 const SfxSlot *pSlot = aSvr.GetSlot();
1580                 SfxShell *pSh = GetShell(aSvr.GetShellLevel());
1581 
1582                 DBG( SfxApplication *pSfxApp = SFX_APP() );
1583                 DBG( pSfxApp->EnterAsynchronCall_Impl() );
1584 
1585                 // Wenn pSlot ein "Pseudoslot" f"ur Macros oder Verben ist, kann
1586                 // er im Call_Impl zerst"ort werden, also nicht mehr benutzen!
1587                 pReq->SetSynchronCall( sal_False );
1588                 Call_Impl( *pSh, *pSlot, *pReq, pReq->AllowsRecording() ); //! woher bRecord?
1589 //                Call_Impl( *pShell, *pExec->pSlot, *pReq, sal_True ); //! woher bRecord?
1590                 DBG( pSfxApp->LeaveAsynchronCall_Impl() );
1591             }
1592 
1593 //            delete pExec;
1594         }
1595         else
1596         {
1597 //            pImp->xPoster->Post(pExec);
1598             if ( pImp->bLocked )
1599                 pImp->aReqArr.Insert( new SfxRequest(*pReq), pImp->aReqArr.Count() );
1600             else
1601                 pImp->xPoster->Post(new SfxRequest(*pReq));
1602         }
1603     }
1604 //    else
1605 //        delete pExec;
1606 
1607     delete pReq;
1608     return 0;
1609 }
1610 //--------------------------------------------------------------------
1611 void SfxDispatcher::SetMenu_Impl()
1612 {
1613     if ( pImp->pFrame )
1614     {
1615         SfxViewFrame* pTop = pImp->pFrame->GetTopViewFrame();
1616         if ( pTop && pTop->GetBindings().GetDispatcher() == this )
1617         {
1618             SfxFrame& rFrame = pTop->GetFrame();
1619             if ( rFrame.IsMenuBarOn_Impl() )
1620             {
1621                 com::sun::star::uno::Reference < com::sun::star::beans::XPropertySet > xPropSet( rFrame.GetFrameInterface(), com::sun::star::uno::UNO_QUERY );
1622                 if ( xPropSet.is() )
1623                 {
1624                     com::sun::star::uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager;
1625                     com::sun::star::uno::Any aValue = xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" )));
1626                     aValue >>= xLayoutManager;
1627                     if ( xLayoutManager.is() )
1628                     {
1629                         rtl::OUString aMenuBarURL( RTL_CONSTASCII_USTRINGPARAM( "private:resource/menubar/menubar" ));
1630                         if ( !xLayoutManager->isElementVisible( aMenuBarURL ) )
1631                             xLayoutManager->createElement( aMenuBarURL );
1632                     }
1633                 }
1634             }
1635         }
1636     }
1637 }
1638 
1639 //--------------------------------------------------------------------
1640 void SfxDispatcher::Update_Impl( sal_Bool bForce )
1641 {
1642     SFX_STACK(SfxDispatcher::Update_Impl);
1643 
1644     Flush();
1645 
1646     if ( !pImp->pFrame || pImp->bUILocked )
1647         return;
1648 
1649     SFX_APP();  // -Wall is this required???
1650     SfxDispatcher *pDisp = this;
1651     sal_Bool bUpdate = bForce;
1652     while ( pDisp && pDisp->pImp->pFrame )
1653     {
1654         SfxWorkWindow *pWork = pDisp->pImp->pFrame->GetFrame().GetWorkWindow_Impl();
1655         SfxDispatcher *pAct = pWork->GetBindings().GetDispatcher_Impl();
1656         if ( pAct == pDisp || pAct == this )
1657         {
1658             if ( !bUpdate )
1659                 bUpdate = !pDisp->pImp->bUpdated;
1660             pDisp->pImp->bUpdated = sal_True;
1661         }
1662         else
1663             break;
1664 
1665         pDisp = pDisp->pImp->pParent;
1666     }
1667 
1668     if ( !bUpdate || pImp->pFrame->GetFrame().IsClosing_Impl() )
1669         return;
1670 
1671     SfxViewFrame* pTop = pImp->pFrame ? pImp->pFrame->GetTopViewFrame() : NULL;
1672     sal_Bool bUIActive = pTop && pTop->GetBindings().GetDispatcher() == this;
1673 
1674     if ( !bUIActive && pTop && GetBindings() == &pTop->GetBindings() )
1675         // keep own tools internally for collecting
1676         GetBindings()->GetDispatcher()->pImp->bUpdated = sal_False;
1677 
1678     SfxBindings* pBindings = GetBindings();
1679     if ( pBindings )
1680         pBindings->DENTERREGISTRATIONS();
1681 
1682     com::sun::star::uno::Reference< com::sun::star::frame::XFrame > xFrame = pBindings->GetActiveFrame();
1683     com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet > xPropSet( xFrame, com::sun::star::uno::UNO_QUERY );
1684     com::sun::star::uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager;
1685     if ( xPropSet.is() )
1686     {
1687         try
1688         {
1689             com::sun::star::uno::Any aValue = xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" )) );
1690             aValue >>= xLayoutManager;
1691         }
1692         catch ( com::sun::star::uno::Exception& )
1693         {
1694         }
1695     }
1696 
1697     if ( xLayoutManager.is() )
1698         xLayoutManager->lock();
1699 
1700     sal_Bool bIsIPActive = pImp->pFrame && pImp->pFrame->GetObjectShell()->IsInPlaceActive();
1701     SfxInPlaceClient *pClient = pImp->pFrame ? pImp->pFrame->GetViewShell()->GetUIActiveClient() : NULL;
1702     if ( bUIActive && /* !bIsIPActive && */ ( !pClient || !pClient->IsObjectUIActive() ) )
1703         SetMenu_Impl();
1704 
1705     SfxWorkWindow *pWorkWin = pImp->pFrame->GetFrame().GetWorkWindow_Impl();
1706     SfxWorkWindow *pTaskWin = pImp->pFrame->GetTopFrame().GetWorkWindow_Impl();
1707     pTaskWin->ResetStatusBar_Impl();
1708 
1709     SfxDispatcher *pDispat = this;
1710     while ( pDispat )
1711     {
1712         SfxWorkWindow *pWork = pDispat->pImp->pFrame->GetFrame().GetWorkWindow_Impl();
1713         SfxDispatcher *pAct = pWork->GetBindings().GetDispatcher_Impl();
1714         if ( pAct == pDispat || pAct == this )
1715         {
1716             pWork->ResetObjectBars_Impl();
1717             pWork->ResetChildWindows_Impl();
1718         }
1719 
1720         pDispat = pDispat->pImp->pParent;
1721     }
1722 
1723     sal_Bool bIsActive = sal_False;
1724     SfxDispatcher *pActDispat = pWorkWin->GetBindings().GetDispatcher_Impl();
1725     pDispat = this;
1726     while ( pActDispat && !bIsActive )
1727     {
1728         if ( pDispat == pActDispat )
1729             bIsActive = sal_True;
1730         pActDispat = pActDispat->pImp->pParent;
1731     }
1732 
1733     _Update_Impl( bUIActive, !bIsIPActive, bIsIPActive, pTaskWin );
1734     if ( bUIActive || bIsActive )
1735         pWorkWin->UpdateObjectBars_Impl();
1736 
1737     if ( pBindings )
1738         pBindings->DLEAVEREGISTRATIONS();
1739 
1740     if ( xLayoutManager.is() )
1741         xLayoutManager->unlock();
1742 
1743     return;
1744 }
1745 
1746 void SfxDispatcher::_Update_Impl( sal_Bool bUIActive, sal_Bool bIsMDIApp, sal_Bool bIsIPOwner, SfxWorkWindow *pTaskWin )
1747 {
1748     SFX_APP();
1749     SfxWorkWindow *pWorkWin = pImp->pFrame->GetFrame().GetWorkWindow_Impl();
1750     sal_Bool bIsActive = sal_False;
1751     sal_Bool bIsTaskActive = sal_False;
1752     SfxDispatcher *pActDispat = pWorkWin->GetBindings().GetDispatcher_Impl();
1753     SfxDispatcher *pDispat = this;
1754     while ( pActDispat && !bIsActive )
1755     {
1756         if ( pDispat == pActDispat )
1757             bIsActive = sal_True;
1758         pActDispat = pActDispat->pImp->pParent;
1759     }
1760 
1761     if ( pImp->pParent && !pImp->bQuiet /* && bUIActive */ )
1762         pImp->pParent->_Update_Impl( bUIActive, bIsMDIApp, bIsIPOwner, pTaskWin );
1763 
1764     for (sal_uInt16 n=0; n<SFX_OBJECTBAR_MAX; n++)
1765         pImp->aObjBars[n].nResId = 0;
1766     pImp->aChildWins.Remove(0, pImp->aChildWins.Count());
1767 
1768     // bQuiet : own shells aren't considered for UI and SlotServer
1769     // bNoUI: own Shells aren't considered fors UI
1770     if ( pImp->bQuiet || pImp->bNoUI || (pImp->pFrame && pImp->pFrame->GetObjectShell()->IsPreview()) )
1771         return;
1772 
1773     sal_uInt32 nStatBarId=0;
1774     SfxShell *pStatusBarShell = NULL;
1775 
1776     SfxSlotPool* pSlotPool = &SfxSlotPool::GetSlotPool( GetFrame() );
1777     sal_uInt16 nTotCount = pImp->aStack.Count();
1778     for ( sal_uInt16 nShell = nTotCount; nShell > 0; --nShell )
1779     {
1780         SfxShell *pShell = GetShell( nShell-1 );
1781         SfxInterface *pIFace = pShell->GetInterface();
1782 
1783         // don't consider shells if "Hidden" oder "Quiet"
1784         sal_Bool bReadOnlyShell = IsReadOnlyShell_Impl( nShell-1 );
1785         sal_uInt16 nNo;
1786         for ( nNo = 0; pIFace && nNo<pIFace->GetObjectBarCount(); ++nNo )
1787         {
1788             sal_uInt16 nPos = pIFace->GetObjectBarPos(nNo);
1789             if ( bReadOnlyShell && !( nPos & SFX_VISIBILITY_READONLYDOC ) )
1790                 continue;
1791 
1792             // check wether toolbar needs activation of a special feature
1793             sal_uInt32 nFeature = pIFace->GetObjectBarFeature(nNo);
1794             if ( nFeature && !pShell->HasUIFeature( nFeature ) )
1795                 continue;
1796 
1797             // check for toolboxes that are exclusively for a viewer
1798             if ( pImp->pFrame)
1799             {
1800                 sal_Bool bViewerTbx = SFX_VISIBILITY_VIEWER == ( nPos & SFX_VISIBILITY_VIEWER );
1801                 SfxObjectShell* pSh = pImp->pFrame->GetObjectShell();
1802                 SFX_ITEMSET_ARG( pSh->GetMedium()->GetItemSet(), pItem, SfxBoolItem, SID_VIEWONLY, sal_False );
1803                 sal_Bool bIsViewer = pItem && pItem->GetValue();
1804                 if ( bIsViewer != bViewerTbx )
1805                     continue;
1806             }
1807 
1808             // always register toolbars, allows to switch them on
1809             sal_Bool bVisible = pIFace->IsObjectBarVisible(nNo);
1810             if ( !bVisible )
1811                 nPos &= SFX_POSITION_MASK;
1812 
1813             SfxObjectBars_Impl& rBar = pImp->aObjBars[nPos & SFX_POSITION_MASK];
1814             rBar.nMode = nPos;
1815             rBar.nResId = pIFace->GetObjectBarResId(nNo).GetId();
1816             const String *pName = pIFace->GetObjectBarName(nNo);
1817             if ( pName )
1818                 rBar.aName = *pName;
1819             else
1820                 rBar.aName.Erase();
1821             rBar.pIFace = pIFace;
1822 
1823             if ( bUIActive || bIsActive )
1824             {
1825                 pWorkWin->SetObjectBar_Impl(
1826                     nPos, rBar.nResId, rBar.pIFace, &rBar.aName );
1827             }
1828 
1829             if ( !bVisible )
1830                 rBar.nResId = 0;
1831         }
1832 
1833         for ( nNo=0; pIFace && nNo<pIFace->GetChildWindowCount(); nNo++ )
1834         {
1835             sal_uInt32 nId = pIFace->GetChildWindowId(nNo);
1836             const SfxSlot *pSlot = pSlotPool->GetSlot( (sal_uInt16) nId );
1837             DBG_ASSERT( pSlot, "Childwindow slot missing!");
1838             if ( bReadOnlyShell )
1839             {
1840                 // only show ChildWindows if their slot is allowed for readonly documents
1841                 if ( pSlot && !pSlot->IsMode( SFX_SLOT_READONLYDOC ) )
1842                     continue;
1843             }
1844 
1845             sal_uInt32 nFeature = pIFace->GetChildWindowFeature(nNo);
1846             if ( nFeature && !pShell->HasUIFeature( nFeature ) )
1847                 continue;
1848 
1849             // slot decides wether a ChildWindow is shown when document is OLE server or OLE client
1850             sal_uInt16 nMode = SFX_VISIBILITY_STANDARD;
1851             if( pSlot )
1852             {
1853                 if ( pSlot->IsMode(SFX_SLOT_CONTAINER) )
1854                 {
1855                     if ( pWorkWin->IsVisible_Impl( SFX_VISIBILITY_CLIENT ) )
1856                         nMode |= SFX_VISIBILITY_CLIENT;
1857                 }
1858                 else
1859                 {
1860                     if ( pWorkWin->IsVisible_Impl( SFX_VISIBILITY_SERVER ) )
1861                         nMode |= SFX_VISIBILITY_SERVER;
1862                 }
1863             }
1864 
1865             if ( bUIActive || bIsActive )
1866                 pWorkWin->SetChildWindowVisible_Impl( nId, sal_True, nMode );
1867             if ( bUIActive || bIsActive || !pWorkWin->IsFloating( (sal_uInt16) ( nId & 0xFFFF ) ) )
1868                 pImp->aChildWins.Insert( nId, pImp->aChildWins.Count());
1869         }
1870 
1871         if ( bIsMDIApp || bIsIPOwner )
1872         {
1873             sal_uInt32 nId = pIFace->GetStatusBarResId().GetId();
1874             if ( nId )
1875             {
1876                 nStatBarId = nId;
1877                 pStatusBarShell =  pShell;
1878             }
1879         }
1880     }
1881 
1882     for ( sal_uInt16 nPos=0; nPos<SFX_OBJECTBAR_MAX; nPos++ )
1883     {
1884         SfxObjectBars_Impl& rFixed = pImp->aFixedObjBars[nPos];
1885         if ( rFixed.nResId )
1886         {
1887             SfxObjectBars_Impl& rBar = pImp->aObjBars[nPos];
1888             rBar = rFixed;
1889             pWorkWin->SetObjectBar_Impl( rFixed.nMode,
1890                 rFixed.nResId, rFixed.pIFace, &rFixed.aName );
1891         }
1892     }
1893 
1894     if ( pTaskWin && ( bIsMDIApp || bIsIPOwner ) )
1895     {
1896         SfxDispatcher *pActDispatcher = pTaskWin->GetBindings().GetDispatcher_Impl();
1897         SfxDispatcher *pDispatcher = this;
1898         while ( pActDispatcher && !bIsTaskActive )
1899         {
1900             if ( pDispatcher == pActDispatcher )
1901                 bIsTaskActive = sal_True;
1902             pActDispatcher = pActDispatcher->pImp->pParent;
1903         }
1904 
1905         if ( bIsTaskActive && nStatBarId && pImp->pFrame )
1906         {
1907             // internal frames also may control statusbar
1908             SfxBindings& rBindings = pImp->pFrame->GetBindings();
1909             pImp->pFrame->GetFrame().GetWorkWindow_Impl()->SetStatusBar_Impl( nStatBarId, pStatusBarShell, rBindings );
1910         }
1911     }
1912 }
1913 
1914 //--------------------------------------------------------------------
1915 void SfxDispatcher::FlushImpl()
1916 
1917 /*  [Beschreibung]
1918 
1919     Hilfsmethode zum Ausf"uhren der ausstehenden Push- und Pop-Befehle.
1920 */
1921 
1922 {
1923     DBG_PROFSTART(SfxDispatcherFlush);
1924     DBG_MEMTEST();
1925     SFX_STACK(SfxDispatcher::FlushImpl);
1926 
1927     DBG_TRACE("Flushing dispatcher!");
1928 
1929 #ifdef DBG_UTIL
1930     ByteString aMsg( "SfxDispatcher(" );
1931     aMsg += ByteString::CreateFromInt64( (sal_uIntPtr) this );
1932     aMsg += ")::Flush()";
1933 #endif
1934 
1935     pImp->aTimer.Stop();
1936 
1937     if ( pImp->pParent )
1938         pImp->pParent->Flush();
1939 
1940 //  if ( pImp->bQuiet )
1941 //      return;
1942 
1943     pImp->bFlushing = !pImp->bFlushing;
1944     if ( !pImp->bFlushing )
1945     {
1946         pImp->bFlushing = sal_True;
1947         DBG_PROFSTOP(SfxDispatcherFlush);
1948 //!
1949 #ifdef DBG_UTIL_MESSEHACK_AUSKOMMENT
1950         DBG_ERROR( "reentering SfxDispatcher::Flush()" );
1951         aMsg += " reentering, aborted";
1952         DbgTrace( aMsg.GetBuffer() );
1953 #endif
1954         return;
1955     }
1956 
1957     SfxApplication *pSfxApp = SFX_APP();
1958 
1959     // in der 1. Runde den echten Stack 'um'bauen
1960     SfxToDoStack_Impl aToDoCopy;
1961     sal_Bool bModify = sal_False;
1962     short nToDo;
1963     for ( nToDo = pImp->aToDoStack.Count()-1; nToDo >= 0; --nToDo )
1964     {
1965         bModify = sal_True;
1966 
1967         SfxToDo_Impl aToDo( pImp->aToDoStack.Top(nToDo) );
1968         if ( aToDo.bPush )
1969         {
1970             // tats"aechlich pushen
1971             DBG_ASSERT( !pImp->aStack.Contains( aToDo.pCluster ),
1972                         "pushed SfxShell already on stack" );
1973             pImp->aStack.Push( aToDo.pCluster );
1974             aToDo.pCluster->SetDisableFlags( pImp->nDisableFlags );
1975 
1976             // die bewegte Shell merken
1977             aToDoCopy.Push( aToDo );
1978         }
1979         else
1980         {
1981             // tats"aechlich poppen
1982             SfxShell* pPopped = 0;
1983             bool bFound = sal_False;
1984             do
1985             {
1986                 DBG_ASSERT( pImp->aStack.Count(), "popping from empty stack" );
1987                 pPopped = pImp->aStack.Pop();
1988                 pPopped->SetDisableFlags( 0 );
1989                 bFound = pPopped == aToDo.pCluster;
1990 
1991                 // die bewegte Shell merken
1992                 aToDoCopy.Push( SfxToDo_Impl( sal_False, aToDo.bDelete, sal_False, *pPopped) );
1993             }
1994             while ( aToDo.bUntil && !bFound );
1995             DBG_ASSERT( bFound, "wrong SfxShell popped" );
1996         }
1997 
1998         if ( nToDo == 0 )
1999             pImp->aToDoStack.Clear();
2000     }
2001 
2002     // ggf. Bindings invalidieren
2003     if ( !pSfxApp->IsDowning() )
2004     {
2005         if ( bModify )
2006         {
2007             pImp->pCachedServ1 = 0;
2008             pImp->pCachedServ2 = 0;
2009         }
2010 
2011         InvalidateBindings_Impl( bModify );
2012     }
2013 
2014     pImp->bFlushing = sal_False;
2015     pImp->bUpdated = sal_False; // nicht nur bei bModify, falls Doc/Template-Config
2016     bFlushed = sal_True;
2017     DBG_TRACE("Successfully flushed dispatcher!");
2018 
2019     // in der 2. Runde die Shells aktivieren und ggf. l"oschen
2020     for ( nToDo = aToDoCopy.Count()-1; nToDo >= 0; --nToDo )
2021     {
2022         SfxToDo_Impl aToDo( aToDoCopy.Top(nToDo) );
2023         if ( aToDo.bPush )
2024         {
2025             if ( pImp->bActive )
2026                 aToDo.pCluster->DoActivate_Impl(pImp->pFrame, sal_True);
2027         }
2028         else
2029             if ( pImp->bActive )
2030                 aToDo.pCluster->DoDeactivate_Impl(pImp->pFrame, sal_True);
2031     }
2032     for ( nToDo = aToDoCopy.Count()-1; nToDo >= 0; --nToDo )
2033     {
2034         SfxToDo_Impl aToDo( aToDoCopy.Top(nToDo) );
2035         if ( aToDo.bDelete ) delete aToDo.pCluster;
2036     }
2037     sal_Bool bAwakeBindings = aToDoCopy.Count() != 0;
2038     if( bAwakeBindings )
2039         aToDoCopy.Clear();
2040 
2041     // Wenn bei Activate/Deactivate/Delete weitere Stackbewegungen erfolgt sind :
2042     if (!bFlushed)
2043         // falls jemand Push/Pop gerufen hat, wurde auch EnterReg gerufen!
2044         FlushImpl();
2045 
2046     if( bAwakeBindings && GetBindings() )
2047         GetBindings()->DLEAVEREGISTRATIONS();
2048     DBG_PROFSTOP(SfxDispatcherFlush);
2049 
2050     for (sal_uInt16 n=0; n<SFX_OBJECTBAR_MAX; n++)
2051         pImp->aFixedObjBars[n].nResId = 0;
2052 
2053 #ifdef DBG_UTIL
2054     aMsg += " done";
2055     DbgTrace( aMsg.GetBuffer() );
2056 #endif
2057 }
2058 
2059 //--------------------------------------------------------------------
2060 void SfxDispatcher::SetSlotFilter
2061 (
2062     HACK(hier muss mal ein enum rein)
2063     sal_Bool            bEnable,    /*  sal_True:
2064                                     nur angegebene Slots enablen,
2065                                     alle anderen disablen
2066 
2067                                     sal_False:
2068                                     die angegebenen Slots disablen,
2069                                     alle anderen zun"achst enablen
2070                                 */
2071     sal_uInt16          nCount,     //  Anzahl der SIDs im folgenden Array
2072     const sal_uInt16*   pSIDs       //  sortiertes Array von 'nCount' SIDs
2073 )
2074 
2075 /*  [Beschreibung]
2076 
2077     Mit dieser Methode wird ein Filter gesetzt, mit dem gezielt Slots
2078     enabled bzw. disabled werden k"onnen. Das "ubergebene Array mu\s
2079     bis zum Dtor bzw. n"achsten <SetSlotFilter()> erhalten bleiben, es
2080     wird nicht vom Dispatcher gel"oscht, es kann daher static sein.
2081 
2082     In ReadOnly-Dokumenten kann man mit 'bEnable==2' quasi das ReadOnlyDoc
2083     Flag von Slots "ubersteuern, dieser werden also wieder gefunden. Auf
2084     andere Slots hat das dann keine Auswirkung.
2085 
2086 
2087     [Beispiel]
2088 
2089     gezieltes disablen der Slots 1, 2 und 3:
2090 
2091         static sal_uInt16 __READONLY_DATA pSIDs[] = { 1, 2, 3 };
2092         pDisp->SetSlotFilter( sal_False, sizeof(pSIDs)/sizeof(sal_uInt16), pSIDs );
2093 
2094     nur die Slots 5, 6 und 7 zulassen:
2095 
2096         static sal_uInt16 __READONLY_DATA pSIDs[] = { 5, 6, 7 };
2097         pDisp->SetSlotFilter( sal_True, sizeof(pSIDs)/sizeof(sal_uInt16), pSIDs );
2098 
2099     Filter ausschalten:
2100 
2101         pDisp->SetSlotFilter();
2102 */
2103 
2104 {
2105 #ifdef DBG_UTIL
2106     // Array "uberpr"ufen
2107     for ( sal_uInt16 n = 1; n < nCount; ++n )
2108         DBG_ASSERT( pSIDs[n] > pSIDs[n-1], "SetSlotFilter: SIDs not sortet" );
2109 #endif
2110 
2111     if ( pImp->pFilterSIDs )
2112         pImp->pFilterSIDs = 0;
2113 
2114     pImp->bFilterEnabling = bEnable;
2115     pImp->nFilterCount = nCount;
2116     pImp->pFilterSIDs = pSIDs;
2117 
2118     GetBindings()->InvalidateAll(sal_True);
2119 }
2120 
2121 //--------------------------------------------------------------------
2122 EXTERN_C
2123 #if defined( PM2 ) && (!defined( CSET ) && !defined ( MTW ) && !defined( WTC ))
2124 int _stdcall
2125 #else
2126 #ifdef WNT
2127 int _cdecl
2128 #else
2129 int
2130 #endif
2131 #endif
2132 
2133 SfxCompareSIDs_Impl( const void* pSmaller, const void* pBigger )
2134 {
2135     DBG_MEMTEST();
2136     return ( (long) *((sal_uInt16*)pSmaller) ) - ( (long) *((sal_uInt16*)pBigger) );
2137 }
2138 
2139 //--------------------------------------------------------------------
2140 sal_Bool SfxDispatcher::IsSlotEnabledByFilter_Impl( sal_uInt16 nSID ) const
2141 
2142 /*  [Beschreibung]
2143 
2144     Sucht 'nSID' in dem mit <SetSlotFilter()> gesetzten Filter und
2145     liefert sal_True, falls die SID erlaubt ist, bzw. sal_False, falls sie
2146     durch den Filter disabled ist.
2147 
2148     [R"uckgabewert]
2149     sal_Bool                0   =>  disabled
2150                         1   =>  enabled
2151                         2   =>  enabled even if ReadOnlyDoc
2152 */
2153 
2154 {
2155     // kein Filter?
2156     if ( 0 == pImp->nFilterCount )
2157         // => alle SIDs erlaubt
2158         return sal_True;
2159 
2160     // suchen
2161     sal_Bool bFound = 0 != bsearch( &nSID, pImp->pFilterSIDs, pImp->nFilterCount,
2162                                 sizeof(sal_uInt16), SfxCompareSIDs_Impl );
2163 
2164     // even if ReadOnlyDoc
2165     if ( 2 == pImp->bFilterEnabling )
2166         return bFound ? 2 : 1;
2167     // sonst je nach Negativ/Positiv Filter
2168     return pImp->bFilterEnabling ? bFound : !bFound;
2169 }
2170 
2171 //--------------------------------------------------------------------
2172 sal_Bool SfxDispatcher::_TryIntercept_Impl
2173 (
2174     sal_uInt16              nSlot,      // zu suchende Slot-Id
2175     SfxSlotServer&      rServer,    // zu f"uellende <SfxSlotServer>-Instanz
2176     sal_Bool                bSelf
2177 )
2178 {
2179     // Eventuell geh"ort der parent auch zu einer Komponente
2180     SfxDispatcher *pParent = pImp->pParent;
2181     sal_uInt16 nLevels = pImp->aStack.Count();
2182     while ( pParent && pParent->pImp->pFrame )
2183     {
2184         if ( pParent->pImp->pFrame->GetFrame().HasComponent() )
2185         {
2186             // Components d"urfen intercepten
2187             if ( pParent->_TryIntercept_Impl( nSlot, rServer, sal_True ) )
2188             {
2189                 // Die eigenen Shells zum Shelllevel hinzuz"ahlen
2190                 rServer.SetShellLevel( rServer.GetShellLevel() + nLevels );
2191                 return sal_True;
2192             }
2193             else
2194                 // Keine weitere Interception
2195                 break;
2196         }
2197         else
2198             nLevels = nLevels + pParent->pImp->aStack.Count();
2199 
2200         pParent = pParent->pImp->pParent;
2201     }
2202 
2203     if ( bSelf )
2204     {
2205         // Die ComponentViewShell befragen
2206         Flush();
2207         SfxShell *pObjShell = GetShell(0);
2208         SfxInterface *pIFace = pObjShell->GetInterface();
2209         const SfxSlot *pSlot = pIFace->GetSlot(nSlot);
2210 
2211         if ( pSlot )
2212         {
2213             rServer.SetSlot(pSlot);
2214             rServer.SetShellLevel(0);
2215 #ifdef DBG_UTILx
2216             String aMsg( nSlot );
2217             aMsg += " intercepted";
2218             DbgTrace( aMsg.GetBuffer() );
2219 #endif
2220             return sal_True;
2221         }
2222     }
2223 
2224     return sal_False;
2225 }
2226 
2227 sal_Bool SfxDispatcher::_FindServer
2228 (
2229     sal_uInt16              nSlot,      // zu suchende Slot-Id
2230     SfxSlotServer&   rServer,    // zu f"uellnde <SfxSlotServer>-Instanz
2231     sal_Bool                bModal      // trotz ModalMode
2232 )
2233 
2234 /*  [Beschreibung]
2235 
2236     Diese Hilfsmethode sucht den <Slot-Server>, der nSlot zur Zeit bedient.
2237     Als Ergebnis wird rServer entsprechend gef"ullt.
2238 
2239     Falls bekannt, kann das SfxInterface mitgegeben werden, von welchem
2240     nSlot momentan bedient wird.
2241 
2242     Vor der Suche nach nSlot wird der SfxDispatcher geflusht.
2243 
2244 
2245     [R"uckgabewert]
2246 
2247     sal_Bool                sal_True
2248                         Der Slot wurde gefunden, rServer ist g"ultig.
2249 
2250                         sal_False
2251                         Der Slot wird momentan nicht bedient, rServer
2252                         ist ung"ultig.
2253 */
2254 
2255 {
2256     SFX_STACK(SfxDispatcher::_FindServer);
2257 
2258     // Dispatcher gelockt? (SID_HELP_PI trotzdem durchlassen)
2259     if ( IsLocked(nSlot) )
2260     {
2261         pImp->bInvalidateOnUnlock = sal_True;
2262         return sal_False;
2263     }
2264 
2265     // Anzahl der Shells auf den verkettenten Dispatchern z"ahlen
2266     Flush();
2267     sal_uInt16 nTotCount = pImp->aStack.Count();
2268     if ( pImp->pParent )
2269     {
2270         SfxDispatcher *pParent = pImp->pParent;
2271         while ( pParent )
2272         {
2273             nTotCount = nTotCount + pParent->pImp->aStack.Count();
2274             pParent = pParent->pImp->pParent;
2275         }
2276     }
2277 
2278     // Verb-Slot?
2279     if (nSlot >= SID_VERB_START && nSlot <= SID_VERB_END)
2280     {
2281         for ( sal_uInt16 nShell = 0;; ++nShell )
2282         {
2283             SfxShell *pSh = GetShell(nShell);
2284             if ( pSh == NULL )
2285                 return false;
2286             if ( pSh->ISA(SfxViewShell) )
2287             {
2288                 const SfxSlot* pSlot = pSh->GetVerbSlot_Impl(nSlot);
2289                 if ( pSlot )
2290                 {
2291                     rServer.SetShellLevel(nShell);
2292                     rServer.SetSlot( pSlot );
2293                     return true;
2294                 }
2295             }
2296         }
2297     }
2298 
2299     // SID gegen gesetzten Filter pr"ufen
2300     sal_uInt16 nSlotEnableMode=0;
2301     if ( pImp->pFrame )
2302     {
2303         nSlotEnableMode = IsSlotEnabledByFilter_Impl( nSlot );
2304         if ( 0 == nSlotEnableMode )
2305             return sal_False;
2306     }
2307 
2308     // im Quiet-Mode nur Parent-Dispatcher
2309     if ( pImp->bQuiet )
2310     {
2311         if ( pImp->pParent )
2312         {
2313             sal_Bool bRet = pImp->pParent->_FindServer( nSlot, rServer, bModal );
2314             rServer.SetShellLevel
2315                 ( rServer.GetShellLevel() + pImp->aStack.Count() );
2316             return bRet;
2317         }
2318         else
2319             return sal_False;
2320     }
2321 
2322     sal_Bool bReadOnly = ( 2 != nSlotEnableMode && pImp->bReadOnly );
2323 //              ( pImp->pFrame && pImp->pFrame->GetObjectShell() );
2324 //                pImp->pFrame->GetObjectShell()->IsLoading() );
2325 
2326     // durch alle Shells der verketteten Dispatchern von oben nach unten suchen
2327 #ifdef DBG_UTILx
2328     String aStack( "Stack:" );
2329 #endif
2330     sal_uInt16 nFirstShell = pImp->bModal && !bModal ? pImp->aStack.Count() : 0;
2331     for ( sal_uInt16 i = nFirstShell; i < nTotCount; ++i )
2332     {
2333         SfxShell *pObjShell = GetShell(i);
2334         SfxInterface *pIFace = pObjShell->GetInterface();
2335         const SfxSlot *pSlot = pIFace->GetSlot(nSlot);
2336 
2337         if ( pSlot && pSlot->nDisableFlags && ( pSlot->nDisableFlags & pObjShell->GetDisableFlags() ) != 0 )
2338             return sal_False;
2339 
2340         if ( pSlot && !( pSlot->nFlags & SFX_SLOT_READONLYDOC ) && bReadOnly )
2341             return sal_False;
2342 
2343         if ( pSlot )
2344         {
2345             // Slot geh"ort zum Container?
2346             bool bIsContainerSlot = pSlot->IsMode(SFX_SLOT_CONTAINER);
2347             bool bIsInPlace = pImp->pFrame && pImp->pFrame->GetObjectShell()->IsInPlaceActive();
2348 
2349             // Shell geh"ort zum Server?
2350             // AppDispatcher oder IPFrame-Dispatcher
2351             bool bIsServerShell = !pImp->pFrame || bIsInPlace;
2352 
2353             // Nat"urlich sind ServerShell-Slots auch ausf"uhrbar, wenn sie auf
2354             // einem Container-Dispatcher ohne IPClient ausgef"uhrt werden sollen.
2355             if ( !bIsServerShell )
2356             {
2357                 SfxViewShell *pViewSh = pImp->pFrame->GetViewShell();
2358                 bIsServerShell = !pViewSh || !pViewSh->GetUIActiveClient();
2359             }
2360 
2361             // Shell geh"ort zum Container?
2362             // AppDispatcher oder kein IPFrameDispatcher
2363             bool bIsContainerShell = !pImp->pFrame || !bIsInPlace;
2364             // Shell und Slot passen zusammen
2365             if ( !( ( bIsContainerSlot && bIsContainerShell ) ||
2366                     ( !bIsContainerSlot && bIsServerShell ) ) )
2367                 pSlot = 0;
2368         }
2369 
2370 #ifdef DBG_UTILx
2371         if ( pSlot )
2372         {
2373             String aMsg( nSlot );
2374             aMsg += " found in ";
2375             aMsg += pObjShell->GetInterface()->GetClassName();
2376             DbgTrace( aMsg.GetBuffer() );
2377         }
2378         else
2379         {
2380             aStack += " ";
2381             aStack += pObjShell->GetInterface()->GetClassName();
2382         }
2383 #endif
2384         if ( pSlot && !IsAllowed( nSlot ) )
2385         {
2386             pSlot = NULL;
2387         }
2388 
2389         if ( pSlot )
2390         {
2391             rServer.SetSlot(pSlot);
2392             rServer.SetShellLevel(i);
2393             return sal_True;
2394         }
2395     }
2396 
2397 #ifdef DBG_UTILx
2398     String aMsg( nSlot );
2399     aMsg += " not found in ";
2400     aMsg += aStack;
2401     DbgTrace( aMsg.GetBuffer() );
2402 #endif
2403     return sal_False;
2404 }
2405 
2406 sal_Bool SfxDispatcher::HasSlot_Impl( sal_uInt16 nSlot )
2407 {
2408     Flush();
2409     sal_uInt16 nTotCount = pImp->aStack.Count();
2410 
2411     if ( pImp->pParent && !pImp->pParent->pImp->pFrame )
2412     {
2413         // the last frame also uses the AppDispatcher
2414         nTotCount = nTotCount + pImp->aStack.Count();
2415     }
2416 
2417     if (nSlot >= SID_VERB_START && nSlot <= SID_VERB_END)
2418     {
2419         // Verb-Slot?
2420         for ( sal_uInt16 nShell = 0;; ++nShell )
2421         {
2422             SfxShell *pSh = GetShell(nShell);
2423             if ( pSh == NULL )
2424                 return false;
2425             if ( pSh->ISA(SfxViewShell) )
2426                 return true;
2427         }
2428     }
2429 
2430     // SID gegen gesetzten Filter pr"ufen
2431     sal_uInt16 nSlotEnableMode=0;
2432     if ( pImp->pFrame )
2433     {
2434         nSlotEnableMode = IsSlotEnabledByFilter_Impl( nSlot );
2435         if ( 0 == nSlotEnableMode )
2436             return sal_False;
2437     }
2438 
2439     // im Quiet-Mode nur Parent-Dispatcher
2440     if ( pImp->bQuiet )
2441         return sal_False;
2442 
2443     sal_Bool bReadOnly = ( 2 != nSlotEnableMode && pImp->bReadOnly );
2444 //              ( pImp->pFrame && pImp->pFrame->GetObjectShell());
2445 //                pImp->pFrame->GetObjectShell()->IsLoading() );
2446 
2447     for ( sal_uInt16 i=0 ; i < nTotCount; ++i )
2448     {
2449         SfxShell *pObjShell = GetShell(i);
2450         SfxInterface *pIFace = pObjShell->GetInterface();
2451         const SfxSlot *pSlot = pIFace->GetSlot(nSlot);
2452         if ( pSlot && pSlot->nDisableFlags && ( pSlot->nDisableFlags & pObjShell->GetDisableFlags() ) != 0 )
2453             return sal_False;
2454 
2455         if ( pSlot && !( pSlot->nFlags & SFX_SLOT_READONLYDOC ) && bReadOnly )
2456             return sal_False;
2457 
2458         if ( pSlot )
2459         {
2460             // Slot geh"ort zum Container?
2461             bool bIsContainerSlot = pSlot->IsMode(SFX_SLOT_CONTAINER);
2462             bool bIsInPlace = pImp->pFrame && pImp->pFrame->GetObjectShell()->IsInPlaceActive();
2463 
2464             // Shell geh"ort zum Server?
2465             // AppDispatcher oder IPFrame-Dispatcher
2466             bool bIsServerShell = !pImp->pFrame || bIsInPlace;
2467 
2468             // Nat"urlich sind ServerShell-Slots auch ausf"uhrbar, wenn sie auf
2469             // einem Container-Dispatcher ohne IPClient ausgef"uhrt werden sollen.
2470             if ( !bIsServerShell )
2471             {
2472                 SfxViewShell *pViewSh = pImp->pFrame->GetViewShell();
2473                 bIsServerShell = !pViewSh || !pViewSh->GetUIActiveClient();
2474             }
2475 
2476             // Shell geh"ort zum Container?
2477             // AppDispatcher oder kein IPFrameDispatcher
2478             bool bIsContainerShell = !pImp->pFrame || !bIsInPlace;
2479 
2480             // Shell und Slot passen zusammen
2481             if ( !( ( bIsContainerSlot && bIsContainerShell ) ||
2482                     ( !bIsContainerSlot && bIsServerShell ) ) )
2483                 pSlot = 0;
2484         }
2485 
2486         if ( pSlot && !IsAllowed( nSlot ) )
2487             pSlot = NULL;
2488 
2489         if ( pSlot )
2490             return sal_True;
2491     }
2492 
2493     return sal_False;
2494 }
2495 
2496 
2497 
2498 //--------------------------------------------------------------------
2499 sal_Bool SfxDispatcher::_FillState
2500 (
2501     const SfxSlotServer& rSvr,       // abzufragende <Slot-Server>
2502     SfxItemSet&             rState,     // zu f"ullendes <SfxItemSet>
2503     const SfxSlot*          pRealSlot   // ggf. der tats"achliche Slot
2504 )
2505 
2506 /*  [Beschreibung]
2507 
2508     Hilfsmethode zum Abfragen des Status des <Slot-Server>s rSvr.
2509     In rState m"ussen die gew"unschten Slots-Ids (teilweise in Which-Ids
2510     des betreffenden Pools umgewandelt) vorhanden sein.
2511 
2512     Der SfxDispatcher wird vor der Abfrage geflusht.
2513 */
2514 
2515 {
2516     SFX_STACK(SfxDispatcher::_FillState);
2517 
2518     DBG_PROFSTART(SfxDispatcherFillState);
2519 
2520     const SfxSlot *pSlot = rSvr.GetSlot();
2521     if ( pSlot && IsLocked( pSlot->GetSlotId() ) )
2522     {
2523         pImp->bInvalidateOnUnlock = sal_True;
2524         DBG_PROFSTOP(SfxDispatcherFillState);
2525         return sal_False;
2526     }
2527 
2528     if ( pSlot )
2529     {
2530         DBG_ASSERT(bFlushed, "Dispatcher not flushed after retrieving slot servers!");
2531         if ( !bFlushed )
2532             return sal_False;
2533         // Flush();
2534 
2535         // Objekt ermitteln und Message an diesem Objekt aufrufen
2536         SfxShell *pSh = GetShell(rSvr.GetShellLevel());
2537         DBG_ASSERT(pSh, "ObjektShell nicht gefunden");
2538 
2539         SfxStateFunc pFunc;
2540 
2541         if (pRealSlot)
2542             pFunc = pRealSlot->GetStateFnc();
2543         else
2544             pFunc = pSlot->GetStateFnc();
2545 
2546         pSh->CallState( pFunc, rState );
2547 #ifdef DBG_UTIL
2548         // pr"ufen, ob IDL (SlotMap) und aktuelle Items "ubereinstimmen
2549         if ( DbgIsAssertWarning() && rState.Count() )
2550         {
2551             SfxInterface *pIF = pSh->GetInterface();
2552             SfxItemIter aIter( rState );
2553             for ( const SfxPoolItem *pItem = aIter.FirstItem();
2554                   pItem;
2555                   pItem = aIter.NextItem() )
2556                 if ( !IsInvalidItem(pItem) && !pItem->ISA(SfxVoidItem) )
2557                 {
2558                     sal_uInt16 nSlotId = rState.GetPool()->GetSlotId(pItem->Which());
2559                     if ( !pItem->IsA(pIF->GetSlot(nSlotId)->GetType()->Type()) )
2560                     {
2561                         ByteString aMsg( "item-type unequal to IDL (=> no BASIC)" );
2562                         aMsg += "\nwith SID: ";
2563                         aMsg += ByteString::CreateFromInt32( nSlotId );
2564                         aMsg += "\nin ";
2565                         aMsg += pIF->GetClassName();
2566                         DbgOut( aMsg.GetBuffer(), DBG_OUT_ERROR, __FILE__, __LINE__);
2567                     }
2568                 }
2569         }
2570 #endif
2571 
2572         DBG_PROFSTOP(SfxDispatcherFillState);
2573         return sal_True;
2574     }
2575 
2576     DBG_PROFSTOP(SfxDispatcherFillState);
2577     return sal_False;
2578 }
2579 
2580 //--------------------------------------------------------------------
2581 const SfxPoolItem* SfxDispatcher::_Execute( const SfxSlotServer &rSvr )
2582 
2583 /*  [Beschreibung]
2584 
2585     Diese Methode f"uhrt einen Request "uber einen gecachten <Slot-Server>
2586     aus.
2587 */
2588 
2589 {
2590     const SfxSlot *pSlot = rSvr.GetSlot();
2591     if ( IsLocked( pSlot->GetSlotId() ) )
2592         return 0;
2593 
2594     if ( pSlot )
2595     {
2596         Flush();
2597 
2598         if ( pSlot->IsMode(SFX_SLOT_ASYNCHRON) )
2599             //! ignoriert rSvr
2600         {
2601             SfxShell *pShell = GetShell( rSvr.GetShellLevel() );
2602             SfxDispatcher *pDispat = this;
2603             while ( pDispat )
2604             {
2605                 sal_uInt16 nShellCount = pDispat->pImp->aStack.Count();
2606                 for ( sal_uInt16 n=0; n<nShellCount; n++ )
2607                     if ( pShell == pDispat->pImp->aStack.Top(n) )
2608                     {
2609                         pDispat->pImp->xPoster->Post(
2610                             new SfxRequest( pSlot->GetSlotId(),
2611                                 SFX_CALLMODE_RECORD, pShell->GetPool() ) );
2612 //                        pDispat->pImp->xPoster->Post(new Executer(
2613 //                                new SfxRequest( pSlot->GetSlotId(),
2614 //                                    SFX_CALLMODE_RECORD, pShell->GetPool() ),
2615 //                                pSlot, n ));
2616                         return 0;
2617                     }
2618             }
2619         }
2620         else
2621         {
2622             // Objekt ermitteln und Message an diesem Objekt aufrufen
2623             SfxShell *pSh = GetShell(rSvr.GetShellLevel());
2624             SfxRequest aReq( pSlot->GetSlotId(), SFX_CALLMODE_RECORD, pSh->GetPool() );
2625             if ( Call_Impl( *pSh, *pSlot, aReq, sal_True ) ) // von Bindings immer recorden
2626                 return aReq.GetReturnValue();
2627         }
2628     }
2629     return 0;
2630 }
2631 
2632 //----------------------------------------------------------------------
2633 void SfxDispatcher::ExecutePopup( sal_uInt16 nConfigId,
2634                                   Window *pWin, const Point *pPos,
2635                                   const SfxPoolItem *, ... )
2636 {
2637     ExecutePopup( nConfigId, pWin, pPos );
2638 }
2639 
2640 SfxPopupMenuManager* SfxDispatcher::Popup( sal_uInt16 nConfigId,Window *pWin, const Point *pPos )
2641 {
2642     SfxDispatcher &rDisp = *SFX_APP()->GetDispatcher_Impl();
2643     sal_uInt16 nShLevel = 0;
2644     SfxShell *pSh;
2645     nShLevel=0;
2646 
2647     if ( rDisp.pImp->bQuiet )
2648     {
2649         nConfigId = 0;
2650         nShLevel = rDisp.pImp->aStack.Count();
2651     }
2652 
2653     Window *pWindow = pWin ? pWin : rDisp.pImp->pFrame->GetFrame().GetWorkWindow_Impl()->GetWindow();
2654     for ( pSh = rDisp.GetShell(nShLevel); pSh; ++nShLevel, pSh = rDisp.GetShell(nShLevel) )
2655     {
2656         const ResId& rResId = pSh->GetInterface()->GetPopupMenuResId();
2657         if ( ( nConfigId == 0 && rResId.GetId() ) || ( nConfigId != 0 && rResId.GetId() == nConfigId ) )
2658         {
2659                 return SfxPopupMenuManager::Popup( rResId, rDisp.GetFrame(), pPos ? *pPos : pWindow->GetPointerPosPixel(), pWindow );
2660         }
2661     }
2662     return 0;
2663 }
2664 
2665 
2666 //----------------------------------------------------------------------
2667 void SfxDispatcher::ExecutePopup( sal_uInt16 nConfigId, Window *pWin, const Point *pPos )
2668 {
2669     SfxDispatcher &rDisp = *SFX_APP()->GetDispatcher_Impl();
2670     sal_uInt16 nShLevel = 0;
2671     SfxShell *pSh;
2672 /*
2673     const SvVerbList *pVerbList = 0;
2674     sal_uInt16 nMaxShellLevel = rDisp.pImp->aStack.Count();
2675     for ( pSh = rDisp.GetShell(nShLevel);
2676           pSh && nShLevel < nMaxShellLevel ;
2677           ++nShLevel, pSh = rDisp.GetShell(nShLevel) )
2678     {
2679         if ( pSh->GetVerbs() )
2680         {
2681             pVerbList = pSh->GetVerbs();
2682             break;
2683         }
2684     }
2685 */
2686     nShLevel=0;
2687     if ( rDisp.pImp->bQuiet )
2688     {
2689         nConfigId = 0;
2690         nShLevel = rDisp.pImp->aStack.Count();
2691     }
2692 
2693     Window *pWindow = pWin ? pWin : rDisp.pImp->pFrame->GetFrame().GetWorkWindow_Impl()->GetWindow();
2694     for ( pSh = rDisp.GetShell(nShLevel); pSh; ++nShLevel, pSh = rDisp.GetShell(nShLevel) )
2695     {
2696         const ResId& rResId = pSh->GetInterface()->GetPopupMenuResId();
2697         if ( ( nConfigId == 0 && rResId.GetId() ) || ( nConfigId != 0 && rResId.GetId() == nConfigId ) )
2698         {
2699             //SfxPopupMenuManager aPop( rResId.GetId(), *rDisp.GetBindings() );
2700             //aPop.SetResMgr(rResId.GetResMgr());
2701             //aPop.AddClipboardFunctions();
2702             //aPop.Initialize();
2703             //if ( pVerbList && pVerbList->Count() )
2704             //    aPop.InsertVerbs(pVerbList);
2705             //aPop.RemoveDisabledEntries();
2706             //aPop.Execute( pPos ? *pPos : pWindow->GetPointerPosPixel(), pWindow );
2707             SfxPopupMenuManager::ExecutePopup( rResId, rDisp.GetFrame(), pPos ? *pPos : pWindow->GetPointerPosPixel(), pWindow );
2708             return;
2709         }
2710     }
2711 }
2712 
2713 //----------------------------------------------------------------------
2714 void SfxDispatcher::ExecutePopup( const ResId &rId, Window *pWin, const Point *pPos )
2715 {
2716     Window *pWindow = pWin ? pWin : pImp->pFrame->GetFrame().GetWorkWindow_Impl()->GetWindow();
2717 /*
2718     SfxPopupMenuManager aPop( rId, *GetBindings() );
2719     aPop.AddClipboardFunctions();
2720     aPop.Initialize();
2721     aPop.RemoveDisabledEntries();
2722     aPop.Execute( pPos ? *pPos : pWindow->GetPointerPosPixel(), pWindow );
2723 */
2724     SfxPopupMenuManager::ExecutePopup( rId, GetFrame(), pPos ? *pPos : pWindow->GetPointerPosPixel(), pWindow );
2725 }
2726 
2727 //--------------------------------------------------------------------
2728 void SfxDispatcher::Lock( sal_Bool bLock )
2729 
2730 /*  [Beschreibung]
2731 
2732     Mit dieser Methode kann der SfxDispatcher gesperrt und freigegeben
2733     werden. Ein gesperrter SfxDispatcher f"uhrt keine <SfxRequest>s mehr
2734     aus und liefert keine Status-Informationen mehr. Er verh"alt sich
2735     so als w"aren alle Slots disabled.
2736 */
2737 
2738 {
2739     SfxBindings* pBindings = GetBindings();
2740     if ( !bLock && pImp->bLocked && pImp->bInvalidateOnUnlock )
2741     {
2742         if ( pBindings )
2743             pBindings->InvalidateAll(sal_True);
2744         pImp->bInvalidateOnUnlock = sal_False;
2745     }
2746     else if ( pBindings )
2747         pBindings->InvalidateAll(sal_False);
2748     pImp->bLocked = bLock;
2749     if ( !bLock )
2750     {
2751         sal_uInt16 nCount = pImp->aReqArr.Count();
2752         for ( sal_uInt16 i=0; i<nCount; i++ )
2753             pImp->xPoster->Post( pImp->aReqArr[i] );
2754         pImp->aReqArr.Remove( 0, nCount );
2755     }
2756 }
2757 
2758 sal_uInt32 SfxDispatcher::GetObjectBarId( sal_uInt16 nPos ) const
2759 {
2760     return pImp->aObjBars[nPos].nResId;
2761 }
2762 
2763 //--------------------------------------------------------------------
2764 void SfxDispatcher::ResetObjectBars_Impl()
2765 
2766 /*  [Beschreibung]
2767 
2768     Mit dieser Methode werden alle Objectbar-Anforderungen, die dieser
2769     Dispatcher an das AppWindow hat, beseitigt.
2770 */
2771 {
2772     for (sal_uInt16 n=0; n<SFX_OBJECTBAR_MAX; n++)
2773         pImp->aObjBars[n].nResId = 0;
2774     pImp->aChildWins.Remove(0, pImp->aChildWins.Count());
2775 }
2776 
2777 
2778 //--------------------------------------------------------------------
2779 void SfxDispatcher::DebugOutput_Impl() const
2780 {
2781 #ifdef DBG_UTIL
2782 
2783     sal_uInt16 nOld = (sal_uInt16) DbgGetData()->nTraceOut;
2784     DbgGetData()->nTraceOut = DBG_OUT_FILE;
2785 
2786     if (bFlushed)
2787         DBG_TRACE("Flushed");
2788     if (pImp->bUpdated)
2789         DBG_TRACE("Updated");
2790 
2791     for ( sal_uInt16 nShell = pImp->aStack.Count(); nShell > 0; --nShell )
2792     {
2793         SfxShell *pShell = GetShell(nShell-1);
2794         const SfxInterface *pIFace = pShell->GetInterface();
2795         DBG_TRACE (pIFace->GetClassName());
2796     }
2797 
2798     DbgGetData()->nTraceOut = nOld;
2799 
2800 #endif
2801 }
2802 
2803 void SfxDispatcher::LockUI_Impl( sal_Bool bLock )
2804 {
2805     sal_Bool bWasLocked = pImp->bUILocked;
2806     pImp->bUILocked = bLock;
2807     if ( !bLock && bWasLocked )
2808         Update_Impl( sal_True );
2809 }
2810 
2811 //-------------------------------------------------------------------------
2812 void SfxDispatcher::HideUI( sal_Bool bHide )
2813 {
2814 //  if ( !bHide && pImp->bReadOnly )
2815 //      bHide = sal_True;
2816     sal_Bool bWasHidden = pImp->bNoUI;
2817     pImp->bNoUI = bHide;
2818     if ( pImp->pFrame )
2819     {
2820         SfxViewFrame* pTop = pImp->pFrame->GetTopViewFrame();
2821         if ( pTop && pTop->GetBindings().GetDispatcher() == this )
2822         {
2823             SfxFrame& rFrame = pTop->GetFrame();
2824             if ( rFrame.IsMenuBarOn_Impl() )
2825             {
2826                 com::sun::star::uno::Reference < com::sun::star::beans::XPropertySet > xPropSet( rFrame.GetFrameInterface(), com::sun::star::uno::UNO_QUERY );
2827                 if ( xPropSet.is() )
2828                 {
2829                     com::sun::star::uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager;
2830                     com::sun::star::uno::Any aValue = xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" )));
2831                     aValue >>= xLayoutManager;
2832                     if ( xLayoutManager.is() )
2833                         xLayoutManager->setVisible( !bHide );
2834                 }
2835             }
2836         }
2837     }
2838 
2839     if ( bHide != bWasHidden )
2840         Update_Impl( sal_True );
2841 }
2842 
2843 void SfxDispatcher::SetReadOnly_Impl( sal_Bool bOn )
2844 {
2845     pImp->bReadOnly = bOn;
2846 //  pImp->bNoUI = bOn;
2847 }
2848 
2849 sal_Bool SfxDispatcher::GetReadOnly_Impl() const
2850 {
2851     return pImp->bReadOnly;
2852 }
2853 
2854 //-------------------------------------------------------------------------
2855 void SfxDispatcher::SetQuietMode_Impl( sal_Bool bOn )
2856 
2857 /*  [Beschreibung]
2858 
2859     Bei 'bOn' stellt sich dieser Dispatcher quasi tot und leitet alles
2860     an den Parent-Dispatcher weiter.
2861 */
2862 
2863 {
2864     pImp->bQuiet = bOn;
2865     SfxBindings* pBindings = GetBindings();
2866     if ( pBindings )
2867         pBindings->InvalidateAll(sal_True);
2868 }
2869 
2870 //-------------------------------------------------------------------------
2871 void SfxDispatcher::SetModalMode_Impl( sal_Bool bOn )
2872 
2873 /*  [Beschreibung]
2874 
2875     Bei 'bOn' werden nur noch Slots des Parent-Dispatchers gefunden.
2876 */
2877 
2878 {
2879     pImp->bModal = bOn;
2880     SfxBindings* pBindings = GetBindings();
2881     if ( pBindings )
2882         pBindings->InvalidateAll(sal_True);
2883 }
2884 
2885 void SfxDispatcher::SetExecuteMode( sal_uInt16 nMode )
2886 {
2887     pImp->nStandardMode = nMode;
2888 }
2889 
2890 SfxItemState SfxDispatcher::QueryState( sal_uInt16 nSlot, const SfxPoolItem* &rpState )
2891 {
2892     SfxShell *pShell = 0;
2893     const SfxSlot *pSlot = 0;
2894     if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, sal_False, sal_False ) )
2895     {
2896         rpState = pShell->GetSlotState(nSlot);
2897         if ( !rpState )
2898             return SFX_ITEM_DISABLED;
2899         else
2900             return SFX_ITEM_AVAILABLE;
2901     }
2902 
2903     return SFX_ITEM_DISABLED;
2904 }
2905 
2906 SfxItemState SfxDispatcher::QueryState( sal_uInt16 nSID, ::com::sun::star::uno::Any& rAny )
2907 {
2908     SfxShell *pShell = 0;
2909     const SfxSlot *pSlot = 0;
2910     if ( GetShellAndSlot_Impl( nSID, &pShell, &pSlot, sal_False, sal_False ) )
2911     {
2912         const SfxPoolItem* pItem( 0 );
2913 
2914         pItem = pShell->GetSlotState( nSID );
2915         if ( !pItem )
2916             return SFX_ITEM_DISABLED;
2917         else
2918         {
2919             ::com::sun::star::uno::Any aState;
2920             if ( !pItem->ISA(SfxVoidItem) )
2921             {
2922                 sal_uInt16 nSubId( 0 );
2923                 SfxItemPool& rPool = pShell->GetPool();
2924                 sal_uInt16 nWhich = rPool.GetWhich( nSID );
2925                 if ( rPool.GetMetric( nWhich ) == SFX_MAPUNIT_TWIP )
2926                     nSubId |= CONVERT_TWIPS;
2927                 pItem->QueryValue( aState, (sal_uInt8)nSubId );
2928             }
2929             rAny = aState;
2930 
2931             return SFX_ITEM_AVAILABLE;
2932         }
2933     }
2934 
2935     return SFX_ITEM_DISABLED;
2936 }
2937 
2938 sal_Bool SfxDispatcher::IsReadOnlyShell_Impl( sal_uInt16 nShell ) const
2939 {
2940     sal_uInt16 nShellCount = pImp->aStack.Count();
2941     if ( nShell < nShellCount )
2942     {
2943         SfxShell* pShell = pImp->aStack.Top( nShell );
2944         if( pShell->ISA( SfxModule ) || pShell->ISA( SfxApplication ) || pShell->ISA( SfxViewFrame ) )
2945             return sal_False;
2946         else
2947             return pImp->bReadOnly;
2948     }
2949     else if ( pImp->pParent )
2950         return pImp->pParent->IsReadOnlyShell_Impl( nShell - nShellCount );
2951     return sal_True;
2952 }
2953 
2954 // Ein dirty trick, um an die Methoden der private base class von
2955 // SfxShellStack_Impl heranzukommen
2956 class StackAccess_Impl : public SfxShellStack_Implarr_
2957 {};
2958 
2959 void SfxDispatcher::InsertShell_Impl( SfxShell& rShell, sal_uInt16 nPos )
2960 {
2961     Flush();
2962 
2963     // Der cast geht, weil SfxShellStack_Impl keine eigenen member hat
2964     ((StackAccess_Impl*) (&pImp->aStack))->Insert( nPos, &rShell );
2965     rShell.SetDisableFlags( pImp->nDisableFlags );
2966     rShell.DoActivate_Impl(pImp->pFrame, sal_True);
2967 
2968     if ( !SFX_APP()->IsDowning() )
2969     {
2970         pImp->bUpdated = sal_False;
2971         pImp->pCachedServ1 = 0;
2972         pImp->pCachedServ2 = 0;
2973         InvalidateBindings_Impl(sal_True);
2974     }
2975 }
2976 
2977 void SfxDispatcher::RemoveShell_Impl( SfxShell& rShell )
2978 {
2979     Flush();
2980 
2981     // Der cast geht, weil SfxShellStack_Impl keine eigenen member hat
2982     StackAccess_Impl& rStack = *((StackAccess_Impl*) (&pImp->aStack));
2983     sal_uInt16 nCount = rStack.Count();
2984     for ( sal_uInt16 n=0; n<nCount; ++n )
2985     {
2986         if ( rStack[n] == &rShell )
2987         {
2988             rStack.Remove( n );
2989             rShell.SetDisableFlags( 0 );
2990             rShell.DoDeactivate_Impl(pImp->pFrame, sal_True);
2991             break;
2992         }
2993     }
2994 
2995     if ( !SFX_APP()->IsDowning() )
2996     {
2997         pImp->bUpdated = sal_False;
2998         pImp->pCachedServ1 = 0;
2999         pImp->pCachedServ2 = 0;
3000         InvalidateBindings_Impl(sal_True);
3001     }
3002 }
3003 
3004 sal_Bool SfxDispatcher::IsAllowed
3005 (
3006     sal_uInt16 nSlot
3007 ) const
3008 /*
3009     [Beschreibung]
3010     Die Methode prueft, ob der Zugriff auf diese Schnittstelle erlaubt ist.
3011     */
3012 {
3013     if ( !pImp->pDisableList )
3014     {
3015         return sal_True;
3016     }
3017 
3018     // BinSearch in der DisableListe
3019     SvUShorts& rList = *pImp->pDisableList;
3020     sal_uInt16 nCount = rList.Count();
3021     sal_uInt16 nLow = 0, nMid = 0, nHigh;
3022     sal_Bool bFound = sal_False;
3023     nHigh = nCount - 1;
3024 
3025     while ( !bFound && nLow <= nHigh )
3026     {
3027         nMid = (nLow + nHigh) >> 1;
3028         DBG_ASSERT( nMid < nCount, "bsearch ist buggy" );
3029 
3030         int nDiff = (int) nSlot - (int) rList[nMid];
3031         if ( nDiff < 0)
3032         {
3033             if ( nMid == 0 )
3034                 break;
3035             nHigh = nMid - 1;
3036         }
3037         else if ( nDiff > 0 )
3038         {
3039             nLow = nMid + 1;
3040             if ( nLow == 0 )
3041                 break;
3042         }
3043         else
3044             bFound = sal_True;
3045     }
3046 
3047 #ifdef _DEBUG
3048     // Slot in der Liste gefunden ?
3049     sal_uInt16 nPos = bFound ? nMid : nLow;
3050 
3051     DBG_ASSERT( nPos <= nCount, "" );
3052     DBG_ASSERT( nPos == nCount || nSlot <= rList[nPos], "" );
3053     DBG_ASSERT( nPos == 0 || nSlot > rList[nPos-1], "" );
3054     DBG_ASSERT( ( (nPos+1) >= nCount ) || nSlot < rList[nPos+1], "" );
3055 #endif
3056 
3057     return !bFound;
3058 }
3059 
3060 void SfxDispatcher::InvalidateBindings_Impl( sal_Bool bModify )
3061 {
3062     // App-Dispatcher?
3063     if ( IsAppDispatcher() )
3064     {
3065         for ( SfxViewFrame *pFrame = SfxViewFrame::GetFirst();
3066                 pFrame;
3067                 pFrame = SfxViewFrame::GetNext( *pFrame ) )
3068             pFrame->GetBindings().InvalidateAll(bModify);
3069     }
3070     else
3071     {
3072         SfxDispatcher *pDisp = GetBindings()->GetDispatcher_Impl();
3073         while ( pDisp )
3074         {
3075             if ( pDisp == this )
3076             {
3077                 GetBindings()->InvalidateAll( bModify );
3078                 break;
3079             }
3080 
3081             pDisp = pDisp->pImp->pParent;
3082         }
3083     }
3084 }
3085 
3086 sal_Bool SfxDispatcher::IsUpdated_Impl() const
3087 {
3088     return pImp->bUpdated;
3089 }
3090 
3091 void SfxDispatcher::SetDisableFlags( sal_uInt32 nFlags )
3092 {
3093     pImp->nDisableFlags = nFlags;
3094     for ( int i = int(pImp->aStack.Count()) - 1; i >= 0; --i )
3095         pImp->aStack.Top( (sal_uInt16) i )->SetDisableFlags( nFlags );
3096 }
3097 
3098 sal_uInt32 SfxDispatcher::GetDisableFlags() const
3099 {
3100     return pImp->nDisableFlags;
3101 }
3102 
3103 SfxModule* SfxDispatcher::GetModule() const
3104 {
3105     for ( sal_uInt16 nShell = 0;; ++nShell )
3106     {
3107         SfxShell *pSh = GetShell(nShell);
3108         if ( pSh == NULL )
3109             return 0;
3110         if ( pSh->ISA(SfxModule) )
3111             return (SfxModule*) pSh;
3112     }
3113 }
3114