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