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