xref: /aoo42x/main/sfx2/source/control/dispatch.cxx (revision 940681c7)
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 whether 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 whether 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