summaryrefslogtreecommitdiff
path: root/sfx2/source/control
diff options
context:
space:
mode:
authorJens-Heiner Rechtien <hr@openoffice.org>2000-09-18 16:07:07 +0000
committerJens-Heiner Rechtien <hr@openoffice.org>2000-09-18 16:07:07 +0000
commitfd069bee7e57ad529c3c0974559fd2d84ec3151a (patch)
treeef2eddeefb786feaf966d6a1c0c291872c0ae420 /sfx2/source/control
parent04c1c754ab9d0ad07f2c5362d46597d13efe75c2 (diff)
initial import
Diffstat (limited to 'sfx2/source/control')
-rw-r--r--sfx2/source/control/bindings.cxx3022
-rw-r--r--sfx2/source/control/ctrlitem.cxx480
-rw-r--r--sfx2/source/control/dispatch.cxx3493
-rw-r--r--sfx2/source/control/macrconf.cxx947
-rw-r--r--sfx2/source/control/macro.cxx858
-rw-r--r--sfx2/source/control/makefile.mk120
-rw-r--r--sfx2/source/control/minfitem.cxx136
-rw-r--r--sfx2/source/control/msg.cxx101
-rw-r--r--sfx2/source/control/msgpool.cxx627
-rw-r--r--sfx2/source/control/objface.cxx1427
-rw-r--r--sfx2/source/control/request.cxx576
-rw-r--r--sfx2/source/control/shell.cxx1524
-rw-r--r--sfx2/source/control/srchitem.cxx306
-rw-r--r--sfx2/source/control/statcach.cxx577
-rw-r--r--sfx2/source/control/unoctitm.cxx560
15 files changed, 14754 insertions, 0 deletions
diff --git a/sfx2/source/control/bindings.cxx b/sfx2/source/control/bindings.cxx
new file mode 100644
index 000000000000..ea5e1a3f7c67
--- /dev/null
+++ b/sfx2/source/control/bindings.cxx
@@ -0,0 +1,3022 @@
+/*************************************************************************
+ *
+ * $RCSfile: bindings.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 16:52:29 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _SFXITEMPOOL_HXX //autogen
+#include <svtools/itempool.hxx>
+#endif
+#ifndef _SFXITEMITER_HXX //autogen
+#include <svtools/itemiter.hxx>
+#endif
+#ifndef _SFXENUMITEM_HXX //autogen
+#include <svtools/eitem.hxx>
+#endif
+#ifndef _AEITEM_HXX //autogen
+#include <svtools/aeitem.hxx>
+#endif
+#include <svtools/intitem.hxx>
+#include <svtools/stritem.hxx>
+
+#ifndef _COM_SUN_STAR_UTIL_XURLTRANSFORMER_HPP_
+#include <com/sun/star/util/XURLTransformer.hpp>
+#endif
+#ifndef _COM_SUN_STAR_FRAME_XDISPATCHPROVIDERINTERCEPTOR_HPP_
+#include <com/sun/star/frame/XDispatchProviderInterceptor.hpp>
+#endif
+#ifndef _COM_SUN_STAR_FRAME_XDISPATCH_HPP_
+#include <com/sun/star/frame/XDispatch.hpp>
+#endif
+#ifndef _COM_SUN_STAR_FRAME_XDISPATCHPROVIDER_HPP_
+#include <com/sun/star/frame/XDispatchProvider.hpp>
+#endif
+#ifndef _COM_SUN_STAR_FRAME_XSTATUSLISTENER_HPP_
+#include <com/sun/star/frame/XStatusListener.hpp>
+#endif
+#ifndef _COM_SUN_STAR_FRAME_FRAMESEARCHFLAG_HPP_
+#include <com/sun/star/frame/FrameSearchFlag.hpp>
+#endif
+#ifndef _COM_SUN_STAR_FRAME_XDISPATCHPROVIDERINTERCEPTION_HPP_
+#include <com/sun/star/frame/XDispatchProviderInterception.hpp>
+#endif
+#ifndef _COM_SUN_STAR_FRAME_FEATURESTATEEVENT_HPP_
+#include <com/sun/star/frame/FeatureStateEvent.hpp>
+#endif
+#ifndef _COM_SUN_STAR_FRAME_DISPATCHDESCRIPTOR_HPP_
+#include <com/sun/star/frame/DispatchDescriptor.hpp>
+#endif
+#ifndef _COM_SUN_STAR_FRAME_XCONTROLLER_HPP_
+#include <com/sun/star/frame/XController.hpp>
+#endif
+#include <unotools/processfactory.hxx>
+
+#pragma hdrstop
+
+#include "ipfrm.hxx"
+#include "ipenv.hxx"
+#include "interno.hxx"
+#include "bindings.hxx"
+#include "msg.hxx"
+#include "statcach.hxx"
+#include "ctrlitem.hxx"
+#include "app.hxx"
+#include "appdata.hxx"
+#include "dispatch.hxx"
+#include "request.hxx"
+#include "objface.hxx"
+#include "sfxtypes.hxx"
+#include "workwin.hxx"
+#include "macrconf.hxx"
+#include "unoctitm.hxx"
+#include "sfx.hrc"
+#include "sfxuno.hxx"
+#include "topfrm.hxx"
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::util;
+
+DBG_NAME(SfxBindingsMsgPos);
+DBG_NAME(SfxBindingsUpdateServers);
+DBG_NAME(SfxBindingsCreateSet);
+DBG_NAME(SfxBindingsUpdateCtrl1);
+DBG_NAME(SfxBindingsUpdateCtrl2);
+DBG_NAME(SfxBindingsNextJob_Impl0);
+DBG_NAME(SfxBindingsNextJob_Impl);
+DBG_NAME(SfxBindingsUpdate_Impl);
+DBG_NAME(SfxBindingsInvalidateAll);
+
+//====================================================================
+
+#define TIMEOUT_FIRST 20
+#define TIMEOUT_UPDATING 0
+#define TIMEOUT_IDLE 2500
+
+static sal_uInt32 nCache1 = 0;
+static sal_uInt32 nCache2 = 0;
+
+//====================================================================
+//TYPEINIT1(SfxSlotInterceptorItem, SfxPoolItem);
+
+DECL_PTRARRAY(SfxStateCacheArr_Impl, SfxStateCache*, 32, 16);
+DECL_PTRARRAY(SfxInterceptorArr_Impl, SfxSlotInterceptor*, 2, 2);
+
+//====================================================================
+
+struct SfxSlotInterceptor_Impl
+{
+ SfxBindings* _pBindings;
+ sal_Bool _bIsActive;
+};
+
+//====================================================================
+
+class SfxBindings_Impl
+
+/* [Beschreibung]
+
+ Diese Implementations-Struktur der Klasse SfxBindings dient
+ der Entkopplung von "Anderungen vom exportierten Interface sowie
+ der Verringerung von extern sichtbaren Symbolen.
+
+ Eine Instanz exisitiert pro SfxBindings-Instanz f"ur deren Laufzeit.
+*/
+
+{
+public:
+ ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > xProv;
+ SfxUnoControllerArr_Impl*
+ pUnoCtrlArr;
+ SfxWorkWindow* pWorkWin;
+ SfxBindings* pSubBindings;
+ SfxBindings* pSuperBindings;
+ SfxInterceptorArr_Impl* pInterceptors; // Slots vor dem Dispatcher abfangen
+ SfxStateCacheArr_Impl* pCaches; // je ein cache fuer jede gebundene
+ sal_uInt16 nCachedFunc1; // index der zuletzt gerufenen
+ sal_uInt16 nCachedFunc2; // index der vorletzt gerufenen
+ sal_uInt16 nMsgPos; // Message-Position, ab der zu aktualisieren ist
+ SfxPopupAction ePopupAction; // in DeleteFloatinWindow() abgefragt
+ sal_Bool bMsgDirty; // wurde ein MessageServer invalidiert?
+ sal_Bool bAllMsgDirty; // wurden die MessageServer invalidiert?
+ sal_Bool bAllDirty; // nach InvalidateAll
+ sal_Bool bCtrlReleased; // waehrend EnterRegistrations
+ AutoTimer aTimer; // fuer volatile Slots
+ sal_Bool bInUpdate; // fuer Assertions
+ sal_Bool bInNextJob; // fuer Assertions
+ sal_Bool bFirstRound; // Erste Runde im Update
+ sal_uInt16 nFirstShell; // Shell, die in erster Runde bevorzugt wird
+// sal_Bool bInExecute; // zum Test auf synchrone Executes
+ sal_uInt16 nOwnRegLevel; // z"ahlt die echten Locks, ohne die der SuperBindings
+
+ void InsertSlotInterceptor( SfxSlotInterceptor* );
+ void RemoveSlotInterceptor( SfxSlotInterceptor* );
+};
+
+void SfxBindings_Impl::InsertSlotInterceptor( SfxSlotInterceptor* pInter )
+{
+ // ggf. Interceptor-Liste on-demand erzeugen
+ if ( !pInterceptors )
+ pInterceptors = new SfxInterceptorArr_Impl;
+ pInterceptors->Insert( 0, pInter );
+
+ if ( pSubBindings )
+ pSubBindings->pImp->InsertSlotInterceptor( pInter );
+}
+
+void SfxBindings_Impl::RemoveSlotInterceptor( SfxSlotInterceptor* pInter )
+{
+ // bei den Bindings austragen
+ pInterceptors->Remove( pInter );
+
+ // gar kein SfxSlotInterceptor mehr => auf 0 setzen (f"ur Schnellabfrage)
+ if ( !pInterceptors->Count() )
+ DELETEZ( pInterceptors );
+
+ if ( pSubBindings )
+ pSubBindings->pImp->RemoveSlotInterceptor( pInter );
+}
+
+//--------------------------------------------------------------------
+
+struct SfxFoundCache_Impl
+
+/* [Beschreibung]
+
+ In Instanzen dieser Struktur werden in <SfxBindings::CreateSet_Impl()>
+ weitere Informationen zu den gemeinsam von einem <Slot-Server> zu
+ erfragenden Status gesammelt, deren Ids dort in die Ranges eines
+ <SfxItemSet>s aufgenommen werden.
+
+ Diese Informationen werden w"ahrend der Suche nach den zusammen
+ upzudatenden Ids sowieso als Zwischenergebnis ermittelt und nachher
+ wieder ben"otigt, daher macht es Sinn, sie f"ur diesen kurzen Zeitraum
+ gleich aufzubewahren.
+*/
+
+{
+ sal_uInt16 nSlotId; // die Slot-Id
+ sal_uInt16 nWhichId; // falls verf"ugbar die Which-Id, sonst nSlotId
+ const SfxSlot* pSlot; // Pointer auf den <Master-Slot>
+ SfxStateCache* pCache; // Pointer auf den StatusCache, ggf. 0
+
+ SfxFoundCache_Impl():
+ nSlotId(0),
+ nWhichId(0),
+ pSlot(0),
+ pCache(0)
+ {}
+
+ SfxFoundCache_Impl(SfxFoundCache_Impl&r):
+ nSlotId(r.nSlotId),
+ nWhichId(r.nWhichId),
+ pSlot(r.pSlot),
+ pCache(r.pCache)
+ {}
+
+ SfxFoundCache_Impl(sal_uInt16 nS, sal_uInt16 nW, const SfxSlot *pS, SfxStateCache *pC ):
+ nSlotId(nS),
+ nWhichId(nW),
+ pSlot(pS),
+ pCache(pC)
+ {}
+
+ int operator<( const SfxFoundCache_Impl &r ) const
+ { return nWhichId < r.nWhichId; } const
+
+ int operator==( const SfxFoundCache_Impl &r )
+ { return nWhichId== r.nWhichId; }
+};
+
+//--------------------------------------------------------------------------
+
+SV_DECL_PTRARR_SORT_DEL(SfxFoundCacheArr_Impl, SfxFoundCache_Impl*, 16, 16 );
+SV_IMPL_OP_PTRARR_SORT(SfxFoundCacheArr_Impl, SfxFoundCache_Impl*);
+
+//==========================================================================
+
+SfxBindings::SfxBindings()
+
+/* [Beschreibung]
+
+ Konstruktor der Klasse SfxBindings. Genau eine Instanz wird automatisch
+ von der <SfxApplication> vor <SfxApplication::Init()> angelegt. Wird
+ eine Instanz ben"otigt, z.B. zum Invalidieren von Slots, sollte diese
+ "uber den zugeh"origen <SfxViewFrame> besorgt werden. Bestimmte
+ SfxViewFrame Subklassen (z.B. <SfxInPlaceFrame>) legen ihre eigene
+ Instanz der SfxBindings an.
+
+ <SfxControllerItem> Instanzen k"onnen erst angelegt werden, wenn
+ die zugeh"orige SfxBindings Instanz existiert.
+*/
+
+: pImp(new SfxBindings_Impl),
+ pDispatcher(0),
+ nRegLevel(1) // geht erst auf 0, wenn Dispatcher gesetzt
+{
+ pImp->nMsgPos = 0;
+ pImp->bAllMsgDirty = sal_True;
+ pImp->bMsgDirty = sal_True;
+ pImp->bAllDirty = sal_True;
+ pImp->ePopupAction = SFX_POPUP_DELETE;
+ pImp->nCachedFunc1 = 0;
+ pImp->nCachedFunc2 = 0;
+ pImp->bCtrlReleased = sal_False;
+ pImp->bFirstRound = sal_False;
+ pImp->bInNextJob = sal_False;
+ pImp->bInUpdate = sal_False;
+// pImp->bInExecute = sal_False;
+ pImp->pSubBindings = NULL;
+ pImp->pSuperBindings = NULL;
+ pImp->pWorkWin = NULL;
+ pImp->pUnoCtrlArr = NULL;
+ pImp->nOwnRegLevel = nRegLevel;
+
+ // all caches are valid (no pending invalidate-job)
+ // create the list of caches
+ pImp->pCaches = new SfxStateCacheArr_Impl;
+ pImp->aTimer.SetTimeoutHdl( LINK(this, SfxBindings, NextJob_Impl) );
+ pImp->pInterceptors = 0;
+}
+
+//====================================================================
+
+SfxBindings::~SfxBindings()
+
+/* [Beschreibung]
+
+ Destruktor der Klasse SfxBindings. Die eine, f"ur jede <SfxApplication>
+ existierende Instanz wird von der <SfxApplication> nach Ausf"urhung
+ von <SfxApplication::Exit()> automatisch zerst"ort.
+
+ Noch existierende <SfxControllerItem> Instanzen, die bei dieser
+ SfxBindings Instanz angemeldet sind, werden im Destruktor
+ automatisch zerst"ort. Dies sind i.d.R. Floating-Toolboxen, Value-Sets
+ etc. Arrays von SfxControllerItems d"urfen zu diesem Zeitpunkt nicht
+ mehr exisitieren.
+*/
+
+{
+ // Die SubBindings sollen ja nicht gelocked werden !
+ pImp->pSubBindings = NULL;
+
+ ENTERREGISTRATIONS();
+
+ pImp->aTimer.Stop();
+ DeleteControllers_Impl();
+
+ // Caches selbst l"oschen
+ sal_uInt16 nCount = pImp->pCaches->Count();
+ for ( sal_uInt16 nCache = 0; nCache < nCount; ++nCache )
+ delete pImp->pCaches->GetObject(nCache);
+
+ delete pImp->pCaches;
+ delete pImp;
+}
+
+//--------------------------------------------------------------------
+
+void SfxBindings::DeleteControllers_Impl()
+
+/* [Beschreibung]
+
+ Interne Methode zum l"oschen noch existierender <SfxControllerItem>
+ Instanzen, die bei dieser SfxBindings Instanz angemeldet sind.
+
+ Dies sind i.d.R. <SfxPopupWindow>s. Nich sich selbst geh"orende
+ SfxControllerItems d"urfen bei Aufruf nur noch existieren, wenn sie
+ einem der restlichen SfxPopupWindows geh"oren.
+
+
+ [Anmerkung]
+
+ Wird beim Beenden der Applikation gerufen, bevor das Applikations-
+ Fenster gel"oscht wird.
+*/
+
+{
+ // in der ersten Runde den SfxPopupWindows l"oschen
+ sal_uInt16 nCount = pImp->pCaches->Count();
+ sal_uInt16 nCache;
+ for ( nCache = 0; nCache < nCount; ++nCache )
+ {
+ // merken wo man ist
+ SfxStateCache *pCache = pImp->pCaches->GetObject(nCache);
+ sal_uInt16 nSlotId = pCache->GetId();
+
+ // SfxPopupWindow l"oschen lassen
+ pCache->DeleteFloatingWindows();
+
+ // da der Cache verkleinert worden sein kann, wiederaufsetzen
+ sal_uInt16 nNewCount = pImp->pCaches->Count();
+ if ( nNewCount < nCount )
+ {
+ nCache = GetSlotPos(nSlotId);
+ if ( nCache >= nNewCount ||
+ nSlotId != pImp->pCaches->GetObject(nCache)->GetId() )
+ --nCache;
+ nCount = nNewCount;
+ }
+ }
+
+ // alle Caches l"oschen
+ for ( nCache = pImp->pCaches->Count(); nCache > 0; --nCache )
+ {
+ // Cache via ::com::sun::star::sdbcx::Index besorgen
+ SfxStateCache *pCache = pImp->pCaches->GetObject(nCache-1);
+
+ // alle Controller in dem Cache unbinden
+ SfxControllerItem *pNext;
+ for ( SfxControllerItem *pCtrl = pCache->GetItemLink();
+ pCtrl; pCtrl = pNext )
+ {
+ pNext = pCtrl->GetItemLink();
+ pCtrl->UnBind();
+ }
+
+ // Cache l"oschen
+ if( nCache-1 < pImp->pCaches->Count() )
+ delete (*pImp->pCaches)[nCache-1];
+ pImp->pCaches->Remove(nCache-1, 1);
+ }
+
+ if( pImp->pUnoCtrlArr )
+ {
+ sal_uInt16 nCount = pImp->pUnoCtrlArr->Count();
+ for ( sal_uInt16 n=nCount; n>0; n-- )
+ {
+ SfxUnoControllerItem *pCtrl = (*pImp->pUnoCtrlArr)[n-1];
+ pCtrl->ReleaseBindings();
+ }
+
+ DBG_ASSERT( !pImp->pUnoCtrlArr->Count(), "UnoControllerItems nicht entfernt!" );
+ DELETEZ( pImp->pUnoCtrlArr );
+ }
+}
+
+//--------------------------------------------------------------------
+
+SfxPopupAction SfxBindings::GetPopupAction_Impl() const
+{
+ return pImp->ePopupAction;
+}
+
+
+//--------------------------------------------------------------------
+
+void SfxBindings::HidePopups( FASTBOOL bHide )
+
+/* [Beschreibung]
+
+ Dieser Methode versteckt und zeigt die <SfxPopupWindows>, die aus
+ <SfxToolboxControl>s dieser SfxBindings-Instanz abgerissen wurden bzw.
+ floating <SfxChildWindow>-Instanzen dieser SfxBindings-Instanz.
+
+
+ [Anmerkung]
+
+ Es k"onnten noch weitere Floating-Windows exisitieren, die durch
+ diese Methode nicht erfa\st werden.
+*/
+
+{
+ // SfxPopupWindows hiden
+ HidePopupCtrls_Impl( bHide );
+ SfxBindings *pSub = pImp->pSubBindings;
+ while ( pSub )
+ {
+ pImp->pSubBindings->HidePopupCtrls_Impl( bHide );
+ pSub = pSub->pImp->pSubBindings;
+ }
+
+ // SfxChildWindows hiden
+ DBG_ASSERT( pDispatcher, "HidePopups not allowed without dispatcher" );
+ if ( pImp->pWorkWin )
+ pImp->pWorkWin->HidePopups_Impl( bHide, sal_True );
+}
+
+void SfxBindings::HidePopupCtrls_Impl( FASTBOOL bHide )
+{
+ if ( bHide )
+ {
+ // SfxPopupWindows hiden
+ pImp->ePopupAction = SFX_POPUP_HIDE;
+ }
+ else
+ {
+ // SfxPopupWindows showen
+ pImp->ePopupAction = SFX_POPUP_SHOW;
+ }
+
+ for ( sal_uInt16 nCache = 0; nCache < pImp->pCaches->Count(); ++nCache )
+ pImp->pCaches->GetObject(nCache)->DeleteFloatingWindows();
+ pImp->ePopupAction = SFX_POPUP_DELETE;
+}
+
+//--------------------------------------------------------------------
+
+void SfxBindings::Update_Impl
+(
+ SfxStateCache* pCache // der upzudatende SfxStatusCache
+)
+
+/* [Beschreibung]
+
+ Interne Methode zum Updaten eines Caches und den von derselben
+ Status-Methode in derselben Shell bedienten und dirty Slots.
+*/
+
+{
+ if( pCache->GetDispatch().is() && pCache->GetItemLink() )
+ {
+ pCache->SetCachedState();
+ return;
+ }
+
+ if ( !pDispatcher )
+ return;
+ DBG_PROFSTART(SfxBindingsUpdate_Impl);
+
+ // alle mit derselben Statusmethode zusammensammeln, die dirty sind
+ SfxDispatcher &rDispat = *pDispatcher;
+ const SfxSlot *pRealSlot = 0;
+ const SfxSlotServer* pMsgServer = 0;
+ SfxFoundCacheArr_Impl aFound;
+ SfxItemSet *pSet = CreateSet_Impl( pCache, pRealSlot, &pMsgServer, aFound );
+ sal_Bool bUpdated = sal_False;
+ if ( pSet )
+ {
+ // Status erfragen
+ if ( rDispat._FillState( *pMsgServer, *pSet, pRealSlot ) )
+ {
+ // Status posten
+ const SfxInterface *pInterface =
+ rDispat.GetShell(pMsgServer->GetShellLevel())->GetInterface();
+ for ( sal_uInt16 nPos = 0; nPos < aFound.Count(); ++nPos )
+ {
+ const SfxFoundCache_Impl *pFound = aFound[nPos];
+ sal_uInt16 nWhich = pFound->nWhichId;
+ const SfxPoolItem *pItem = 0;
+ SfxItemState eState = pSet->GetItemState(nWhich, sal_True, &pItem);
+ if ( eState == SFX_ITEM_DEFAULT && SfxItemPool::IsWhich(nWhich) )
+ pItem = &pSet->Get(nWhich);
+ UpdateControllers_Impl( pInterface, aFound[nPos], pItem, eState );
+ }
+ bUpdated = sal_True;
+ }
+
+ delete pSet;
+ }
+
+ if ( !bUpdated && pCache )
+ {
+ // Wenn pCache == NULL und kein SlotServer ( z.B. weil Dispatcher gelockt! ),
+ // darf nat"urlich kein Update versucht werden
+ SfxFoundCache_Impl aFound( pCache->GetId(), 0,
+ pRealSlot, pCache );
+ UpdateControllers_Impl( 0, &aFound, 0, SFX_ITEM_DISABLED);
+ }
+
+ DBG_PROFSTOP(SfxBindingsUpdate_Impl);
+}
+
+//--------------------------------------------------------------------
+
+void SfxBindings::Update
+(
+ sal_uInt16 nId // die gebundene und upzudatende Slot-Id
+)
+
+/* [Beschreibung]
+
+ Diese Methode sorgt f"ur synchrones Updaten der auf die Slot-Id nId
+ gebundenen <SfxContollerItem> Instanzen, die an dieser SfxBindings
+ Instanz angemeldet sind. Vergleichbar zu Window::Update()
+ (StarView) erfolgt ein Update nur, wenn entweder ein auf diese
+ Slot-Id gebundenes SfxContollerItem dirty ist, oder die Slot-Id
+ selbst dirty ist. Dies kann durch einen vorhergehendes Aufruf von
+ <SfxBindings::Invalidate(sal_uInt16)> erzwungen werden.
+
+
+ [Anmerkung]
+
+ Es ist g"unstiger, zun"achst alle zu invalidierenden Slot-Ids per
+ <SfxBindings::Invalidate(sal_uInt16)> zu invalidieren und dann
+ Update() aufzurufen, als einzelne abwechselnde Invalidate/Update,
+ da von derselben Status-Methode bediente Status-Anfragen von
+ den SfxBindings automatisch zusammengefa"st werden.
+
+
+ [Querverweise]
+
+ <SfxShell::Invalidate(sal_uInt16)>
+ <SfxBindings::Invalidate(sal_uInt16)>
+ <SfxBindings::InvalidateAll(sal_Bool)>
+ <SfxBindings::Update()>
+*/
+
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
+
+//!!TLX: Fuehrte zu Vorlagenkatalogstillstand
+// if ( nRegLevel )
+// return;
+
+ if ( pDispatcher )
+ pDispatcher->Flush();
+
+ if ( pImp->pSubBindings )
+ pImp->pSubBindings->Update( nId );
+
+ SfxStateCache* pCache = GetStateCache( nId );
+ if ( pCache )
+ {
+ pImp->bInUpdate = sal_True;
+ if ( pImp->bMsgDirty )
+ {
+ UpdateSlotServer_Impl();
+ pCache = GetStateCache( nId );
+ }
+
+ if (pCache)
+ {
+ if( pCache->GetDispatch().is() && pCache->GetItemLink() )
+ {
+ pCache->SetCachedState();
+ }
+ else
+ {
+ // Status erfragen
+ const SfxSlotServer* pMsgServer =
+ pCache->GetSlotServer(*pDispatcher, pImp->xProv);
+ if ( !pCache->IsControllerDirty() &&
+ ( !pMsgServer ||
+ !pMsgServer->GetSlot()->IsMode(SFX_SLOT_VOLATILE) ) )
+ {
+ pImp->bInUpdate = sal_False;
+ return;
+ }
+ if (!pMsgServer)
+ {
+ pCache->SetState(SFX_ITEM_DISABLED, 0);
+ pImp->bInUpdate = sal_False;
+ return;
+ }
+
+ Update_Impl(pCache);
+ }
+
+ pImp->bAllDirty = sal_False;
+ }
+
+ pImp->bInUpdate = sal_False;
+ }
+}
+
+//--------------------------------------------------------------------
+
+void SfxBindings::Update()
+
+/* [Beschreibung]
+
+ Diese Methode sorgt f"ur synchrones Updaten aller <SfxContollerItem>
+ Instanzen, die an dieser SfxBindings Instanz angemeldet sind. Vergleichbar
+ zu Window::Update() (StarView) erfolgt ein Update nur, wenn entweder ein
+ SfxContollerItem dirty ist, in einem Status-Cache der Zeiger auf den
+ <Slot-Server> dirty ist. Ersteres kann durch einen Aufruf von
+ <SfxBindings::Invalidate(sal_uInt16)> erzwungen werden, letzters durch
+ <SfxBindings::InvalidateAll(sal_Bool)>.
+
+
+ [Querverweise]
+
+ <SfxShell::Invalidate(sal_uInt16)>
+ <SfxBindings::Invalidate(sal_uInt16)>
+ <SfxBindings::InvalidateAll(sal_Bool)>
+ <SfxBindings::Update(sal_uInt16)>
+*/
+
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
+
+ if ( pImp->pSubBindings )
+ pImp->pSubBindings->Update();
+
+ if ( pDispatcher )
+ {
+ if ( nRegLevel )
+ return;
+
+ pImp->bInUpdate = sal_True;
+ pDispatcher->Flush();
+ pDispatcher->Update_Impl();
+ while ( !NextJob_Impl(0) )
+ ; // loop
+ pImp->bInUpdate = sal_False;
+ }
+}
+
+//--------------------------------------------------------------------
+
+void SfxBindings::SetState
+(
+ const SfxItemSet& rSet // zu setzende Status-Werte
+)
+
+/* [Beschreibung]
+
+ Diese Methode erlaubt das direkte Setzen neuer Status-Werte, ohne
+ den Umweg "uber <SfxBindings::Invalidate()> und das dann im Update
+ erfolgende Rufen der Status-Methoden an den <SfxShell>s.
+
+
+ [Querverweise]
+
+ <SfxBindings::SetState(const SfxPoolItem&)>
+*/
+
+{
+ // wenn gelockt, dann nur invalidieren
+ if ( nRegLevel )
+ {
+ SfxItemIter aIter(rSet);
+ for ( const SfxPoolItem *pItem = aIter.FirstItem();
+ pItem;
+ pItem = aIter.NextItem() )
+ Invalidate( pItem->Which() );
+ }
+ else
+ {
+ // Status d"urfen nur angenommen werden, wenn alle Slot-Pointer gesetzt sind
+ if ( pImp->bMsgDirty )
+ UpdateSlotServer_Impl();
+
+ // "uber das ItemSet iterieren, falls Slot gebunden, updaten
+ //! Bug: WhichIter verwenden und ggf. VoidItems hochschicken
+ SfxItemIter aIter(rSet);
+ for ( const SfxPoolItem *pItem = aIter.FirstItem();
+ pItem;
+ pItem = aIter.NextItem() )
+ {
+ SfxStateCache* pCache =
+ GetStateCache( rSet.GetPool()->GetSlotId(pItem->Which()) );
+ if ( pCache )
+ {
+ // Status updaten
+ if ( !pCache->IsControllerDirty() )
+ pCache->Invalidate(sal_False);
+ pCache->SetState( SFX_ITEM_AVAILABLE, pItem );
+
+ //! nicht implementiert: Updates von EnumSlots via MasterSlots
+ }
+ }
+ }
+}
+
+//--------------------------------------------------------------------
+
+void SfxBindings::SetState
+(
+ const SfxPoolItem& rItem // zu setzender Status-Wert
+)
+
+/* [Beschreibung]
+
+ Diese Methode erlaubt das direkte Setzen eines neuen Status-Wertes,
+ ohne den Umweg "uber <SfxBindings::Invalidate()> und das dann im Update
+ erfolgende Rufen der Status-Methoden an den <SfxShell>s.
+
+ Mit dieser Methode k"onnen nur <SfxPoolItem>s mit Slot, nicht
+ aber mit Which-Id gesetzt werden, da kein <SfxItemPool> bekannt ist,
+ "uber den gemappt werden k"onnte.
+
+
+ [Querverweise]
+
+ <SfxBindings::SetState(const SfxItemSet&)>
+*/
+
+{
+ if ( nRegLevel )
+ {
+ Invalidate( rItem.Which() );
+ }
+ else
+ {
+ // Status d"urfen nur angenommen werden, wenn alle Slot-Pointer gesetzt sind
+ if ( pImp->bMsgDirty )
+ UpdateSlotServer_Impl();
+
+ // falls der Slot gebunden ist, updaten
+ DBG_ASSERT( SfxItemPool::IsSlot( rItem.Which() ),
+ "cannot set items with which-id" );
+ SfxStateCache* pCache = GetStateCache( rItem.Which() );
+ if ( pCache )
+ {
+ // Status updaten
+ if ( !pCache->IsControllerDirty() )
+ pCache->Invalidate(sal_False);
+ pCache->SetState( SFX_ITEM_AVAILABLE, &rItem );
+
+ //! nicht implementiert: Updates von EnumSlots via MasterSlots
+ }
+ }
+}
+
+
+//--------------------------------------------------------------------
+
+SfxStateCache* SfxBindings::GetAnyStateCache_Impl( sal_uInt16 nId )
+{
+ SfxStateCache* pCache = GetStateCache( nId );
+ if ( !pCache && pImp->pSubBindings )
+ return pImp->pSubBindings->GetAnyStateCache_Impl( nId );
+ return pCache;
+}
+
+SfxStateCache* SfxBindings::GetStateCache
+(
+ sal_uInt16 nId /* Slot-Id, deren SfxStatusCache gefunden
+ werden soll */,
+ sal_uInt16* pPos /* 0 bzw. Position, ab der die Bindings
+ bin"ar durchsucht werden sollen. Liefert
+ die Position zur"uck, an der nId gefunden
+ wurde, bzw. an der es einfef"ugt werden
+ w"urde. */
+)
+
+/* [Beschreibung]
+
+ Diese Methode sucht die zu einer Slot-Id geh"orige <SfxStatusCache>
+ Instanz. Falls die Slot-Id in keinem Controller gebunden ist, wird
+ ein 0-Pointer zur"uckgegeben.
+
+ Falls pPos != 0, wird erst ab der Position mit der Suche angefangen.
+ Dieses ist eine Optimierung, f"ur den Fall, da"s die kleineren
+ Ids bereits abgearbeitet wurden.
+
+ In *pPos wird der ::com::sun::star::sdbcx::Index innerhalb der SfxBindings zur"uckgegeben,
+ unter dem dieser Cache z.Zt. abgelegt ist. Dieser ::com::sun::star::sdbcx::Index ist bis zum
+ n"achsten Aufruf von <SfxBindings::EnterRegistrations()> g"ultig.
+ W"ahrend der Umkonfiguration (<SfxBindings::IsInRegistrations()> == sal_True)
+ kann ist der ::com::sun::star::sdbcx::Index und der R"uckgabewert nur sehr kurzfristig
+ g"ultig.
+*/
+
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
+ // is the specified function bound?
+ const sal_uInt16 nStart = ( pPos ? *pPos : 0 );
+ const sal_uInt16 nPos = GetSlotPos( nId, nStart );
+
+ if ( nPos < pImp->pCaches->Count() &&
+ (*pImp->pCaches)[nPos]->GetId() == nId )
+ {
+ if ( pPos )
+ *pPos = nPos;
+ return (*pImp->pCaches)[nPos];
+ }
+ return 0;
+}
+
+//--------------------------------------------------------------------
+
+void SfxBindings::InvalidateAll
+(
+ sal_Bool bWithMsg /* sal_True
+ Slot-Server als ung"ultig markieren
+
+ sal_False
+ Slot-Server bleiben g"ultig */
+)
+
+/* [Beschreibung]
+
+ Invalidiert alle <SfxControllerItem> Instanzen, die an dieser
+ SfxBindings Instanz angemeldet sind, und bei bWithMsg == sal_True
+ ebenfalls die <Slot-Server>-Caches.
+
+ Es wird daraufhin ein Timer gestartet, bei dessen Ablauf das Updaten
+ beginnt. Somit k"onnen mehrere Invalidierungen vorgenommen werden,
+ bevor "uberhaupt etwas passiert.
+
+
+ [Querverweise]
+
+ <SfxShell::Invalidate(sal_uInt16)>
+ <SfxBindings::Invalidate(sal_uInt16)>
+ <SfxBindings::Invalidate(sal_uInt16*)>
+ <SfxBindings::Update()>
+ <SfxBindings::Update(sal_uInt16)>
+*/
+
+{
+ DBG_PROFSTART(SfxBindingsInvalidateAll);
+ DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
+
+ DBG_MEMTEST();
+
+ if ( pImp->pSubBindings )
+ pImp->pSubBindings->InvalidateAll( bWithMsg );
+
+ // ist schon alles dirty gesetzt oder downing => nicht zu tun
+ if ( !pDispatcher ||
+ ( pImp->bAllDirty && ( !bWithMsg || pImp->bAllMsgDirty ) ) ||
+ SFX_APP()->IsDowning() )
+ {
+ DBG_PROFSTOP(SfxBindingsInvalidateAll);
+ return;
+ }
+
+ pImp->bAllMsgDirty = pImp->bAllMsgDirty || bWithMsg;
+ pImp->bMsgDirty = pImp->bMsgDirty || pImp->bAllMsgDirty || bWithMsg;
+ pImp->bAllDirty = sal_True;
+
+ for ( sal_uInt16 n = 0; n < pImp->pCaches->Count(); ++n )
+ pImp->pCaches->GetObject(n)->Invalidate(bWithMsg);
+ pImp->nMsgPos = 0;
+ if ( !nRegLevel )
+ {
+ pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
+ pImp->aTimer.Start();
+// pImp->bFirstRound = sal_True;
+// pImp->nFirstShell = 0;
+ }
+
+ DBG_PROFSTOP(SfxBindingsInvalidateAll);
+}
+
+//--------------------------------------------------------------------
+
+void SfxBindings::Invalidate
+(
+ const sal_uInt16* pIds /* numerisch sortiertes 0-terminiertes Array
+ von Slot-Ids (einzel, nicht als Paare!) */
+)
+
+/* [Beschreibung]
+
+ Invalidiert die <SfxControllerItem> Instanzen der Slot-Ids in 'pIds',
+ die an dieser SfxBindings Instanz angemeldet sind.
+
+ Es wird daraufhin ein Timer gestartet, bei dessen Ablauf das Updaten
+ beginnt. Somit k"onnen mehrere Invalidierungen vorgenommen werden,
+ bevor "uberhaupt etwas passiert.
+
+
+ [Querverweise]
+
+ <SfxShell::Invalidate(sal_uInt16)>
+ <SfxBindings::Invalidate(sal_uInt16)>
+ <SfxBindings::InvalidateAll(sal_uInt16)>
+ <SfxBindings::Update()>
+ <SfxBindings::Update(sal_uInt16)>
+*/
+
+{
+ DBG_PROFSTART(SfxBindingsInvalidateAll);
+ DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
+
+ DBG_MEMTEST();
+
+ if ( pImp->pSubBindings )
+ pImp->pSubBindings->Invalidate( pIds );
+
+ // ist schon alles dirty gesetzt oder downing => nicht zu tun
+ if ( !pDispatcher || pImp->bAllDirty || SFX_APP()->IsDowning() )
+ return;
+
+ // in immer kleiner werdenden Berichen bin"ar suchen
+ for ( sal_uInt16 n = GetSlotPos(*pIds);
+ *pIds && n < pImp->pCaches->Count();
+ n = GetSlotPos(*pIds, n) )
+ {
+ // falls SID "uberhaupt gebunden ist, den Cache invalidieren
+ SfxStateCache *pCache = pImp->pCaches->GetObject(n);
+ if ( pCache->GetId() == *pIds )
+ pCache->Invalidate(sal_False);
+
+ // n"achste SID
+ if ( !*++pIds )
+ break;
+ DBG_ASSERT( *pIds > *(pIds-1), "pIds unsorted" );
+ }
+
+ // falls nicht gelockt, Update-Timer starten
+ pImp->nMsgPos = 0;
+ if ( !nRegLevel )
+ {
+ pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
+ pImp->aTimer.Start();
+// pImp->bFirstRound = sal_True;
+// pImp->nFirstShell = 0;
+ }
+
+ DBG_PROFSTOP(SfxBindingsInvalidateAll);
+}
+
+//--------------------------------------------------------------------
+
+void SfxBindings::InvalidateShell
+(
+ const SfxShell& rSh /* Die <SfxShell>, deren Slot-Ids
+ invalidiert werden sollen. */,
+
+ sal_Bool bDeep /* sal_True
+ auch die, von der SfxShell
+ ererbten Slot-Ids werden invalidert
+
+ sal_False
+ die ererbten und nicht "uberladenen
+ Slot-Ids werden invalidiert */
+ //! MI: z. Zt. immer bDeep
+)
+
+/* [Beschreibung]
+
+ Invalidiert alle <SfxControllerItem> Instanzen, die zur Zeit von
+ der angegebenen SfxShell Instanz bedient werden und an dieser
+ SfxBindings Instanz angemeldet sind
+
+ Es wird daraufhin ein Timer gestartet, bei dessen Ablauf das Updaten
+ beginnt. Somit k"onnen mehrere Invalidierungen vorgenommen werden,
+ bevor "uberhaupt etwas passiert.
+
+
+ [Querverweise]
+
+ <SfxShell::Invalidate(sal_uInt16)>
+ <SfxBindings::Invalidate(sal_uInt16)>
+ <SfxBindings::Update()>
+ <SfxBindings::Update(sal_uInt16)>
+*/
+
+{
+ DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
+
+ if ( pImp->pSubBindings )
+ pImp->pSubBindings->InvalidateShell( rSh, bDeep );
+
+ if ( !pDispatcher || pImp->bAllDirty || SFX_APP()->IsDowning() )
+ return;
+
+ DBG_PROFSTART(SfxBindingsInvalidateAll);
+ DBG_MEMTEST();
+
+ // Jetzt schon flushen, wird in GetShellLevel(rSh) sowieso gemacht; wichtig,
+ // damit pImp->bAll(Msg)Dirty korrekt gesetzt ist
+ pDispatcher->Flush();
+
+ if ( !pDispatcher ||
+ ( pImp->bAllDirty && pImp->bAllMsgDirty ) ||
+ SFX_APP()->IsDowning() )
+ {
+ // Wenn sowieso demn"achst alle Server geholt werden
+ return;
+ }
+
+ // Level finden
+ sal_uInt16 nLevel = pDispatcher->GetShellLevel(rSh);
+ if ( nLevel != USHRT_MAX )
+ {
+ for ( sal_uInt16 n = 0; n < pImp->pCaches->Count(); ++n )
+ {
+ SfxStateCache *pCache = pImp->pCaches->GetObject(n);
+ const SfxSlotServer *pMsgServer =
+ pCache->GetSlotServer(*pDispatcher, pImp->xProv);
+ if ( pMsgServer && pMsgServer->GetShellLevel() == nLevel )
+ pCache->Invalidate(sal_False);
+ }
+ pImp->nMsgPos = 0;
+ if ( !nRegLevel )
+ {
+ pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
+ pImp->aTimer.Start();
+ pImp->bFirstRound = sal_True;
+ pImp->nFirstShell = nLevel;
+ }
+ }
+
+ DBG_PROFSTOP(SfxBindingsInvalidateAll);
+}
+
+//--------------------------------------------------------------------
+
+void SfxBindings::Invalidate
+(
+ sal_uInt16 nId // zu invalidierende Slot-Id
+)
+
+/* [Beschreibung]
+
+ Invalidiert alle <SfxControllerItem> Instanzen, die auf die Slot-Id
+ nId gebunden sind und an dieser SfxBindings Instanz angemeldet sind.
+
+ Es wird daraufhin ein Timer gestartet, bei dessen Ablauf das Updaten
+ beginnt. Somit k"onnen mehrere Invalidierungen vorgenommen werden,
+ bevor "uberhaupt etwas passiert.
+
+
+ [Querverweise]
+ <SfxBindings::Invalidate(sal_uInt16*)>
+ <SfxBindings::InvalidateAll(sal_Bool)>
+ <SfxBindings::Update()>
+ <SfxBindings::Update(sal_uInt16)>
+*/
+
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
+
+ if ( pImp->pSubBindings )
+ pImp->pSubBindings->Invalidate( nId );
+
+ if ( !pDispatcher || pImp->bAllDirty || SFX_APP()->IsDowning() )
+ return;
+
+ SfxStateCache* pCache = GetStateCache(nId);
+ if ( pCache )
+ {
+ pCache->Invalidate(sal_False);
+ pImp->nMsgPos = Min(GetSlotPos(nId), pImp->nMsgPos);
+ if ( !nRegLevel )
+ {
+ pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
+ pImp->aTimer.Start();
+ }
+ }
+}
+
+//--------------------------------------------------------------------
+
+void SfxBindings::Invalidate
+(
+ sal_uInt16 nId, // zu invalidierende Slot-Id
+ sal_Bool bWithItem, // StateCache clearen ?
+ sal_Bool bWithMsg // SlotServer neu holen ?
+)
+
+/* [Beschreibung]
+
+ Invalidiert alle <SfxControllerItem> Instanzen, die auf die Slot-Id
+ nId gebunden sind und an dieser SfxBindings Instanz angemeldet sind,
+ und bei bWithMsg == sal_True ebenfalls den <Slot-Server>-Cache.
+
+ Es wird daraufhin ein Timer gestartet, bei dessen Ablauf das Updaten
+ beginnt. Somit k"onnen mehrere Invalidierungen vorgenommen werden,
+ bevor "uberhaupt etwas passiert.
+
+ [Querverweise]
+ <SfxBindings::Invalidate(sal_uInt16*)>
+ <SfxBindings::InvalidateAll(sal_Bool)>
+ <SfxBindings::Update()>
+ <SfxBindings::Update(sal_uInt16)>
+*/
+
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
+
+ if ( pImp->pSubBindings )
+ pImp->pSubBindings->Invalidate( nId, bWithItem, bWithMsg );
+
+ if ( SFX_APP()->IsDowning() )
+ return;
+
+ SfxStateCache* pCache = GetStateCache(nId);
+ if ( pCache )
+ {
+ if ( bWithItem )
+ pCache->ClearCache();
+ pCache->Invalidate(bWithMsg);
+
+ if ( !pDispatcher || pImp->bAllDirty )
+ return;
+
+ pImp->nMsgPos = Min(GetSlotPos(nId), pImp->nMsgPos);
+ if ( !nRegLevel )
+ {
+ pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
+ pImp->aTimer.Start();
+ }
+ }
+}
+
+void SfxBindings::Invalidate
+(
+ sal_uInt16 nId, // zu invalidierende Slot-Id
+ sal_Bool bWithMsg // SlotServer neu holen ?
+)
+
+/* [Beschreibung]
+
+ Invalidiert alle <SfxControllerItem> Instanzen, die auf die Slot-Id
+ nId gebunden sind und an dieser SfxBindings Instanz angemeldet sind,
+ und bei bWithMsg == sal_True ebenfalls den <Slot-Server>-Cache.
+
+ Es wird daraufhin ein Timer gestartet, bei dessen Ablauf das Updaten
+ beginnt. Somit k"onnen mehrere Invalidierungen vorgenommen werden,
+ bevor "uberhaupt etwas passiert.
+
+ [Querverweise]
+ <SfxBindings::Invalidate(sal_uInt16*)>
+ <SfxBindings::InvalidateAll(sal_Bool)>
+ <SfxBindings::Update()>
+ <SfxBindings::Update(sal_uInt16)>
+*/
+
+{
+ DBG_ERROR( "Methode veraltet!" );
+/*
+ DBG_MEMTEST();
+ DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
+ DBG_ASSERT( sal_False, "alte Methode aus Kompatibilitaetsgruenden gerettet (MH)");
+
+ if ( pImp->pSubBindings )
+ pImp->pSubBindings->Invalidate( nId, bWithMsg );
+
+ if ( !pDispatcher || pImp->bAllDirty || SFX_APP()->IsDowning() )
+ return;
+
+ SfxStateCache* pCache = GetStateCache(nId);
+ if ( pCache )
+ {
+ pCache->Invalidate(bWithMsg);
+ pImp->nMsgPos = Min(GetSlotPos(nId), pImp->nMsgPos);
+ if ( !nRegLevel )
+ {
+ pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
+ pImp->aTimer.Start();
+ }
+ }
+*/
+}
+
+//--------------------------------------------------------------------
+
+sal_Bool SfxBindings::IsBound( sal_uInt16 nSlotId, sal_uInt16 nStartSearchAt )
+
+/* [Beschreibung]
+
+ Stellt fest, ob die angegebene Slot-Id in einem <SfxControllerItem>
+ gebunden ist, der an dieser SfxBindings Instanz angemeldet ist.
+
+
+ [R"uckgabewert]
+
+ sal_Bool sal_True
+ Die angegeben Slot-Id ist gebunden.
+
+ sal_False
+ Die angegeben Slot-Id ist nicht gebunden.
+*/
+
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
+ return GetStateCache(nSlotId, &nStartSearchAt ) != 0;
+}
+
+//--------------------------------------------------------------------
+
+sal_uInt16 SfxBindings::GetSlotPos( sal_uInt16 nId, sal_uInt16 nStartSearchAt )
+
+/* [Beschreibung]
+
+ Ermittelt den ::com::sun::star::sdbcx::Index der angegebenen Slot-Id in den SfxBindings.
+ Falls die Slot-Id nicht gebunden ist, wird der ::com::sun::star::sdbcx::Index zur"uckgegeben,
+ an dem sie eingef"ugt w"urde.
+*/
+
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
+ DBG_PROFSTART(SfxBindingsMsgPos);
+
+ // answer immediately if a function-seek comes repeated
+ if ( pImp->nCachedFunc1 < pImp->pCaches->Count() &&
+ (*pImp->pCaches)[pImp->nCachedFunc1]->GetId() == nId )
+ {
+ ++nCache1;
+ DBG_PROFSTOP(SfxBindingsMsgPos);
+ return pImp->nCachedFunc1;
+ }
+ if ( pImp->nCachedFunc2 < pImp->pCaches->Count() &&
+ (*pImp->pCaches)[pImp->nCachedFunc2]->GetId() == nId )
+ {
+ ++nCache2;
+
+ // swap the caches
+ sal_uInt16 nTemp = pImp->nCachedFunc1;
+ pImp->nCachedFunc1 = pImp->nCachedFunc2;
+ pImp->nCachedFunc2 = nTemp;
+ DBG_PROFSTOP(SfxBindingsMsgPos);
+ return pImp->nCachedFunc1;
+ }
+
+ // binary search, if not found, seek to target-position
+ if ( pImp->pCaches->Count() <= nStartSearchAt )
+ {
+ DBG_PROFSTOP(SfxBindingsMsgPos);
+ return 0;
+ }
+ if ( pImp->pCaches->Count() == (nStartSearchAt+1) )
+ {
+ DBG_PROFSTOP(SfxBindingsMsgPos);
+ return (*pImp->pCaches)[nStartSearchAt]->GetId() >= nId ? 0 : 1;
+ }
+ size_t nLow = nStartSearchAt, nMid, nHigh = 0;
+ sal_Bool bFound = sal_False;
+ nHigh = pImp->pCaches->Count() - 1;
+ while ( !bFound && nLow <= nHigh )
+ {
+ nMid = (nLow + nHigh) >> 1;
+ DBG_ASSERT( nMid < pImp->pCaches->Count(), "bsearch ist buggy" );
+ int nDiff = (int) nId - (int) ( ((*pImp->pCaches)[nMid])->GetId() );
+ if ( nDiff < 0)
+ { if ( nMid == 0 )
+ break;
+ nHigh = nMid - 1;
+ }
+ else if ( nDiff > 0 )
+ { nLow = nMid + 1;
+ if ( nLow == 0 )
+ break;
+ }
+ else
+ bFound = sal_True;
+ }
+ sal_uInt16 nPos = bFound ? nMid : nLow;
+ DBG_ASSERT( nPos <= pImp->pCaches->Count(), "" );
+ DBG_ASSERT( nPos == pImp->pCaches->Count() ||
+ nId <= (*pImp->pCaches)[nPos]->GetId(), "" );
+ DBG_ASSERT( nPos == nStartSearchAt ||
+ nId > (*pImp->pCaches)[nPos-1]->GetId(), "" );
+ DBG_ASSERT( ( (nPos+1) >= pImp->pCaches->Count() ) ||
+ nId < (*pImp->pCaches)[nPos+1]->GetId(), "" );
+ pImp->nCachedFunc2 = pImp->nCachedFunc1;
+ pImp->nCachedFunc1 = nPos;
+ DBG_PROFSTOP(SfxBindingsMsgPos);
+ return nPos;
+}
+//--------------------------------------------------------------------
+
+void SfxBindings::Register( SfxControllerItem& rItem )
+
+/* [Beschreibung]
+
+ Mit dieser Methode melden sich Instanzen der Klasse <SfxControllerItem>
+ an der betreffenden SfxBindings Instanz an, wenn sie eine Slot-Id binden.
+
+
+ [Querverweise]
+ <SfxBindings::Release(SfxControllerItem&)>
+ <SfxBindings::EnterRegistrations()>
+ <SfxBindings::LeaveRegistrations()>
+*/
+
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( nRegLevel > 0, "registration without EnterRegistrations" );
+ DBG_ASSERT( !pImp->bInNextJob, "SfxBindings::Register while status-updating" );
+ //! EnterRegistrations();
+
+ // if not exist, insert a new cache
+ sal_uInt16 nId = rItem.GetId();
+ sal_uInt16 nPos = GetSlotPos(nId);
+ if ( nPos >= pImp->pCaches->Count() ||
+ (*pImp->pCaches)[nPos]->GetId() != nId )
+ {
+ SfxStateCache* pCache = new SfxStateCache(nId);
+ pImp->pCaches->Insert( nPos, pCache );
+ DBG_ASSERT( nPos == 0 ||
+ (*pImp->pCaches)[nPos]->GetId() >
+ (*pImp->pCaches)[nPos-1]->GetId(), "" );
+ DBG_ASSERT( (nPos == pImp->pCaches->Count()-1) ||
+ (*pImp->pCaches)[nPos]->GetId() <
+ (*pImp->pCaches)[nPos+1]->GetId(), "" );
+ pImp->bMsgDirty = sal_True;
+ }
+
+ // enqueue the new binding
+ SfxControllerItem *pOldItem = (*pImp->pCaches)[nPos]->ChangeItemLink(&rItem);
+ rItem.ChangeItemLink(pOldItem);
+
+ //! LeaveRegistrations();
+}
+//--------------------------------------------------------------------
+
+void SfxBindings::Release( SfxControllerItem& rItem )
+
+/* [Beschreibung]
+
+ Mit dieser Methode melden sich Instanzen der Klasse <SfxControllerItem>
+ an den SfxBindings ab.
+
+
+ [Querverweise]
+ <SfxBindings::Register(SfxControllerItem&)>
+ <SfxBindings::Release(SfxControllerItem&)>
+ <SfxBindings::EnterRegistrations()>
+ <SfxBindings::LeaveRegistrations()>
+*/
+
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
+ //! DBG_ASSERT( nRegLevel > 0, "release without EnterRegistrations" );
+ DBG_ASSERT( !pImp->bInNextJob, "SfxBindings::Release while status-updating" );
+ ENTERREGISTRATIONS();
+
+ // find the bound function
+ sal_uInt16 nId = rItem.GetId();
+ sal_uInt16 nPos = GetSlotPos(nId);
+ SfxStateCache* pCache = (*pImp->pCaches)[nPos];
+ if ( pCache->GetId() == nId )
+ {
+ // is this the first binding in the list?
+ SfxControllerItem* pItem = pCache->GetItemLink();
+ if ( pItem == &rItem )
+ pCache->ChangeItemLink( rItem.GetItemLink() );
+ else
+ {
+ // search the binding in the list
+ while ( pItem && pItem->GetItemLink() != &rItem )
+ pItem = pItem->GetItemLink();
+
+ // unlink it if it was found
+ if ( pItem )
+ pItem->ChangeItemLink( rItem.GetItemLink() );
+ }
+ // was this the last controller?
+ if ( pCache->GetItemLink() == 0 )
+ {
+#ifdef slow
+ // remove the BoundFunc
+ delete (*pImp->pCaches)[nPos];
+ pImp->pCaches->Remove(nPos, 1);
+#endif
+ if ( SfxMacroConfig::IsMacroSlot( nId ) )
+ {
+ delete (*pImp->pCaches)[nPos];
+ pImp->pCaches->Remove(nPos, 1);
+ }
+ else
+ pImp->bCtrlReleased = sal_True;
+ }
+ }
+
+ LEAVEREGISTRATIONS();
+}
+
+//--------------------------------------------------------------------
+#if SUPD<582
+sal_Bool SfxBindings::Execute( sal_uInt16 nId, const SfxPoolItem** ppItems, sal_uInt16 nModi )
+{
+ return Execute( nId, SFX_CALLMODE_SLOT, ppItems, nModi );
+}
+
+sal_Bool SfxBindings::Execute( sal_uInt16 nId, SfxCallMode nCallMode, const SfxPoolItem** ppItems, sal_uInt16 nModi, const SfxPoolItem **ppInternalArgs )
+#else
+sal_Bool SfxBindings::Execute( sal_uInt16 nId, const SfxPoolItem** ppItems, sal_uInt16 nModi, SfxCallMode nCallMode, const SfxPoolItem **ppInternalArgs )
+#endif
+/* [Beschreibung]
+
+ F"uhrt den Slot mit der Slot-Id nId "uber den <Slot-Server> Cache
+ aus. Dies ist nur bei in dieser SfxBindings INstanz gebundenen
+ Slot-Ids m"oglich.
+
+
+ [R"uckgabewert]
+
+ sal_Bool sal_True
+ Das Execute wurde ausgef"uhrt.
+
+ sal_False
+ Das Execute konnte nicht ausgef"uhrt werden,
+ weil der Slot entweder nicht zur Verf"ugung steht
+ (in keiner aktiven <SfxShell> vorhanden oder
+ disabled) ist oder der Anwender die Ausf"uhrung
+ abgebrochen hat (Cancel in einem Dialog).
+
+
+ [Querverweise]
+ <SfxDispatcher>
+*/
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
+
+ if( !nId || !pDispatcher )
+ return sal_False;
+
+ SfxStateCache *pCache = GetStateCache( nId );
+ if ( !pCache )
+ {
+ SfxBindings *pBind = pImp->pSubBindings;
+ while ( pBind )
+ {
+ if ( pBind->GetStateCache( nId ) )
+#if SUPD<582
+ return pBind->Execute( nId, nCallMode, ppItems, nModi, ppInternalArgs );
+#else
+ return pBind->Execute( nId, ppItems, nModi, nCallMode, ppInternalArgs );
+#endif
+ pBind = pBind->pImp->pSubBindings;
+ };
+ }
+
+ // synchronisieren
+ SfxDispatcher &rDispatcher = *pDispatcher;
+ rDispatcher.Flush();
+// pImp->bInExecute = sal_True;
+ SfxViewFrame *pFrame = rDispatcher.GetFrame();
+
+ // vom cache den Server (Slot+ShellLevel) und die Shell etc. abholen
+ sal_Bool bDeleteCache = sal_False;
+ if ( !pCache && pImp->xProv.is() )
+ {
+ pCache = new SfxStateCache( nId );
+ pCache->GetSlotServer( rDispatcher, pImp->xProv );
+ bDeleteCache = sal_True;
+ }
+
+ if ( pCache && pCache->GetDispatch().is() )
+ {
+ pCache->Dispatch( nCallMode == SFX_CALLMODE_SYNCHRON );
+ if ( bDeleteCache )
+ DELETEZ( pCache );
+ return sal_True;
+ }
+
+ // abgefangen?
+ if ( pImp->pInterceptors )
+ {
+ for ( sal_uInt16 n = 0; n < pImp->pInterceptors->Count(); ++n )
+ {
+ SfxSlotInterceptor *pInterceptor = pImp->pInterceptors->GetObject(n);
+ SfxPoolItem *pState = 0;
+ if ( SFX_ITEM_DISABLED != pInterceptor->QueryState(nId, pState) &&
+ pInterceptor->Execute(nId, (SfxPoolItem**) ppItems) )
+ {
+ delete pState;
+// pImp->bInExecute = sal_False;
+ return sal_True;
+ }
+ }
+ }
+
+ // Zur Sicherheit!
+ if ( pImp->bMsgDirty )
+ UpdateSlotServer_Impl();
+
+ // Neuerdings k"onnen wir auch nicht gecachete Slots executen
+ // ( wg. Acceleratoren, deren Controller aus Performance-Gr"unden nicht mehr
+ // gebunden werden ).
+ SfxShell *pShell=0;
+ const SfxSlot *pSlot=0;
+
+ const SfxSlotServer* pServer = pCache ? pCache->GetSlotServer( rDispatcher, pImp->xProv ) : 0;
+ if ( !pServer )
+ {
+ SfxSlotServer aServer;
+// if ( !rDispatcher._TryIntercept_Impl( nId, aServer, sal_False ) )
+ {
+ if ( !rDispatcher._FindServer( nId, aServer, sal_False ) )
+ {
+// pImp->bInExecute = sal_False;
+ if ( bDeleteCache )
+ delete pCache;
+ return sal_False;
+ }
+ }
+
+ pShell = rDispatcher.GetShell( aServer.GetShellLevel() );
+ pSlot = aServer.GetSlot();
+ }
+ else
+ {
+ pShell = rDispatcher.GetShell( pServer->GetShellLevel() );
+ pSlot = pServer->GetSlot();
+ }
+
+ SfxItemPool &rPool = pShell->GetPool();
+ SfxRequest aReq( nId, nCallMode, rPool );
+ aReq.SetModifier( nModi );
+ if( ppItems )
+ while( *ppItems )
+ aReq.AppendItem( **ppItems++ );
+ if ( ppInternalArgs )
+ {
+ SfxAllItemSet aSet( rPool );
+ for ( const SfxPoolItem **pArg = ppInternalArgs; *pArg; ++pArg )
+ aSet.Put( **pArg );
+ aReq.SetInternalArgs_Impl( aSet );
+ }
+
+/*
+ if ( pFrame && pFrame->IsVisible() )
+ {
+ // Bugfix #48745
+ // damit der Benutzer nicht verwirrt wird, wird bei Executes vom
+ // UI aus, die "Anderungen am Dokument vornehmen, der Focus auf das
+ // EditWindow gezogen, sofern der Frame sichtbar ist und der Focus
+ // nicht schon im Frame liegt
+ SfxViewFrame *pTop = pFrame->GetTopViewFrame();
+ SfxViewFrame *pAct = SfxViewFrame::Current()->GetTopViewFrame();
+ if ( !pSlot->IsMode( SFX_SLOT_READONLYDOC ) && pTop == pAct && !pFrame->GetWindow().HasChildPathFocus( sal_True ) )
+ pFrame->GetFrame()->GrabFocusOnComponent_Impl();
+ }
+*/
+ if ( SFX_KIND_ENUM == pSlot->GetKind() )
+ {
+ // bei Enum-Slots muss der Master mit dem Wert des Enums executet werden
+ const SfxSlot *pRealSlot = pShell->GetInterface()->GetRealSlot(pSlot);
+ const sal_uInt16 nSlotId = pRealSlot->GetSlotId();
+ aReq.SetSlot( nSlotId );
+ aReq.AppendItem( SfxAllEnumItem( rPool.GetWhich(nSlotId),
+ pSlot->GetValue() ) );
+ rDispatcher._Execute( *pShell, *pRealSlot, aReq, nCallMode | SFX_CALLMODE_RECORD );
+ }
+ else if ( SFX_KIND_ATTR == pSlot->GetKind() )
+ {
+ // bei Attr-Slots mu der Which-Wert gemapped werden
+ const sal_uInt16 nSlotId = pSlot->GetSlotId();
+ aReq.SetSlot( nSlotId );
+ if ( pSlot->IsMode(SFX_SLOT_TOGGLE) )
+ {
+ // an togglebare-Attribs (Bools) wird der Wert angeheangt
+ sal_uInt16 nWhich = pSlot->GetWhich(rPool);
+ SfxItemSet aSet(rPool, nWhich, nWhich, 0);
+ SfxStateFunc aFunc = pSlot->GetStateFnc();
+ pShell->CallState( aFunc, aSet );
+ const SfxPoolItem *pOldItem;
+ SfxItemState eState = aSet.GetItemState(nWhich, sal_True, &pOldItem);
+ if ( SFX_ITEM_SET == eState ||
+ ( SFX_ITEM_AVAILABLE == eState &&
+ SfxItemPool::IsWhich(nWhich) &&
+ ( pOldItem = &aSet.Get(nWhich) ) ) )
+ {
+ if ( pOldItem->ISA(SfxBoolItem) )
+ {
+ // wir koennen Bools toggeln
+ sal_Bool bOldValue = ((const SfxBoolItem *)pOldItem)->GetValue();
+ SfxBoolItem *pNewItem = (SfxBoolItem*) (pOldItem->Clone());
+ pNewItem->SetValue( !bOldValue );
+ aReq.AppendItem( *pNewItem );
+ delete pNewItem;
+ }
+ else if ( pOldItem->ISA(SfxEnumItemInterface) &&
+ ((SfxEnumItemInterface *)pOldItem)->HasBoolValue())
+ {
+ // und Enums mit Bool-Interface
+ SfxEnumItemInterface *pNewItem =
+ (SfxEnumItemInterface*) (pOldItem->Clone());
+ pNewItem->SetBoolValue(!((SfxEnumItemInterface *)pOldItem)->GetBoolValue());
+ aReq.AppendItem( *pNewItem );
+ delete pNewItem;
+ }
+ else
+ DBG_ERROR( "Toggle only for Enums and Bools allowed" );
+ }
+ else if ( SFX_ITEM_DONTCARE == eState )
+ {
+ // ein Status-Item per Factory erzeugen
+ SfxPoolItem *pNewItem = pSlot->GetType()->CreateItem();
+ DBG_ASSERT( pNewItem, "Toggle an Slot ohne ItemFactory" );
+ pNewItem->SetWhich( nWhich );
+
+ if ( pNewItem->ISA(SfxBoolItem) )
+ {
+ // wir koennen Bools toggeln
+ ((SfxBoolItem*)pNewItem)->SetValue( sal_True );
+ aReq.AppendItem( *pNewItem );
+ }
+ else if ( pNewItem->ISA(SfxEnumItemInterface) &&
+ ((SfxEnumItemInterface *)pNewItem)->HasBoolValue())
+ {
+ // und Enums mit Bool-Interface
+ ((SfxEnumItemInterface*)pNewItem)->SetBoolValue(sal_True);
+ aReq.AppendItem( *pNewItem );
+ }
+ else
+ DBG_ERROR( "Toggle only for Enums and Bools allowed" );
+ delete pNewItem;
+ }
+ else
+ DBG_ERROR( "suspicious Toggle-Slot" );
+ }
+ rDispatcher._Execute( *pShell, *pSlot, aReq, nCallMode | SFX_CALLMODE_RECORD );
+ }
+ else
+ rDispatcher._Execute( *pShell, *pSlot, aReq, nCallMode | SFX_CALLMODE_RECORD );
+
+// pImp->bInExecute = sal_False;
+ if ( bDeleteCache )
+ delete pCache;
+ return sal_True;
+}
+
+//--------------------------------------------------------------------
+
+void SfxBindings::UpdateSlotServer_Impl()
+
+/* [Beschreibung]
+
+ Interne Methode zum Updaten der Pointer auf die SlotServer
+ nach <SfxBindings::InvalidateAll(sal_Bool)>.
+*/
+
+{
+ DBG_PROFSTART(SfxBindingsUpdateServers);
+ DBG_MEMTEST();
+ DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
+
+ // synchronisieren
+ pDispatcher->Flush();
+// pDispatcher->Update_Impl();
+
+ const sal_uInt16 nCount = pImp->pCaches->Count();
+ for(sal_uInt16 i = 0; i < nCount; ++i)
+ {
+ SfxStateCache *pCache = pImp->pCaches->GetObject(i);
+ pCache->GetSlotServer(*pDispatcher, pImp->xProv);
+ }
+ pImp->bMsgDirty = pImp->bAllMsgDirty = sal_False;
+
+ Broadcast( SfxSimpleHint(SFX_HINT_DOCCHANGED) );
+
+ DBG_PROFSTOP(SfxBindingsUpdateServers);
+}
+
+//--------------------------------------------------------------------
+
+#ifdef WNT
+int __cdecl CmpUS_Impl(const void *p1, const void *p2)
+#else
+int CmpUS_Impl(const void *p1, const void *p2)
+#endif
+
+/* [Beschreibung]
+
+ Interne Vergleichsfunktion fuer qsort.
+*/
+
+{
+ return *(sal_uInt16 *)p1 - *(sal_uInt16 *)p2;
+}
+
+//--------------------------------------------------------------------
+
+SfxItemSet* SfxBindings::CreateSet_Impl
+(
+ SfxStateCache*& pCache, // in: Status-Cache von nId
+ const SfxSlot*& pRealSlot, // out: RealSlot zu nId
+ const SfxSlotServer** pMsgServer, // out: Slot-Server zu nId
+ SfxFoundCacheArr_Impl& rFound // out: Liste der Caches der Siblings
+)
+
+/* [Beschreibung]
+
+ Diese interne Methode sucht zu pCache die Slot-Ids, die von derselben
+ Status-Methode bedient werden und ebenfalls gebunden und dirty sind.
+ Es wird ein SfxItemSet zusammengestellt, das die Slot-Ids (oder falls
+ vorhanden die mit dem Pool der Shell gemappten Which-Ids) enth"alt.
+ Die Caches dieser Slots werden in pFoundCaches zur"uckgeliefert.
+*/
+
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
+
+ DBG_ASSERT( !pImp->bMsgDirty, "CreateSet_Impl mit dirty MessageServer" );
+
+ const SfxSlotServer* pMsgSvr = pCache->GetSlotServer(*pDispatcher, pImp->xProv);
+ if(!pMsgSvr || !pDispatcher)
+ return 0;
+
+ DBG_PROFSTART(SfxBindingsCreateSet);
+ pRealSlot = 0;
+ *pMsgServer = pMsgSvr;
+
+ sal_uInt16 nShellLevel = pMsgSvr->GetShellLevel();
+ SfxShell *pShell = pDispatcher->GetShell( nShellLevel );
+ if ( !pShell ) // seltener GPF beim Browsen durch Update aus Inet-Notify
+ return 0;
+
+ SfxItemPool &rPool = pShell->GetPool();
+
+ // hole die Status-Methode, von der pCache bedient wird
+ SfxStateFunc pFnc = 0;
+ const SfxInterface *pInterface = pShell->GetInterface();
+ if ( SFX_KIND_ENUM == pMsgSvr->GetSlot()->GetKind() )
+ {
+ pRealSlot = pInterface->GetRealSlot(pMsgSvr->GetSlot());
+ pCache = GetStateCache( pRealSlot->GetSlotId() );
+// DBG_ASSERT( pCache, "Kein Slotcache fuer den Masterslot gefunden!" );
+ }
+ else
+ pRealSlot = pMsgSvr->GetSlot();
+
+ //
+ // Achtung: pCache darf auch NULL sein !!!
+ //
+
+ pFnc = pRealSlot->GetStateFnc();
+
+ // der RealSlot ist immer drin
+ const SfxFoundCache_Impl *pFound = new SfxFoundCache_Impl(
+ pRealSlot->GetSlotId(), pRealSlot->GetWhich(rPool), pRealSlot, pCache );
+ rFound.Insert( pFound );
+
+ if ( !SfxMacroConfig::IsMacroSlot( pRealSlot->GetSlotId() ) )
+ {
+ pInterface->GetRealInterfaceForSlot( pRealSlot );
+ DBG_ASSERT (pInterface,"Slot in angegebener Shell nicht gefunden!");
+ }
+
+ // Durchsuche die Bindings nach den von derselben Funktion bedienten Slots.
+ // Daf"ur kommen nur Slots in Frage, die es im gefundenen Interface gibt.
+
+ // Die Position des Statecaches im StateCache-Array
+ sal_uInt16 nCachePos = pImp->nMsgPos;
+ const SfxSlot *pSibling = pRealSlot->GetNextSlot();
+
+ // Die Slots eines Interfaces sind im Kreis verkettet
+ while ( pSibling > pRealSlot )
+ {
+ SfxStateFunc pSiblingFnc=0;
+ SfxStateCache *pSiblingCache =
+ GetStateCache( pSibling->GetSlotId(), &nCachePos );
+
+ // Ist der Slot "uberhaupt gecached ?
+ if ( pSiblingCache )
+ {
+ const SfxSlotServer *pServ = pSiblingCache->GetSlotServer(*pDispatcher, pImp->xProv);
+ if ( pServ && pServ->GetShellLevel() == nShellLevel )
+ pSiblingFnc = pServ->GetSlot()->GetStateFnc();
+ }
+
+ // Mu\s der Slot "uberhaupt upgedatet werden ?
+ FASTBOOL bInsert = pSiblingCache && pSiblingCache->IsControllerDirty();
+
+ // Bugfix #26161#: Es reicht nicht, nach der selben Shell zu fragen !!
+ FASTBOOL bSameMethod = pSiblingCache && pFnc == pSiblingFnc;
+
+ // Wenn der Slot ein nicht-dirty MasterSlot ist, dann ist vielleicht
+ // einer seiner Slaves dirty ? Dann wird der Masterslot doch eingef"ugt.
+ if ( !bInsert && bSameMethod && pSibling->GetLinkedSlot() )
+ {
+ // auch Slave-Slots auf Binding pru"fen
+ const SfxSlot* pFirstSlave = pSibling->GetLinkedSlot();
+ for ( const SfxSlot *pSlaveSlot = pFirstSlave;
+ !bInsert;
+ pSlaveSlot = pSlaveSlot->GetNextSlot())
+ {
+ // Die Slaves zeigen auf ihren Master
+ DBG_ASSERT(pSlaveSlot->GetLinkedSlot() == pSibling,
+ "Falsche Master/Slave-Beziehung!");
+
+ sal_uInt16 nCurMsgPos = pImp->nMsgPos;
+ const SfxStateCache *pSlaveCache =
+ GetStateCache( pSlaveSlot->GetSlotId(), &nCurMsgPos );
+
+ // Ist der Slave-Slot gecached und dirty ?
+ bInsert = pSlaveCache && pSlaveCache->IsControllerDirty();
+
+ // Slaves sind untereinander im Kreis verkettet
+ if (pSlaveSlot->GetNextSlot() == pFirstSlave)
+ break;
+ }
+ }
+
+ if ( bInsert && bSameMethod )
+ {
+ const SfxFoundCache_Impl *pFound = new SfxFoundCache_Impl(
+ pSibling->GetSlotId(), pSibling->GetWhich(rPool),
+ pSibling, pSiblingCache );
+
+ rFound.Insert( pFound );
+ }
+
+ pSibling = pSibling->GetNextSlot();
+ }
+
+ // aus den Ranges ein Set erzeugen
+ sal_uInt16 *pRanges = new sal_uInt16[rFound.Count() * 2 + 1];
+ int j = 0;
+ int i = 0;
+ while ( i < rFound.Count() )
+ {
+ pRanges[j++] = rFound[i]->nWhichId;
+ // aufeinanderfolgende Zahlen
+ for ( ; i < rFound.Count()-1; ++i )
+ if ( rFound[i]->nWhichId+1 != rFound[i+1]->nWhichId )
+ break;
+ pRanges[j++] = rFound[i++]->nWhichId;
+ }
+ pRanges[j] = 0; // terminierende NULL
+ SfxItemSet *pSet = new SfxItemSet(rPool, pRanges);
+ delete pRanges;
+ DBG_PROFSTOP(SfxBindingsCreateSet);
+ return pSet;
+}
+
+//--------------------------------------------------------------------
+
+void SfxBindings::UpdateControllers_Impl
+(
+ const SfxInterface* pIF, // das diese Id momentan bedienende Interface
+ const SfxFoundCache_Impl* pFound, // Cache, Slot, Which etc.
+ const SfxPoolItem* pItem, // item to send to controller
+ SfxItemState eState // state of item
+)
+
+/* [Beschreibung]
+
+ Dieses ist eine Hilfsmethode f"ur NextJob_Impl mit der die SfxController,
+ welche auf nSlotId gebunden sind, upgedated werden. Dabei wird der
+ Wert aus dem SfxPoolItem unter dem Which-Wert nWhich aus dem Set rSet
+ genommen.
+
+ Falls zu rSlot Enum-Werte in der Slotmap eingetragen sind, und diese
+ gebunden sind, werden sie ebenfalls upgedated.
+*/
+
+{
+ DBG_ASSERT( !pFound->pSlot || SFX_KIND_ENUM != pFound->pSlot->GetKind(),
+ "direct update of enum slot isn't allowed" );
+ DBG_PROFSTART(SfxBindingsUpdateCtrl1);
+
+ SfxStateCache* pCache = pFound->pCache;
+ const SfxSlot* pSlot = pFound->pSlot;
+ DBG_ASSERT( !pCache || !pSlot || pCache->GetId() == pSlot->GetSlotId(), "SID mismatch" );
+
+ // insofern gebunden, die Controller f"uer den Slot selbst updaten
+ if ( pCache && pCache->IsControllerDirty() )
+ {
+ // Slot abgefangen?
+ sal_Bool bIntercepted = sal_False;
+ if ( pImp->pInterceptors )
+ {
+ for ( sal_uInt16 n = 0; n < pImp->pInterceptors->Count(); ++n )
+ {
+ SfxSlotInterceptor *pInterceptor = pImp->pInterceptors->GetObject(n);
+ SfxPoolItem *pState = 0;
+ sal_uInt16 nSID = pCache->GetId();
+ SfxItemState eState = pInterceptor->QueryState( nSID, pState );
+ if ( SFX_ITEM_UNKNOWN != eState )
+ {
+ bIntercepted = sal_True;
+ if ( eState == SFX_ITEM_AVAILABLE )
+ {
+ // Default
+ SfxVoidItem aVoid(nSID);
+ pCache->SetState( eState, &aVoid );
+ }
+ else
+ {
+ // Gesetzt
+ pCache->SetState(
+ eState == SFX_ITEM_SET ? SFX_ITEM_AVAILABLE : eState, pState );
+ delete pState;
+ }
+
+ return;
+ }
+ }
+ }
+
+ if ( !bIntercepted )
+ {
+ if ( SFX_ITEM_DONTCARE == eState )
+ {
+ // uneindeuting
+ pCache->SetState( SFX_ITEM_DONTCARE, (SfxPoolItem *)-1 );
+ }
+ else if ( SFX_ITEM_DEFAULT == eState &&
+ pFound->nWhichId > SFX_WHICH_MAX )
+ {
+ // kein Status oder Default aber ohne Pool
+ SfxVoidItem aVoid(0);
+ pCache->SetState( SFX_ITEM_UNKNOWN, &aVoid );
+ }
+ else if ( SFX_ITEM_DISABLED == eState )
+ pCache->SetState(SFX_ITEM_DISABLED, 0);
+ else
+ pCache->SetState(SFX_ITEM_AVAILABLE, pItem);
+ }
+ }
+
+ DBG_PROFSTOP(SfxBindingsUpdateCtrl1);
+
+ // insofern vorhanden und gebunden, die Controller f"uer Slave-Slots
+ // (Enum-Werte) des Slots updaten
+ DBG_PROFSTART(SfxBindingsUpdateCtrl2);
+ DBG_ASSERT( !pSlot || 0 == pSlot->GetLinkedSlot() || !pItem ||
+ pItem->ISA(SfxEnumItemInterface),
+ "master slot with non-enum-type found" );
+ const SfxSlot *pFirstSlave = pSlot ? pSlot->GetLinkedSlot() : 0;
+ if ( pIF && pFirstSlave)
+ {
+ // Items auf EnumItem casten
+ const SfxEnumItemInterface *pEnumItem =
+ PTR_CAST(SfxEnumItemInterface,pItem);
+ if ( eState == SFX_ITEM_AVAILABLE && !pEnumItem )
+ eState = SFX_ITEM_DONTCARE;
+ else
+ eState = SfxControllerItem::GetItemState( pEnumItem );
+
+ // "uber alle Slaves-Slots iterieren
+ for ( const SfxSlot *pSlave = pFirstSlave; pSlave;
+ pSlave = pSlave->GetNextSlot() )
+ {
+ DBG_ASSERT(pSlave, "Falsche SlaveSlot-Verkettung!");
+ DBG_ASSERT(SFX_KIND_ENUM == pSlave->GetKind(),"non enum slaves aren't allowed");
+ DBG_ASSERT(pSlave->GetMasterSlotId() == pSlot->GetSlotId(),"falscher MasterSlot!");
+
+ // ist die Funktion gebunden?
+ SfxStateCache *pEnumCache = GetStateCache( pSlave->GetSlotId() );
+ if ( pEnumCache )
+ {
+ pEnumCache->Invalidate(sal_False);
+
+ HACK(CONTROL/SELECT Kram)
+ if ( eState == SFX_ITEM_DONTCARE && pFound->nWhichId == 10144 )
+ {
+ SfxVoidItem aVoid(0);
+ pEnumCache->SetState( SFX_ITEM_UNKNOWN, &aVoid );
+
+ if (pSlave->GetNextSlot() == pFirstSlave)
+ break;
+
+ continue;
+ }
+
+ if ( SFX_ITEM_DISABLED == eState
+#ifdef OV_hat_das_SvxChooseControlItem_angepasst
+ || USHRT_MAX == pEnumItem->GetPosByValue(pEnumCache->GetValue())
+#endif
+ )
+ {
+ // disabled
+ pEnumCache->SetState(SFX_ITEM_DISABLED, 0);
+ }
+ else if ( SFX_ITEM_AVAILABLE == eState )
+ {
+ // enum-Wert ermitteln
+ sal_uInt16 nValue = pEnumItem->GetEnumValue();
+ SfxBoolItem aBool( pFound->nWhichId, pSlave->GetValue() == nValue );
+ pEnumCache->SetState(SFX_ITEM_AVAILABLE, &aBool);
+ }
+ else
+ {
+ // uneindeuting
+ pEnumCache->SetState( SFX_ITEM_DONTCARE, (SfxPoolItem *)-1 );
+ }
+ }
+
+ if (pSlave->GetNextSlot() == pFirstSlave)
+ break;
+ }
+ }
+
+ DBG_PROFSTOP(SfxBindingsUpdateCtrl2);
+}
+
+
+//--------------------------------------------------------------------
+
+IMPL_LINK( SfxBindings, NextJob_Impl, Timer *, pTimer )
+
+/* [Beschreibung]
+
+ Die SfxController werden "uber einen Timer updated. Dieses ist der
+ dazugeh"orige interne TimeOut-Handler.
+ */
+
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
+
+ DBG_PROFSTART(SfxBindingsNextJob_Impl0);
+ SfxApplication *pSfxApp = SFX_APP();
+
+ if( pDispatcher )
+ pDispatcher->Update_Impl();
+
+ // modifying the SfxObjectInterface-stack without SfxBindings => nothing to do
+ SfxViewFrame* pFrame = pDispatcher->GetFrame();
+ if ( pFrame && pFrame->GetObjectShell()->IsInModalMode() || pSfxApp->IsDowning() || !pImp->pCaches->Count() )
+ {
+ DBG_PROFSTOP(SfxBindingsNextJob_Impl0);
+ return sal_True;
+ }
+ if ( !pDispatcher || !pDispatcher->IsFlushed() )
+ {
+ DBG_PROFSTOP(SfxBindingsNextJob_Impl0);
+ return sal_True;
+ }
+
+ // gfs. alle Server aktualisieren / geschieht in eigener Zeitscheibe
+ if ( pImp->bMsgDirty )
+ {
+ UpdateSlotServer_Impl();
+ DBG_PROFSTOP(SfxBindingsNextJob_Impl0);
+ return sal_False;
+ }
+
+ DBG_PROFSTOP(SfxBindingsNextJob_Impl0);
+ DBG_PROFSTART(SfxBindingsNextJob_Impl);
+ pImp->bAllDirty = sal_False;
+ pImp->aTimer.SetTimeout(TIMEOUT_UPDATING);
+
+ // at least 10 loops and further if more jobs are available but no input
+ FASTBOOL bPreEmptive = pTimer && !pSfxApp->Get_Impl()->nInReschedule;
+ sal_uInt16 nLoops = 10;
+ pImp->bInNextJob = sal_True;
+ const sal_uInt16 nCount = pImp->pCaches->Count();
+ while ( pImp->nMsgPos < nCount )
+ {
+ // iterate through the bound functions
+ sal_Bool bJobDone = sal_False;
+ while ( !bJobDone )
+ {
+ SfxStateCache* pCache = (*pImp->pCaches)[pImp->nMsgPos];
+ DBG_ASSERT( pCache, "invalid SfxStateCache-position in job queue" );
+ sal_Bool bWasDirty = pCache->IsControllerDirty();
+ if ( bWasDirty )
+ {
+/*
+ sal_Bool bSkip = sal_False;
+ if ( pImp->bFirstRound )
+ {
+ // Falls beim Update eine Shell vorgezogen werden soll,
+ // kommt in einer ersten Update-Runde nur diese dran
+ const SfxSlotServer *pMsgServer =
+ pCache->GetSlotServer(*pDispatcher, pImp->xProv);
+ if ( pMsgServer &&
+ pMsgServer->GetShellLevel() != pImp->nFirstShell )
+ bSkip = sal_True;
+ }
+
+ if ( !bSkip )
+ {
+*/
+ Update_Impl( pCache );
+ DBG_ASSERT( nCount == pImp->pCaches->Count(),
+ "Reschedule in StateChanged => buff" );
+// }
+ }
+
+ // skip to next function binding
+ ++pImp->nMsgPos;
+
+ // keep job if it is not completed, but any input is available
+ bJobDone = pImp->nMsgPos >= nCount;
+ if ( bJobDone && pImp->bFirstRound )
+ {
+ // Update der bevorzugten Shell ist gelaufen, nun d"urfen
+ // auch die anderen
+ bJobDone = sal_False;
+ pImp->bFirstRound = sal_False;
+ pImp->nMsgPos = 0;
+ }
+
+ if ( bWasDirty && !bJobDone && bPreEmptive && (--nLoops == 0) )
+ {
+ DBG_PROFSTOP(SfxBindingsNextJob_Impl);
+ pImp->bInNextJob = sal_False;
+ return sal_False;
+ }
+ }
+ }
+
+ // volatiles wieder von vorne starten
+ pImp->nMsgPos = 0;
+ pImp->aTimer.SetTimeout(TIMEOUT_IDLE);
+ for ( sal_uInt16 n = 0; n < nCount; ++n )
+ {
+ SfxStateCache* pCache = (*pImp->pCaches)[n];
+ const SfxSlotServer *pSlotServer = pCache->GetSlotServer(*pDispatcher, pImp->xProv);
+ if ( pSlotServer &&
+ pSlotServer->GetSlot()->IsMode(SFX_SLOT_VOLATILE) )
+ pCache->Invalidate(sal_False);
+ }
+
+ // Update-Runde ist beendet
+ pImp->bInNextJob = sal_False;
+ Broadcast(SfxSimpleHint(SFX_HINT_UPDATEDONE));
+ DBG_PROFSTOP(SfxBindingsNextJob_Impl);
+ return sal_True;
+}
+
+//--------------------------------------------------------------------
+
+sal_uInt16 SfxBindings::EnterRegistrations(char *pFile, int nLine)
+
+/* [Beschreibung]
+
+ Die An- oder Abmeldung von <SfxControllerItem> Instanzen mu"s in
+ EnterRegistrations() und LeaveRegistrations() geklammert werden.
+ W"ahrend dieser Zeit erfolgen keine Udates der <SfxContollerItem>
+ Instanzen (weder der alten noch der neu angemeldeten).
+
+ [Parameter]
+
+ pFile, nLine Dateiname und Zeilennummer der rufenden
+ Methode (nur Debug)
+
+ [R"uckgabewert]
+
+ sal_uInt16 Level der Registrierung. Dieser kann in
+ <SfxBindings::LeaveRegistrations(sal_uInt16)> als
+ Parameter angegeben werden, um die Paarigkeit
+ der EnterRegistrations() und LeaveRegistrations()
+ zu pr"ufen.
+
+
+ [Querverweise]
+ <SfxBindings::IsInRegistrations()>
+ <SfxBindings::Register(SfxControllerItem&)>
+ <SfxBindings::Release(SfxControllerItem&)>
+ <SfxBindings::LeaveRegistrations()>
+*/
+
+{
+ DBG_MEMTEST();
+#ifdef DBG_UTIL
+ ByteString aMsg;
+ aMsg.Fill( Min(nRegLevel, sal_uInt16(8) ) );
+ aMsg += "this = ";
+ aMsg += ByteString::CreateFromInt32((long)this);
+ aMsg += " Level = ";
+ aMsg += ByteString::CreateFromInt32(nRegLevel);
+ aMsg += " SfxBindings::EnterRegistrations ";
+ if(pFile) {
+ aMsg += "File: ";
+ aMsg += pFile;
+ aMsg += " Line: ";
+ aMsg += ByteString::CreateFromInt32(nLine);
+ }
+ DbgTrace( aMsg.GetBuffer() );
+#endif
+
+ // Wenn Bindings gelockt werden, auch SubBindings locken
+ if ( pImp->pSubBindings )
+ {
+ pImp->pSubBindings->ENTERREGISTRATIONS();
+
+ // Dieses EnterRegistrations ist f"ur die SubBindings kein "echtes"
+ pImp->pSubBindings->pImp->nOwnRegLevel--;
+
+ // Bindings synchronisieren
+ pImp->pSubBindings->nRegLevel = nRegLevel + pImp->pSubBindings->pImp->nOwnRegLevel + 1;
+ }
+
+ pImp->nOwnRegLevel++;
+
+ // check if this is the outer most level
+ if ( ++nRegLevel == 1 )
+ {
+ // stop background-processing
+ pImp->aTimer.Stop();
+
+ // flush the cache
+ pImp->nCachedFunc1 = 0;
+ pImp->nCachedFunc2 = 0;
+
+ // merken, ob ganze Caches verschwunden sind
+ pImp->bCtrlReleased = sal_False;
+ }
+
+ return nRegLevel;
+}
+//--------------------------------------------------------------------
+
+void SfxBindings::LeaveRegistrations( sal_uInt16 nLevel, char *pFile, int nLine )
+
+/* [Beschreibung]
+
+ Die An- oder Abmeldung von <SfxControllerItem> Instanzen mu"s in
+ EnterRegistrations() und LeaveRegistrations() geklammert werden.
+ W"ahrend dieser Zeit erfolgen keine Udates der <SfxContollerItem>
+ Instanzen (weder der alten noch der neu angemeldeten).
+
+
+ [Parameter]
+
+ sal_uInt16 nLevel == USRT_MAX
+ keine Paarigkeits-Pr"ufung f"ur diese Klammerung
+
+
+ pFile, nLine Dateiname und Zeilennummer der rufenden
+ Methode (nur Debug)
+
+ < USHRT_MAX
+ R"uckgabewert des zugeh"origen EnterRegistrations()
+ zum pr"ufen der Paarigkeit.
+
+
+ [Querverweise]
+ <SfxBindings::IsInRegistrations()>
+ <SfxBindings::Register(SfxControllerItem&)>
+ <SfxBindings::Release(SfxControllerItem&)>
+ <SfxBindings::EnterRegistrations()>
+*/
+
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( nRegLevel, "Leave without Enter" );
+ DBG_ASSERT( nLevel == USHRT_MAX || nLevel == nRegLevel, "wrong Leave" );
+
+ // Nur wenn die SubBindings noch von den SuperBindings gelockt sind, diesen Lock entfernen
+ // ( d.h. wenn es mehr Locks als "echte" Locks dort gibt )
+ if ( pImp->pSubBindings && pImp->pSubBindings->nRegLevel > pImp->pSubBindings->pImp->nOwnRegLevel )
+ {
+ // Bindings synchronisieren
+ pImp->pSubBindings->nRegLevel = nRegLevel + pImp->pSubBindings->pImp->nOwnRegLevel;
+
+ // Dieses LeaveRegistrations ist f"ur die SubBindings kein "echtes"
+ pImp->pSubBindings->pImp->nOwnRegLevel++;
+ pImp->pSubBindings->LEAVEREGISTRATIONS();
+ }
+
+ pImp->nOwnRegLevel--;
+
+ // check if this is the outer most level
+ if ( --nRegLevel == 0 && !SFX_APP()->IsDowning() )
+ {
+#ifndef slow
+ SfxViewFrame* pFrame = pDispatcher->GetFrame();
+
+ // ggf unbenutzte Caches entfernen bzw. PlugInInfo aufbereiten
+ if ( pImp->bCtrlReleased )
+ {
+ for ( sal_uInt16 nCache = pImp->pCaches->Count(); nCache > 0; --nCache )
+ {
+ // Cache via ::com::sun::star::sdbcx::Index besorgen
+ SfxStateCache *pCache = pImp->pCaches->GetObject(nCache-1);
+
+ // kein Controller mehr interessiert
+ if ( pCache->GetItemLink() == 0 )
+ {
+ // Cache entfernen
+ delete (*pImp->pCaches)[nCache-1];
+ pImp->pCaches->Remove(nCache-1, 1);
+ }
+ else
+ {
+ // neue Controller mit den alten Items benachrichtigen
+ //!pCache->SetCachedState();
+ }
+ }
+ }
+#endif
+ // restart background-processing
+ pImp->nMsgPos = 0;
+ if ( !pFrame || !pFrame->GetObjectShell() )
+ return;
+ if ( pImp->pCaches && pImp->pCaches->Count() )
+ {
+ pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
+ pImp->aTimer.Start();
+// pImp->bFirstRound = sal_True;
+ }
+ }
+
+#ifdef DBG_UTIL
+ ByteString aMsg;
+ aMsg.Fill( Min(nRegLevel, sal_uInt16(8)) );
+ aMsg += "this = ";
+ aMsg += ByteString::CreateFromInt32((long)this);
+ aMsg += " Level = ";
+ aMsg += ByteString::CreateFromInt32(nRegLevel);
+ aMsg += " SfxBindings::LeaveRegistrations ";
+ if(pFile) {
+ aMsg += "File: ";
+ aMsg += pFile;
+ aMsg += " Line: ";
+ aMsg += ByteString::CreateFromInt32(nLine);
+ }
+ DbgTrace( aMsg.GetBuffer() );
+#endif
+}
+
+//--------------------------------------------------------------------
+
+const SfxSlot* SfxBindings::GetSlot(sal_uInt16 nSlotId)
+
+/* [Beschreibung]
+
+ Diese Methode liefert einen Pointer auf den zur Zeit gecacheten
+ SfxSlot f"ur die angegebene Slot-Id.
+
+
+ [R"uckgabewert]
+
+ const <SfxSlot>* 0
+ Falls die Slot-Id nicht gebunden ist oder
+ ein solcher Slot momentan in keiner aktiven
+ <SfxShell> vorhanden ist.
+
+ != 0
+ Falls die Slot-Id gebunden ist und ein solcher
+ Slot momentan in einer aktiven <SfxShell>
+ vorhanden ist.
+*/
+
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
+
+ // syncronisieren
+ pDispatcher->Flush();
+ if ( pImp->bMsgDirty )
+ UpdateSlotServer_Impl();
+
+ // get the cache for the specified function; return if not bound
+ SfxStateCache* pCache = GetStateCache(nSlotId);
+ return pCache && pCache->GetSlotServer(*pDispatcher, pImp->xProv)?
+ pCache->GetSlotServer(*pDispatcher, pImp->xProv)->GetSlot(): 0;
+}
+
+//--------------------------------------------------------------------
+
+void SfxBindings::SetDispatcher( SfxDispatcher *pDisp )
+
+/* [Beschreibung]
+
+ Setzt den zur Zeit von dieser SfxBindings Instanz zu verwendenden
+ Dispatcher um.
+
+ Falls sich der Dispatcher dadurch "andert, wird intern
+ <SFxBindings::InvalidateAll(sal_Bool)> mit sal_True gerufen, also jegliche
+ gecachete Information der Bindings weggeworfen.
+*/
+
+{
+ SfxDispatcher *pOldDispat = pDispatcher;
+ if ( pDisp != pDispatcher )
+ {
+ if ( pOldDispat )
+ {
+ SfxBindings* pBind = pOldDispat->GetBindings();
+ while ( pBind )
+ {
+ if ( pBind->pImp->pSubBindings == this && pBind->pDispatcher != pDisp )
+ pBind->SetSubBindings_Impl( NULL );
+ pBind = pBind->pImp->pSubBindings;
+ }
+ }
+
+ pDispatcher = pDisp;
+ InvalidateAll( sal_True );
+ InvalidateUnoControllers_Impl();
+ if ( pDispatcher && !pOldDispat )
+ {
+ if ( pImp->pSubBindings && pImp->pSubBindings->pDispatcher != pOldDispat )
+ {
+ DBG_ERROR( "SubBindings vor Aktivieren schon gesetzt!" );
+ pImp->pSubBindings->ENTERREGISTRATIONS();
+ }
+ LEAVEREGISTRATIONS();
+ }
+ else if( !pDispatcher )
+ {
+ ENTERREGISTRATIONS();
+ if ( pImp->pSubBindings && pImp->pSubBindings->pDispatcher != pOldDispat )
+ {
+ DBG_ERROR( "SubBindings im Deaktivieren immer noch gesetzt!" );
+ pImp->pSubBindings->LEAVEREGISTRATIONS();
+ }
+ }
+
+ Broadcast( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
+
+ if ( pDisp )
+ {
+ SfxBindings* pBind = pDisp->GetBindings();
+ while ( pBind && pBind != this )
+ {
+ if ( !pBind->pImp->pSubBindings )
+ {
+ pBind->SetSubBindings_Impl( this );
+ break;
+ }
+
+ pBind = pBind->pImp->pSubBindings;
+ }
+ }
+ }
+}
+
+//--------------------------------------------------------------------
+
+void SfxBindings::ClearCache_Impl( sal_uInt16 nSlotId )
+
+// interne Methode zum forwarden dieses Methodenaufrufs
+
+{
+ GetStateCache(nSlotId)->ClearCache();
+}
+
+//--------------------------------------------------------------------
+
+// interne Methode zum Ansto\sen des Statusupdates
+
+void SfxBindings::StartUpdate_Impl( sal_Bool bComplete )
+{
+ if ( pImp->pSubBindings )
+ pImp->pSubBindings->StartUpdate_Impl( bComplete );
+
+ if ( !bComplete )
+ // Update darf unterbrochen werden
+ NextJob_Impl(&pImp->aTimer);
+ else
+ // alle Slots am St"uck updaten
+ NextJob_Impl(0);
+}
+
+//--------------------------------------------------------------------
+
+#if SUPD<359
+SfxSlotInterceptor::SfxSlotInterceptor( SfxBindings *pBindings )
+: _pImp( new SfxSlotInterceptor_Impl )
+{
+ DBG_ASSERT( pBindings, "SfxBindings: 0-Pointer not allowed" );
+ _pImp->_pBindings = pBindings;
+ _pImp->_bIsActive = sal_False;
+
+ // ggf. Interceptor-Liste on-demand erzeugen
+ if ( !_pImp->_pBindings->pImp->pInterceptors )
+ _pImp->_pBindings->pImp->pInterceptors = new SfxInterceptorArr_Impl;
+
+ Activate(sal_True);
+}
+#endif
+
+SfxSlotInterceptor::SfxSlotInterceptor( SfxBindings *pBindings, sal_Bool bActivate )
+
+/* [Bindings]
+
+ Registriert diese Instanz an den angegebenen <SfxBindings>.
+ Ab jetzt wird vor jedem Ausf"uhren eines Slots "uber diese
+ Bindings die virtuelle Methode <SfxSlotInterceptor::Execute()>
+ gerufen und vor jedem Erfragen eines Status die virtuelle
+ Methode <SfxSlotInterceptor::QueryState()>.
+*/
+
+: _pImp( new SfxSlotInterceptor_Impl )
+{
+ _pImp->_pBindings = pBindings;
+ _pImp->_bIsActive = sal_False;
+
+ Activate( bActivate );
+}
+
+//--------------------------------------------------------------------
+
+SfxSlotInterceptor::~SfxSlotInterceptor()
+
+/* [Bindings]
+
+ Beendet das Abfangen der Execute- und Status-Aufrufe an den
+ im Ctor angegebenen Bindings.
+*/
+
+{
+ Activate(sal_False);
+ delete _pImp;
+}
+
+void SfxSlotInterceptor::SetBindings( SfxBindings* pBindings )
+{
+ DBG_ASSERT( !_pImp->_pBindings, "SetBindings bei gesetzten Bindings" );
+ _pImp->_pBindings = pBindings;
+}
+
+SfxBindings* SfxSlotInterceptor::GetBindings() const
+{
+ return _pImp->_pBindings;
+}
+
+
+//--------------------------------------------------------------------
+
+void SfxSlotInterceptor::Activate( sal_Bool bActivate )
+{
+
+ if ( _pImp->_bIsActive == bActivate )
+ return;
+
+ if ( bActivate)
+ _pImp->_pBindings->pImp->InsertSlotInterceptor( this );
+ else
+ _pImp->_pBindings->pImp->RemoveSlotInterceptor( this );
+
+ _pImp->_bIsActive = bActivate;
+ _pImp->_pBindings->InvalidateAll( sal_False );
+}
+
+//-------------------------------------------------------------------------
+
+sal_Bool SfxSlotInterceptor::IsActive() const
+{
+ return _pImp->_bIsActive;
+}
+
+//-------------------------------------------------------------------------
+
+#if SUPD < 355
+sal_Bool SfxSlotInterceptor::Execute( sal_uInt16 nSID )
+#else
+sal_Bool SfxSlotInterceptor::Execute( sal_uInt16 nSID, SfxPoolItem **ppArgs )
+#endif
+
+
+/* [Beschreibung]
+
+ Diese pur-virtuelle Methode mu\s von Subklassen "uberladen werden.
+ Sie wird gerufen, um 'nSID' auszuf"uhren.
+
+ Wurde die SID nicht bearbeitet und soll an den Dispatcher weitergeleitet
+ werden, so mu\s sal_False zur"uckgegeben werden.
+
+ [Beispiel]
+
+ sal_Bool X::Execute( sal_uInt16 nSID )
+ {
+ switch ( nSID )
+ {
+ case SID_A:
+ ...
+ return sal_True;
+
+ case SID_B:
+ ...
+ return sal_True;
+
+ case SID_C:
+ ...
+ return sal_True;
+ }
+
+ return sal_False;
+ }
+*/
+
+{
+ return sal_False;
+}
+
+//-------------------------------------------------------------------------
+
+SfxItemState SfxSlotInterceptor::QueryState
+(
+ sal_uInt16 nSID, // IN: Slot-Id, deren Status erfragt wird
+ SfxPoolItem*& rpState // OUT: Status-Wert (Eigent"umer"ubergang)
+)
+
+/* [Beschreibung]
+
+ Diese pur-virtuelle Methode mu\s von Subklassen "uberladen werden.
+ Sie wird gerufen, um den Status f"ur 'nSID' zu erfragen. 'rpState'
+ darf nur dann ein mit 'new' anzulegendes <SfxPoolItem> zugewiesen
+ werden, wenn <SFX_ITEM_SET> zur"uckgeliefert wird.
+
+ Wurde die SID nicht bearbeitet und soll an den Dispatcher weitergeleitet
+ werden, so mu\s <SFX_ITEM_UNKNOWN> zur"uckgegeben werden (Basisklasse
+ rufen!).
+
+ [Beispiel]
+
+ SfxItemState X::QueryState( sal_uInt16 nSID, SfxPoolItem*& rpState )
+ {
+ switch ( nSID )
+ {
+ case SID_A:
+ // Status-Item verschicken => enabled
+ rpState = new SfxStringItem( nSID, ... );
+ return SFX_ITEM_SET;
+
+ case SID_B:
+ // kein Status aber trotzdem enabled
+ return SFX_ITEM_AVAILABLE;
+
+ case SID_C:
+ // disabled
+ return SFX_ITEM_DISABLED;
+
+ case SID_D:
+ // mehrdeutig, enabled
+ return SFX_ITEM_DONTCARE;
+ }
+
+ return SfxSlotInterceptor::QueryState( nSID, rpState );
+ }
+*/
+
+{
+ return SFX_ITEM_UNKNOWN;
+}
+
+//-------------------------------------------------------------------------
+
+SfxItemState SfxBindings::QueryState( sal_uInt16 nSlot, SfxPoolItem* &rpState )
+/* [Beschreibung]
+
+ Wird gerufen, um den Status f"ur 'nSlot' zu erfragen. Wenn der return
+ value SFX_ITEM_SET ist, wird ein SfxPoolItem zur"uckgegeben, indem der
+ rpState entsprechend gesetzt wird. Es findet dabei ein Eigent"umer"ubergang
+ statt, d.h. die aufrufende Methode mu\s das Item l"oschen.
+
+ Anmerkung: diese Methode ist sehr teuer und sollte nur gerufen werden,
+ wenn kein Controller f"ur das Erfragen des Status angelegt werden kann oder
+ der Status unbedingt sofort geliefert werden mu\s.
+*/
+
+{
+ ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > xDisp;
+ SfxStateCache *pCache = GetStateCache( nSlot );
+ if ( pCache )
+ xDisp = pCache->GetDispatch();
+ if ( xDisp.is() || !pCache && pImp->xProv.is() )
+ {
+//(mba)/compview
+ const SfxSlot* pSlot = 0;//SfxComponentViewShell::GetUnoSlot( nSlot );
+ ::com::sun::star::util::URL aURL;
+ if ( pSlot )
+ {
+ String aCmd( DEFINE_CONST_UNICODE(".uno:"));
+ aCmd += String::CreateFromAscii(pSlot->GetUnoName());
+ aURL.Complete = aCmd;
+ }
+ else
+ {
+ String aCmd( DEFINE_CONST_UNICODE("slot:") );
+ aCmd += String::CreateFromInt32(nSlot);
+ aURL.Complete = aCmd;
+ }
+
+ Reference < XURLTransformer > xTrans( ::utl::getProcessServiceFactory()->createInstance( rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer" )), UNO_QUERY );
+ xTrans->parseStrict( aURL );
+ if ( !xDisp.is() )
+ xDisp = pImp->xProv->queryDispatch( aURL, ::rtl::OUString(), 0 );
+
+ if ( xDisp.is() )
+ {
+ ::com::sun::star::uno::Reference< ::com::sun::star::lang::XUnoTunnel > xTunnel( xDisp, ::com::sun::star::uno::UNO_QUERY );
+ SfxOfficeDispatch* pDisp = NULL;
+ if ( xTunnel.is() )
+ {
+ sal_Int64 nImplementation = xTunnel->getSomething(SfxOfficeDispatch::impl_getStaticIdentifier());
+ pDisp = (SfxOfficeDispatch*)(nImplementation);
+ }
+
+ if ( !pDisp || pDisp->IsInterceptDispatch() )
+ {
+ SfxItemState eState = SFX_ITEM_SET;
+ SfxPoolItem *pItem=NULL;
+ BindDispatch_Impl *pBind = new BindDispatch_Impl( xDisp, aURL, NULL );
+ pBind->acquire();
+ xDisp->addStatusListener( pBind, aURL );
+ if ( !pBind->GetStatus().IsEnabled )
+ eState = SFX_ITEM_DISABLED;
+ else
+ {
+ ::com::sun::star::uno::Any aAny = pBind->GetStatus().State;
+ ::com::sun::star::uno::Type pType = aAny.getValueType();
+
+ if ( pType == ::getBooleanCppuType() )
+ {
+ sal_Bool bTemp ;
+ aAny >>= bTemp ;
+ pItem = new SfxBoolItem( nSlot, bTemp );
+ }
+ else if ( pType == ::getCppuType((const sal_uInt16*)0) )
+ {
+ sal_uInt16 nTemp ;
+ aAny >>= nTemp ;
+ pItem = new SfxUInt16Item( nSlot, nTemp );
+ }
+ else if ( pType == ::getCppuType((const sal_uInt32*)0) )
+ {
+ sal_uInt32 nTemp ;
+ aAny >>= nTemp ;
+ pItem = new SfxUInt32Item( nSlot, nTemp );
+ }
+ else if ( pType == ::getCppuType((const ::rtl::OUString*)0) )
+ {
+ ::rtl::OUString sTemp ;
+ aAny >>= sTemp ;
+ pItem = new SfxStringItem( nSlot, sTemp );
+ }
+ else
+ pItem = new SfxVoidItem( nSlot );
+ }
+
+ pBind->Release();
+ rpState = pItem;
+ return eState;
+ }
+ }
+ }
+
+ SfxSlotServer aServer;
+/*
+ if ( pDispatcher->_TryIntercept_Impl( nSlot, aServer, sal_False ) )
+ {
+ SfxShell* pShell = pDispatcher->GetShell( aServer.GetShellLevel() );
+ const SfxPoolItem *pItem = pShell->GetSlotState(nSlot);
+ if ( !pItem )
+ return SFX_ITEM_DISABLED;
+ else
+ {
+ rpState = pItem->Clone();
+ return SFX_ITEM_SET;
+ }
+ }
+*/
+ if ( pImp->pInterceptors )
+ {
+ // Zuerst die Interceptoren testen
+ for ( sal_uInt16 n = 0; n < pImp->pInterceptors->Count(); ++n )
+ {
+ SfxSlotInterceptor *pInterceptor = pImp->pInterceptors->GetObject(n);
+ SfxItemState eState = pInterceptor->QueryState( nSlot, rpState );
+ if ( SFX_ITEM_UNKNOWN != eState )
+ return eState;
+ }
+ }
+
+ // Dann am Dispatcher testen; da die von dort zur"uckgegebenen Items immer
+ // DELETE_ON_IDLE sind, mu\s eine Kopie davon gezogen werden, um einen
+ // Eigent"umer"ubergang zu erm"oglichen
+ const SfxPoolItem *pItem = NULL;
+ SfxItemState eState = pDispatcher->QueryState( nSlot, pItem );
+ if ( eState == SFX_ITEM_SET )
+ {
+ DBG_ASSERT( pItem, "SFX_ITEM_SET aber kein Item!" );
+ if ( pItem )
+ rpState = pItem->Clone();
+ }
+ else if ( eState == SFX_ITEM_AVAILABLE && pItem )
+ {
+ rpState = pItem->Clone();
+ }
+
+ return eState;
+}
+
+#if 0
+sal_Bool SfxBindings::IsInExecute_Impl() const
+{
+ return pImp->bInExecute;
+}
+#endif
+
+void SfxBindings::SetSubBindings_Impl( SfxBindings *pSub )
+{
+ if ( pImp->pSubBindings )
+ {
+ if ( pImp->pInterceptors )
+ {
+ for ( sal_uInt16 n = 0; n < pImp->pInterceptors->Count(); ++n )
+ {
+ SfxSlotInterceptor *pInter = pImp->pInterceptors->GetObject(n);
+ pImp->pSubBindings->pImp->RemoveSlotInterceptor( pInter );
+ }
+ }
+
+ pImp->pSubBindings->SetDispatchProvider_Impl( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > () );
+ pImp->pSubBindings->pImp->pSuperBindings = NULL;
+ }
+
+ pImp->pSubBindings = pSub;
+
+ if ( pSub )
+ {
+ pImp->pSubBindings->SetDispatchProvider_Impl( pImp->xProv );
+ pSub->pImp->pSuperBindings = this;
+
+ if ( pImp->pInterceptors )
+ {
+ for ( sal_uInt16 n = 0; n < pImp->pInterceptors->Count(); ++n )
+ {
+ SfxSlotInterceptor *pInter = pImp->pInterceptors->GetObject(n);
+ pImp->pSubBindings->pImp->InsertSlotInterceptor( pInter );
+ }
+ }
+ }
+}
+
+SfxBindings* SfxBindings::GetSubBindings_Impl( sal_Bool bTop ) const
+{
+ SfxBindings *pRet = pImp->pSubBindings;
+ if ( bTop )
+ {
+ while ( pRet->pImp->pSubBindings )
+ pRet = pRet->pImp->pSubBindings;
+ }
+
+ return pRet;
+}
+
+void SfxBindings::SetWorkWindow_Impl( SfxWorkWindow* pWork )
+{
+ pImp->pWorkWin = pWork;
+}
+
+SfxWorkWindow* SfxBindings::GetWorkWindow_Impl() const
+{
+ return pImp->pWorkWin;
+}
+
+void SfxBindings::RegisterUnoController_Impl( SfxUnoControllerItem* pControl )
+{
+ if ( !pImp->pUnoCtrlArr )
+ pImp->pUnoCtrlArr = new SfxUnoControllerArr_Impl;
+ pImp->pUnoCtrlArr->Insert( pControl, pImp->pUnoCtrlArr->Count() );
+}
+
+void SfxBindings::ReleaseUnoController_Impl( SfxUnoControllerItem* pControl )
+{
+ if ( pImp->pUnoCtrlArr )
+ {
+ sal_uInt16 nPos = pImp->pUnoCtrlArr->GetPos( pControl );
+ if ( nPos != 0xFFFF )
+ {
+ pImp->pUnoCtrlArr->Remove( nPos );
+ return;
+ }
+ }
+
+ if ( pImp->pSubBindings )
+ pImp->pSubBindings->ReleaseUnoController_Impl( pControl );
+}
+
+void SfxBindings::InvalidateUnoControllers_Impl()
+{
+ if ( pImp->pUnoCtrlArr )
+ {
+ sal_uInt16 nCount = pImp->pUnoCtrlArr->Count();
+ for ( sal_uInt16 n=nCount; n>0; n-- )
+ {
+ SfxUnoControllerItem *pCtrl = (*pImp->pUnoCtrlArr)[n-1];
+ ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > xRef( (::cppu::OWeakObject*)pCtrl, ::com::sun::star::uno::UNO_QUERY );
+ pCtrl->ReleaseDispatch();
+ pCtrl->GetNewDispatch();
+ }
+ }
+
+ if ( pImp->pSubBindings )
+ pImp->pSubBindings->InvalidateUnoControllers_Impl();
+}
+
+sal_Bool SfxBindings::IsInUpdate() const
+{
+ sal_Bool bInUpdate = pImp->bInUpdate;
+ if ( !bInUpdate && pImp->pSubBindings )
+ bInUpdate = pImp->pSubBindings->IsInUpdate();
+ return bInUpdate;
+}
+
+void SfxBindings::SetActiveFrame( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > & rFrame )
+{
+ if ( rFrame.is() )
+ SetDispatchProvider_Impl( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > ( rFrame, ::com::sun::star::uno::UNO_QUERY ) );
+ else if ( pDispatcher && pDispatcher->GetFrame() )
+ {
+ SfxFrame *pFrame = pDispatcher->GetFrame()->GetFrame();
+ ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > xProv( pFrame->GetInterceptor_Impl(), ::com::sun::star::uno::UNO_QUERY );
+ SetDispatchProvider_Impl( xProv );
+ }
+ else
+ SetDispatchProvider_Impl( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > () );
+}
+
+void SfxBindings::SetDispatchProvider_Impl( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > & rProv )
+{
+ sal_Bool bInvalidate = ( rProv != pImp->xProv );
+ if ( bInvalidate )
+ {
+ pImp->xProv = rProv;
+ InvalidateAll( sal_True );
+ InvalidateUnoControllers_Impl();
+ }
+
+ if ( pImp->pSubBindings )
+ pImp->pSubBindings->SetDispatchProvider_Impl( pImp->xProv );
+}
+
+const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > & SfxBindings::GetDispatchProvider_Impl() const
+{
+ return pImp->xProv;
+}
+
+SystemWindow* SfxBindings::GetSystemWindow() const
+{
+ SfxViewFrame *pFrame = pDispatcher->GetFrame();
+ while ( pFrame->GetParentViewFrame_Impl() )
+ pFrame = pFrame->GetParentViewFrame_Impl();
+ SfxTopViewFrame* pTop = PTR_CAST( SfxTopViewFrame, pFrame->GetTopViewFrame() );
+ return pTop->GetTopFrame_Impl()->GetTopWindow_Impl();
+}
diff --git a/sfx2/source/control/ctrlitem.cxx b/sfx2/source/control/ctrlitem.cxx
new file mode 100644
index 000000000000..2d832fd0ef80
--- /dev/null
+++ b/sfx2/source/control/ctrlitem.cxx
@@ -0,0 +1,480 @@
+/*************************************************************************
+ *
+ * $RCSfile: ctrlitem.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 16:52:29 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _SFXITEMPOOL_HXX //autogen
+#include <svtools/itempool.hxx>
+#endif
+#pragma hdrstop
+
+#include "ctrlitem.hxx"
+#include "bindings.hxx"
+#include "dispatch.hxx"
+#include "msgpool.hxx"
+#include "statcach.hxx"
+
+//====================================================================
+
+DBG_NAME(SfxControllerItem);
+
+//--------------------------------------------------------------------
+#ifdef DBG_UTIL
+
+void SfxControllerItem::CheckConfigure_Impl( ULONG nType )
+{
+ // echter Slot? (also kein Separator etc.)
+ if ( !nId )
+ return;
+
+ // ist die Id "uberhaupt in 'nType' konfigurierbar?
+ const SfxSlot *pSlot = SFX_SLOTPOOL().GetSlot(nId);
+ DBG_ASSERTWARNING( pSlot, "SfxControllerItem: binding not existing slot" );
+ if ( pSlot && !pSlot->IsMode(nType) )
+ {
+ DBG_WARNING( "SfxControllerItem: slot without ...Config-flag" );
+ DbgOutf( "SfxControllerItem: Config-flag missing at SID %5d",
+ pSlot->GetSlotId() );
+ }
+}
+
+#endif
+
+//--------------------------------------------------------------------
+
+// returns the next registered SfxControllerItem with the same id
+
+SfxControllerItem* SfxControllerItem::GetItemLink()
+{
+ DBG_MEMTEST();
+ DBG_CHKTHIS(SfxControllerItem, 0);
+ return pNext == this ? 0 : pNext;
+}
+
+//--------------------------------------------------------------------
+
+// returns TRUE if this binding is really bound to a function
+
+BOOL SfxControllerItem::IsBound() const
+{
+ DBG_MEMTEST();
+ DBG_CHKTHIS(SfxControllerItem, 0);
+ return pNext != this;
+}
+
+//--------------------------------------------------------------------
+
+// returns the associated function-id or 0 if none
+
+// USHORT SfxControllerItem::GetId() const;
+
+//====================================================================
+
+// registeres with the id at the bindings
+
+void SfxControllerItem::Bind( USHORT nNewId, SfxBindings *pBindinx )
+{
+ DBG_MEMTEST();
+ DBG_CHKTHIS(SfxControllerItem, 0);
+ DBG_ASSERT(pBindings || pBindinx, "Keine Bindings");
+
+ if ( IsBound() ) {
+ DBG_ASSERT(pBindings, "Keine Bindings");
+ pBindings->Release(*this);
+ }
+
+ nId = nNewId;
+ pNext = 0;
+
+ if (pBindinx)
+ pBindings = pBindinx;
+ pBindings->Register(*this);
+}
+
+
+//====================================================================
+
+void SfxControllerItem::UnBind()
+
+/* [Beschreibung]
+
+ "ost die Verbindung dieses SfxControllerItems mit der SfxBindings-Instanz,
+ an der es zur Zeit gebunden ist. Ab diesem Zeitpunkt erh"alt es keine
+ Statusbenachrichtigungen (<SfxControllerItem::StateChented()>) mehr.
+
+
+ [Querverweise]
+
+ <SfxControllerItem::ReBind()>
+ <SfxControllerItem::ClearCache()>
+*/
+{
+ DBG_MEMTEST();
+ DBG_CHKTHIS(SfxControllerItem, 0);
+ DBG_ASSERT(pBindings, "Keine Bindings");
+ DBG_ASSERT( IsBound(), "unbindings unbound SfxControllerItem" );
+
+ pBindings->Release(*this);
+ pNext = this;
+}
+
+//====================================================================
+
+void SfxControllerItem::ReBind()
+
+/* [Beschreibung]
+
+ Binded dieses SfxControllerItem wieder an die SfxBindings-Instanz,
+ an der es zuletzt gebunden war. Ab diesem Zeitpunkt erh"alt es wieder
+ Statusbenachrichtigungen (<SfxControllerItem::StateChented()>).
+
+
+ [Querverweise]
+
+ <SfxControllerItem::UnBind()>
+ <SfxControllerItem::ClearCache()>
+*/
+
+{
+ DBG_MEMTEST();
+ DBG_CHKTHIS(SfxControllerItem, 0);
+ DBG_ASSERT(pBindings, "Keine Bindings");
+ DBG_ASSERT( !IsBound(), "bindings rebound SfxControllerItem" );
+
+ pBindings->Register(*this);
+}
+
+//====================================================================
+
+void SfxControllerItem::UpdateSlot()
+
+/* [Beschreibung]
+
+ Holt den Status 'hart' neu.
+
+ [Querverweise]
+
+ <SfxControllerItem::ClearCache()>
+*/
+
+{
+ DBG_MEMTEST();
+ DBG_CHKTHIS(SfxControllerItem, 0);
+ DBG_ASSERT(pBindings, "Keine Bindings");
+
+ pBindings->Update( GetId() );
+}
+
+//--------------------------------------------------------------------
+
+void SfxControllerItem::ClearCache()
+
+/* [Beschreibung]
+
+ "oscht den Status-Cache f"ur dieses SfxControllerItem. D.h. beim
+ n"achsten Status-Update wird das <SfxPoolItem> auf jeden Fall geschickt,
+ auch wenn zuvor dasselbe geschickt wurde. Dies wird ben"otigt, wenn
+ ein Controller umgeschaltet werden kann und sich diesen Status
+ selbst merkt.
+
+
+ [Beispiel]
+
+ Der Kombi-Controller f"ur das Einstellen des Fl"achentyps und der
+ konkreten Auspr"agung (Farbe blau oder Schraffur X) kann im Typ
+ umgestellt werden, wird jedoch dann bei der n"achsten Selektion
+ wieder benachrichtigt, auch wenn es dieselben Daten sind.
+
+
+ [Querverweise]
+
+ <SfxControllerItem::UnBind()>
+ <SfxControllerItem::ReBind()>
+*/
+
+
+{
+ DBG_MEMTEST();
+ DBG_CHKTHIS(SfxControllerItem, 0);
+ DBG_ASSERT(pBindings, "Keine Bindings");
+
+ pBindings->ClearCache_Impl( GetId() );
+}
+
+//--------------------------------------------------------------------
+
+// replaces the successor in the list of bindings of the same id
+
+SfxControllerItem* SfxControllerItem::ChangeItemLink( SfxControllerItem* pNewLink )
+{
+ DBG_MEMTEST();
+ DBG_CHKTHIS(SfxControllerItem, 0);
+ SfxControllerItem* pOldLink = pNext;
+ pNext = pNewLink;
+ return pOldLink == this ? 0 : pOldLink;
+}
+
+//--------------------------------------------------------------------
+
+// changes the id of unbound functions (e.g. for sub-menu-ids)
+
+void SfxControllerItem::SetId( USHORT nItemId )
+{
+ DBG_MEMTEST();
+ DBG_CHKTHIS(SfxControllerItem, 0);
+ DBG_ASSERT( !IsBound(), "changing id of bound binding" );
+ nId = nItemId;
+}
+
+//--------------------------------------------------------------------
+
+SvStream& operator<<( SvStream& rStream, const SfxControllerItem& rFunc )
+{
+ DBG_MEMTEST();
+ SFX_SLOTPOOL().StoreId( rStream, rFunc.nId );
+ return rStream;
+}
+
+//--------------------------------------------------------------------
+
+SvStream& operator>>( SvStream& rStream, SfxControllerItem& rFunc )
+{
+ DBG_MEMTEST();
+ USHORT nId;
+ SFX_SLOTPOOL().LoadId( rStream, nId );
+ rFunc.Bind(nId);
+ return rStream;
+}
+
+//--------------------------------------------------------------------
+
+// creates a atomic item for a controller without registration
+
+SfxControllerItem::SfxControllerItem():
+ nId(0),
+ pNext(this),
+ pBindings(0)
+{
+ DBG_MEMTEST();
+ DBG_CTOR(SfxControllerItem, 0);
+}
+
+//--------------------------------------------------------------------
+
+// creates a representation of the function nId and registeres it
+
+SfxControllerItem::SfxControllerItem( USHORT nId, SfxBindings &rBindings ):
+ nId(nId),
+ pNext(this),
+ pBindings(&rBindings)
+{
+ DBG_MEMTEST();
+ DBG_CTOR(SfxControllerItem, 0);
+ Bind(nId, &rBindings);
+}
+
+//--------------------------------------------------------------------
+
+// unregisteres the item in the bindings
+
+SfxControllerItem::~SfxControllerItem()
+{
+ DBG_MEMTEST();
+ if ( IsBound() )
+ pBindings->Release(*this);
+ DBG_DTOR(SfxControllerItem, 0);
+}
+
+//--------------------------------------------------------------------
+
+void SfxControllerItem::StateChanged
+(
+ USHORT nSID, // <SID> des ausl"osenden Slot
+ SfxItemState eState, // <SfxItemState> von 'pState'
+ const SfxPoolItem* pState // Slot-Status, ggf. 0 oder IsInvalidItem()
+)
+
+/* [Beschreibung]
+
+ Diese virtuelle Methode wird vom SFx gerufen, um <SfxControllerItem>s
+ dar"uber zu benachrichtigen, da\s sich der Status des Slots 'nSID'
+ ge"andert hat. Der neue Wert sowie der von diesem Wert ermittelte
+ Status wird als 'pState' bzw. 'eState' mitgegeben.
+
+ Der Status eines Slots kann sich "andern, wenn z.B. das MDI-Fenster
+ gewechselt wird oder der Slot explizit mit <SfxBindings::Invalidate()>
+ invalidiert wurde.
+
+ Achtung! Die Methode wird nicht gerufen, wenn der Slot ung"ultig wurde,
+ danach jedoch wieder denselben Wert angenommen hat.
+
+ Diese Basisklasse braucht nicht gerufen zu werden, weitere Zwischenstufen
+ jedoch (z.B. <SfxToolboxControl>) sollten gerufen werden.
+*/
+
+{
+ DBG_MEMTEST();
+ DBG_CHKTHIS(SfxControllerItem, 0);
+}
+
+//--------------------------------------------------------------------
+
+void SfxControllerItem::DeleteFloatingWindow()
+{
+ DBG_MEMTEST();
+ DBG_CHKTHIS(SfxControllerItem, 0);
+}
+
+//--------------------------------------------------------------------
+
+void SfxStatusForwarder::StateChanged
+(
+ USHORT nSID, // <SID> des ausl"osenden Slot
+ SfxItemState eState, // <SfxItemState> von 'pState'
+ const SfxPoolItem* pState // Slot-Status, ggf. 0 oder IsInvalidItem()
+)
+
+{
+ pMaster->StateChanged( nSID, eState, pState );
+}
+
+//--------------------------------------------------------------------
+
+SfxStatusForwarder::SfxStatusForwarder(
+ USHORT nSlotId,
+ SfxControllerItem& rMaster ):
+ SfxControllerItem( nSlotId, rMaster.GetBindings() ),
+ pMaster( &rMaster )
+{
+}
+
+//--------------------------------------------------------------------
+
+SfxItemState SfxControllerItem::GetItemState
+(
+ const SfxPoolItem* pState /* Pointer auf das <SfxPoolItem>, dessen
+ Status erfragt werden soll. */
+)
+
+/* [Beschreibung]
+
+ Statische Methode zum Ermitteln des Status des SfxPoolItem-Pointers,
+ in der Methode <SfxControllerItem::StateChanged(const SfxPoolItem*)>
+ zu verwenden.
+
+ [R"uckgabewert]
+
+ SfxItemState SFX_ITEM_UNKNOWN
+ Enabled, aber keine weitere Statusinformation
+ verf"ugbar. Typisch f"ur <Slot>s, die allenfalls
+ zeitweise disabled sind, aber ihre Darstellung sonst
+ nicht "andern.
+
+ SFX_ITEM_DISABLED
+ Disabled und keine weiter Statusinformation
+ verf"ugbar. Alle anderen ggf. angezeigten Werte sollten
+ auf den Default zur"uckgesetzt werden.
+
+ SFX_ITEM_DONTCARE
+ Enabled aber es waren nur uneindeutige Werte
+ verf"ugbar (also keine, die abgefragt werden k"onnen).
+
+ SFX_ITEM_AVAILABLE
+ Enabled und mit verf"ugbarem Wert, der von 'pState'
+ erfragbar ist. Der Typ ist dabei im gesamten
+ Programm eindeutig und durch den Slot festgelegt.
+*/
+
+{
+ return !pState
+ ? SFX_ITEM_DISABLED
+ : IsInvalidItem(pState)
+ ? SFX_ITEM_DONTCARE
+ : pState->ISA(SfxVoidItem) && !pState->Which()
+ ? SFX_ITEM_UNKNOWN
+ : SFX_ITEM_AVAILABLE;
+}
+
+//--------------------------------------------------------------------
+
+SfxMapUnit SfxControllerItem::GetCoreMetric() const
+
+/* [Beschreibung]
+
+ Holt vom zust"andigen Pool die Ma\seinheit ab, in der das Status-Item
+ vorliegt.
+*/
+
+{
+ SfxStateCache *pCache = pBindings->GetStateCache( nId );
+ SfxDispatcher *pDispat = pBindings->GetDispatcher_Impl();
+ const SfxSlotServer *pServer = pCache->GetSlotServer( *pDispat );
+ SfxShell *pSh = pDispat->GetShell( pServer->GetShellLevel() );
+ SfxItemPool &rPool = pSh->GetPool();
+ USHORT nWhich = rPool.GetWhich( nId );
+ return rPool.GetMetric( nWhich );
+}
+
+//------------------------------------------------------------------------
+
+#ifdef WNT
+#pragma optimize("g",off)
+#endif
+
+
diff --git a/sfx2/source/control/dispatch.cxx b/sfx2/source/control/dispatch.cxx
new file mode 100644
index 000000000000..57c5c7f6e630
--- /dev/null
+++ b/sfx2/source/control/dispatch.cxx
@@ -0,0 +1,3493 @@
+/*************************************************************************
+ *
+ * $RCSfile: dispatch.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 16:52:29 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _SFXITEMPOOL_HXX //autogen
+#include <svtools/itempool.hxx>
+#endif
+#ifndef _SFXITEMITER_HXX //autogen
+#include <svtools/itemiter.hxx>
+#endif
+#ifndef _SFX_WHITER_HXX //autogen
+#include <svtools/whiter.hxx>
+#endif
+#ifndef _SFXINTITEM_HXX //autogen
+#include <svtools/intitem.hxx>
+#endif
+#ifndef _SFXEITEM_HXX //autogen
+#include <svtools/eitem.hxx>
+#endif
+#ifndef _UNDO_HXX //autogen
+#include <svtools/undo.hxx>
+#endif
+#ifndef _WRKWIN_HXX //autogen
+#include <vcl/wrkwin.hxx>
+#endif
+#ifndef _SVTOOLS_TTPROPS_HXX
+#include <svtools/ttprops.hxx>
+#endif
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h> // wg. bsearch
+
+#define _SVSTDARR_ULONGS
+#include <svtools/svstdarr.hxx>
+
+#pragma hdrstop
+
+#include "sfxhelp.hxx"
+#include "appdata.hxx"
+#include "dispatch.hxx"
+#include "minstack.hxx"
+#include "msg.hxx"
+#include "objface.hxx"
+#include "bindings.hxx"
+#include "request.hxx"
+#include "app.hxx"
+#include "hintpost.hxx"
+#include "slotserv.hxx"
+#include "ipfrm.hxx"
+#include "interno.hxx"
+#include "sfxtypes.hxx"
+#include "macrconf.hxx"
+#include "virtmenu.hxx"
+#include "viewfrm.hxx"
+#include "viewsh.hxx"
+#include "mnumgr.hxx"
+#include "childwin.hxx"
+#include "docfac.hxx"
+#include "saveopt.hxx"
+#include "ipenv.hxx"
+#include "msgpool.hxx"
+#include "module.hxx"
+#include "tbxconf.hxx"
+#include "topfrm.hxx"
+#include "sfxuno.hxx"
+
+//==================================================================
+DBG_NAME(SfxDispatcherFlush);
+DBG_NAME(SfxDispatcherFillState);
+
+//==================================================================
+SV_IMPL_PTRARR( SfxItemPtrArray, SfxPoolItemPtr );
+
+DECL_PTRSTACK(SfxShellStack_Impl, SfxShell*, 8, 4 );
+//==================================================================
+
+struct SfxToDo_Impl
+{
+ SfxShell* pCluster;
+ sal_Bool bPush;
+ sal_Bool bDelete;
+ sal_Bool bUntil;
+
+ SfxToDo_Impl():
+ bPush(sal_False), bDelete(sal_False), bUntil(sal_False), pCluster(0) {}
+ SfxToDo_Impl( sal_Bool bOpPush, sal_Bool bOpDelete, sal_Bool bOpUntil, SfxShell& rCluster ):
+ bPush(bOpPush), bDelete(bOpDelete), bUntil(bOpUntil), pCluster(&rCluster) {}
+ ~SfxToDo_Impl(){}
+
+ sal_Bool operator==( const SfxToDo_Impl& rWith ) const
+ { return pCluster==rWith.pCluster && bPush==rWith.bPush; }
+};
+
+DECL_OBJSTACK(SfxToDoStack_Impl, SfxToDo_Impl, 8, 4);
+IMPL_OBJSTACK(SfxToDoStack_Impl, SfxToDo_Impl);
+
+struct SfxObjectBars_Impl
+{
+ ResId aResId; // Resource - und ConfigId der Toolbox
+ sal_uInt16 nMode; // spezielle Sichtbarkeitsflags
+ String aName;
+ SfxInterface* pIFace;
+
+ SfxObjectBars_Impl() :
+ aResId( 0,0 )
+ {}
+};
+
+//------------------------------------------------------------------
+
+struct SfxDispatcher_Impl
+{
+ const SfxSlotServer* pCachedServ1; // zuletzt gerufene Message
+ const SfxSlotServer* pCachedServ2; // vorletzt gerufene Message
+ SfxShellStack_Impl aStack; // aktive Funktionalitaet
+ Timer aTimer; // fuers flushen
+ SfxToDoStack_Impl aToDoStack; // nicht abgearb. Push/Pop
+ SfxViewFrame* pFrame; // 0 oder zugeh"or. Frame
+ SfxDispatcher* pParent; // z.B. AppDispatcher, ggf. 0
+ SfxHintPosterRef xPoster; // asynchrones Execute
+ sal_Bool bFlushing; // sal_True waehrend Flush //?
+ sal_Bool bFlushed; // aToDoStack.Count() == 0
+ sal_Bool bUpdated; // Update_Impl gelaufen
+ sal_Bool bLocked; // kein Execute
+ sal_Bool bInvalidateOnUnlock;// da fragte jemand
+ sal_Bool bActive; // nicht verwechseln mit gesetzt!
+ sal_Bool* pInCallAliveFlag; // dem Stack den Dtor anzeigen
+ SfxObjectBars_Impl aObjBars[SFX_OBJECTBAR_MAX];
+ SfxObjectBars_Impl aFixedObjBars[SFX_OBJECTBAR_MAX];
+ SvULongs aChildWins;
+ sal_uInt16 nActionLevel; // in EnterAction
+ sal_uInt32 nEventId; // EventId UserEvent
+ sal_Bool bUILocked; // Update abgeklemmt (!zappeln)
+ sal_Bool bNoUI; // UI nur vom Parent Dispatcher
+ sal_Bool bReadOnly; // Dokument ist ReadOnly
+ sal_Bool bQuiet; // nur parent dispatcher verwenden
+ sal_Bool bModal; // nur Slots vom Parent-Dispatcher
+
+ sal_Bool bFilterEnabling; // sal_True=filter enabled slots, 2==ReadOnlyDoc uebersteuert
+ sal_uInt16 nFilterCount; // Anzahl der SIDs in pFilterSIDs
+ const sal_uInt16* pFilterSIDs; // sortiertes Array von SIDs
+ sal_uInt16 nStandardMode; // ExecuteMode f. PlugInDispatcher
+ SvUShorts* pDisableList;
+ sal_uInt32 nDisableFlags;
+};
+
+#define NO_OBJECTBAR 0
+#define OWN_OBJECTBAR 1
+#define OTHER_OBJECTBAR 2
+
+//------------------------------------------------------------------
+
+#define SFX_FLUSH_TIMEOUT 50
+
+//====================================================================
+sal_Bool SfxDispatcher::IsLocked( sal_uInt16 nSID ) const
+
+/* [Beschreibung]
+
+ Mit dieser Methode kann festgestellt werden, ob der SfxDispatcher
+ gesperrt oder freigegeben ist. Ein gesperrter SfxDispatcher
+ f"uhrt keine <SfxRequest>s mehr aus und liefert keine
+ Status-Informationen mehr. Er verh"alt sich so als w"aren alle
+ Slots disabled.
+
+ Der Dispatcher gilt auch als gesperrt, wenn alle Dispatcher
+ gelockt sind (<SfxApplication::LockDispatcher()>) oder der zugeh"orige
+ Top-Frame im modal-mode ist und der angegebene Slot Frame-spezifisch
+ (also nicht von der Application) bedient wird.
+*/
+
+{
+ return nSID != SID_BROWSE_STOP && nSID != SID_HELP_PI &&
+ ( pImp->bLocked || SFX_APP()->IsDispatcherLocked() );
+}
+
+//--------------------------------------------------------------------
+sal_Bool SfxDispatcher::IsAppDispatcher() const
+
+/* [Beschreibung]
+
+ Mit dieser Methode l"a\st sich festellen, ob der SfxDispacher der
+ Applikations-Dispatcher ist.
+
+
+ [R"uckgabewert]
+
+ sal_Bool sal_True
+ Es ist der Applikations-Dispatcher.
+
+ sal_False
+ Es ist ein Dispatcher eines SfxViewFrame.
+*/
+
+{
+ return !pImp->pFrame;
+}
+
+//--------------------------------------------------------------------
+int SfxDispatcher::Call_Impl( SfxShell& rShell, const SfxSlot &rSlot, SfxRequest &rReq, sal_Bool bRecord )
+
+/* [Beschreibung]
+
+ Hilfsfunktion zum pr"ufen, ob ein Slot executed werden darf und
+ der Execution selbst.
+*/
+
+{
+ SFX_STACK(SfxDispatcher::Call_Impl);
+
+ // darf der Slot gerufen werden (i.S.v. enabled)
+ SfxApplication *pSfxApp = SFX_APP();
+ if ( rSlot.IsMode(SFX_SLOT_FASTCALL) || rShell.CanExecuteSlot_Impl(rSlot) )
+ {
+ // ggf. die Bindings locken (MI: warum?)
+ SfxBindings *pBindings = GetBindings();
+#if modal_mode_sinnlos
+ sal_Bool bLockBindings = rSlot.GetSlotId() != SID_OPENDOC && rSlot.GetSlotId() != SID_OPENURL;
+ if ( bLockBindings && pBindings )
+ pBindings->DENTERREGISTRATIONS();
+#endif
+
+ // Alles holen, was gebraucht wird, da der Slot den Execute evtl. nicht
+ // "uberlebt, falls es ein 'Pseudoslot' f"ur Macros oder Verben ist
+ sal_Bool bAutoUpdate = rSlot.IsMode(SFX_SLOT_AUTOUPDATE);
+ SFX_REQUEST_ARG(rReq, pOrigItem, SfxExecuteItem, SID_SUBREQUEST, sal_False);
+ SfxExecuteItem *pExecuteItem = pOrigItem
+ ? (SfxExecuteItem*)pOrigItem->Clone()
+ : 0;
+
+ // ggf. TabPage-ID setzen und SID merken
+ SfxAppData_Impl *pAppData = pSfxApp->Get_Impl();
+ SFX_REQUEST_ARG(rReq, pTabPageItem, SfxUInt16Item, SID_TABPAGE, sal_False);
+ if ( pTabPageItem )
+ {
+ pAppData->nAutoTabPageId = pTabPageItem->GetValue();
+ rReq.RemoveItem( SID_TABPAGE ); // sonst ArgCount > 0 => Seiteneff.
+ }
+ pAppData->nExecutingSID = rReq.GetSlot();
+
+ // API-Call-Klammerung und Document-Lock w"ahrend des Calls
+ {
+ // 'this' mu\s im Dtor bescheid sagen
+ sal_Bool bThisDispatcherAlive = sal_True;
+ sal_Bool *pOldInCallAliveFlag = pImp->pInCallAliveFlag;
+ pImp->pInCallAliveFlag = &bThisDispatcherAlive;
+
+ // eigentlichen Call durchf"uhren
+ sal_Bool bDone = sal_False;
+/*
+ SfxViewFrame *pViewFrame = GetFrame();
+ if ( pViewFrame )
+ {
+ SFX_REQUEST_ARG(rReq, pInterceptorItem, SfxBoolItem, SID_INTERCEPTOR, sal_False);
+ ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProviderInterceptor > xProv( pViewFrame->GetFrame()->GetInterceptor_Impl() );
+ sal_Bool bDirect = ( pInterceptorItem != 0 );
+ if ( bDirect )
+ {
+ bDirect = !pInterceptorItem->GetValue();
+ rReq.RemoveItem( SID_INTERCEPTOR );
+ }
+
+ if ( xProv.is() && !bDirect )
+ {
+ bDone = sal_True;
+ ::com::sun::star::util::URL aURL;
+ String aName( rSlot.GetUnoName() );
+ String aCmd;
+ if ( aName.getLength() )
+ {
+ aCmd = ".uno:";
+ aCmd += aName;
+ }
+ else
+ {
+ aCmd = "slot:";
+ aCmd += rSlot.GetSlotId();
+ }
+
+ aURL.Complete = S2U( aCmd );
+ SfxURLTransformer aTrans;
+ aTrans.parseStrict( aURL );
+ ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > xDisp = xProv->queryDispatch( aURL, "", 0 );
+ if ( xDisp.is() )
+ {
+// automatisch auskommentiert - [getImplementation] - Wird von OWeakObject nicht weiter untersttzt!
+// void* pDisp = xDisp->getImplementation( ::getCppuType((const SfxOfficeDispatch*)0) );
+
+ if ( pDisp)
+ bDone = sal_False;
+ else
+ {
+ ::com::sun::star::uno::Sequence <PropertyValue> aSequ;
+ if ( rReq.GetArgs() )
+ TransformItems( rSlot.GetSlotId(), *rReq.GetArgs(), aSequ, &rSlot );
+ xDisp->dispatch( aURL, aSequ );
+ }
+ }
+ }
+ }
+*/
+ if ( !bDone )
+ {
+ // Bei neuen/komplizierten Funktionen den HelpAgent feuern...
+ Help* pHelp = Application::GetHelp();
+ if ( pHelp )
+ ((SfxHelp_Impl*)pHelp)->SlotExecutedOrFocusChanged( rReq.GetSlot(), sal_True, pSfxApp->GetOptions().IsAutoHelpAgent() );
+
+ SfxExecFunc pFunc = rSlot.GetExecFnc();
+ rShell.CallExec( pFunc, rReq );
+ }
+
+ // falls 'this' noch lebt
+ if ( bThisDispatcherAlive )
+ pImp->pInCallAliveFlag = pOldInCallAliveFlag;
+ else if ( pOldInCallAliveFlag )
+ // auch verschachtelte Stack-Frames sch"utzen
+ *pOldInCallAliveFlag = sal_False;
+ }
+
+ // TabPage-ID und Executing-SID zurueck setzen
+ if ( pTabPageItem )
+ pAppData->nAutoTabPageId = 0;
+ pAppData->nExecutingSID = 0;
+
+#if modal_mode_sinnlos
+ // ggf. Lock wieder freigeben
+ if ( bLockBindings )
+ pBindings->DLEAVEREGISTRATIONS();
+#endif
+
+ if( pExecuteItem )
+ {
+ Execute( *pExecuteItem );
+ delete pExecuteItem;
+ }
+
+ if ( rReq.IsDone() )
+ {
+ // bei AutoUpdate sofort updaten; "Pseudoslots" d"urfen nicht
+ // Autoupdate sein!
+ if ( bAutoUpdate )
+ {
+ const SfxSlot* pSlave = rSlot.GetLinkedSlot();
+ if (pSlave)
+ {
+ // bei Enum-Slots irgendeinen gebundenen Slave-Slot nehmen
+ while (!pBindings->IsBound(pSlave->GetSlotId()) && pSlave != &rSlot )
+ pSlave = pSlave->GetLinkedSlot();
+ pBindings->Invalidate(pSlave->GetSlotId());
+ pBindings->Update(pSlave->GetSlotId());
+ }
+ else
+ {
+ pBindings->Invalidate(rSlot.GetSlotId());
+ pBindings->Update(rSlot.GetSlotId());
+ }
+ }
+ return sal_True;
+ }
+ }
+
+ return sal_False;
+}
+
+//====================================================================
+void SfxDispatcher::Construct_Impl( SfxDispatcher* pParent )
+{
+ pImp = new SfxDispatcher_Impl;
+ bFlushed = sal_True;
+ SfxApplication *pSfxApp = SFX_APP();
+
+ pImp->pCachedServ1 = 0;
+ pImp->pCachedServ2 = 0;
+ pImp->bFlushing = sal_False;
+ pImp->bUpdated = sal_False;
+ pImp->bLocked = sal_False;
+ pImp->bActive = sal_False;
+ pImp->pParent = NULL;
+ pImp->bUILocked = sal_False;
+ pImp->bNoUI = sal_False;
+ pImp->bReadOnly = sal_False;
+ pImp->bQuiet = sal_False;
+ pImp->bModal = sal_False;
+ pImp->pInCallAliveFlag = 0;
+ pImp->bFilterEnabling = sal_False;
+ pImp->nFilterCount = 0;
+ pImp->pFilterSIDs = 0;
+ pImp->nStandardMode = 0;
+ pImp->pDisableList = pSfxApp->GetDisabledSlotList_Impl();
+ pImp->nDisableFlags = 0;
+
+ pImp->pParent = pParent;
+
+ pImp->bInvalidateOnUnlock = sal_False;
+ pImp->nActionLevel = 0;
+
+ for (sal_uInt16 n=0; n<SFX_OBJECTBAR_MAX; n++)
+ pImp->aObjBars[n].aResId = ResId( 0,0 );
+
+ GenLink aGenLink( LINK(this, SfxDispatcher, PostMsgHandler) );
+
+ pImp->xPoster = new SfxHintPoster(aGenLink);
+
+ pImp->aTimer.SetTimeout(SFX_FLUSH_TIMEOUT);
+ pImp->aTimer.SetTimeoutHdl( LINK(this, SfxDispatcher, EventHdl_Impl ) );
+}
+
+SfxDispatcher::SfxDispatcher( SfxDispatcher* pParent )
+{
+ Construct_Impl( pParent );
+ pImp->pFrame = 0;
+}
+
+SfxDispatcher::SfxDispatcher( SfxViewFrame *pViewFrame )
+
+/* [Beschreibung]
+
+ Der Konstruktor der Klasse SfxDispatcher legt einen leeren Stack
+ von <SfxShell>-Pointern an. Er ist initial nicht gelockt und gilt als
+ geflusht.
+*/
+
+{
+ if ( pViewFrame )
+ {
+ SfxViewFrame *pFrame = pViewFrame->GetParentViewFrame();
+ if ( pFrame )
+ Construct_Impl( pFrame->GetDispatcher() );
+ else
+ Construct_Impl( 0 );
+ }
+ else
+ Construct_Impl( 0 );
+ pImp->pFrame = pViewFrame;
+}
+
+//====================================================================
+SfxDispatcher::~SfxDispatcher()
+
+/* [Beschreibung]
+
+ Der Destruktor der Klasse SfxDispatcher darf nicht gerufen werden,
+ wenn die SfxDispatcher-Instanz aktiv ist. Es d"urfen sich allerdings
+ noch <SfxShell>-Pointer auf dem Stack befinden.
+*/
+
+{
+#ifdef DBG_UTIL
+ ByteString sTemp( "Delete Dispatcher " );
+ sTemp += ByteString::CreateFromInt32( (sal_uInt32)this );
+ DBG_TRACE( sTemp.GetBuffer() );
+ DBG_ASSERT( !pImp->bActive, "deleting active Dispatcher" );
+#endif
+
+ // Damit in LeaveRegistrations kein Timer per Reschedule in PlugComm
+ // zuschlaegt
+ pImp->aTimer.Stop();
+ pImp->xPoster->SetEventHdl( Link() );
+
+ // die Stack-Varialblem in Call_Impl benachrichtigen
+ if ( pImp->pInCallAliveFlag )
+ *pImp->pInCallAliveFlag = sal_False;
+
+ // Bindings und App besorgen
+ SfxApplication *pSfxApp = SFX_APP();
+ SfxBindings* pBindings = GetBindings();
+
+// if (pImp->nEventId)
+// pSfxApp->RemoveEventHdl(pImp->nEventId);
+
+ // wenn noch nicht flushed, die Bindings wiederbeleben
+ if ( pBindings && !pSfxApp->IsDowning() && !bFlushed )
+ pBindings->DLEAVEREGISTRATIONS();
+
+ // ggf. bei den Bindings abmelden
+ while ( pBindings )
+ {
+ if ( pBindings->GetDispatcher_Impl() == this)
+ pBindings->SetDispatcher(0);
+ pBindings = pBindings->GetSubBindings_Impl();
+ }
+
+ delete pImp;
+}
+
+//====================================================================
+void SfxDispatcher::Pop
+(
+ SfxShell& rShell, /* Die vom Stack zu nehmende SfxShell-Instanz. */
+
+ sal_uInt16 nMode /* SFX_SHELL_POP_UNTIL
+ Es werden auch alle "uber 'rShell' liegenenden
+ SfxShell's vom Stack genommen.
+
+ SFX_SHELL_POP_DELETE
+ Alle tats"achlich vom Stack genommenen
+ SfxShells werden gel"oscht.
+
+ SFX_SHELL_PUSH (InPlace use only)
+ Die Shell wird gepusht. */
+)
+/* [Beschreibung]
+
+ Mit dieser Methode wird eine oder mehrere <SfxShell> vom SfxDispatcher
+ gepoppt. Die SfxShell wird zun"achst zum poppen vermerkt und
+ es wird ein Timer aufgesetzt. Erst bei Ablauf des Timers wird
+ tats"achlich gepoppt (<SfxDispatcher::Flush()>) und die <SfxBindings>
+ werden invalidiert. W"ahrend der Timer l"auft gleichen sich
+ entgegengesetzte Push und Pop Befehle mit derselben SfxShell aus.
+*/
+
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( rShell.GetInterface(),
+ "pushing SfxShell without previous RegisterInterface()" );
+ DBG_ASSERT( pImp->nActionLevel == 0, "Push or Pop within Action" );
+// DBG_ASSERT( SFX_APP()->IsInAsynchronCall_Impl(),
+// "Dispatcher Push/Pop in synchron-call-stack" );
+
+ FASTBOOL bDelete = (nMode & SFX_SHELL_POP_DELETE) == SFX_SHELL_POP_DELETE;
+ FASTBOOL bUntil = (nMode & SFX_SHELL_POP_UNTIL) == SFX_SHELL_POP_UNTIL;
+ FASTBOOL bPush = (nMode & SFX_SHELL_PUSH) == SFX_SHELL_PUSH;
+
+ SfxApplication *pSfxApp = SFX_APP();
+
+#ifdef DBG_UTIL
+ ByteString aMsg( "SfxDispatcher(" );
+ aMsg += ByteString::CreateFromInt32( (long) this );
+ aMsg += bPush ? ")::Push(" : ")::Pop(";
+ if ( rShell.GetInterface() )
+ aMsg += rShell.GetInterface()->GetClassName();
+ else
+ aMsg += ByteString::CreateFromInt32( (long) &rShell );
+ aMsg += bDelete ? ") with delete" : ")";
+ DbgTrace( aMsg.GetBuffer() );
+#endif
+
+ // gleiche Shell wie on-Top des ToDo-Stacks?
+ if ( pImp->aToDoStack.Count() && pImp->aToDoStack.Top().pCluster == &rShell )
+ {
+ // inverse Actions heben sich auf
+ if ( pImp->aToDoStack.Top().bPush != bPush )
+ pImp->aToDoStack.Pop();
+ else
+ {
+ DBG_ASSERT( bPush, "SfxInterface pushed more than once" );
+ DBG_ASSERT( !bPush, "SfxInterface popped more than once" );
+ }
+ }
+ else
+ {
+ // ::com::sun::star::chaos::Action merken
+ pImp->aToDoStack.Push( SfxToDo_Impl(bPush, bDelete, bUntil, rShell) );
+ if ( bFlushed )
+ {
+ bFlushed = sal_False;
+ pImp->bUpdated = sal_False;
+
+ // Bindings schlafen legen
+ SfxBindings* pBindings = GetBindings();
+ if ( pBindings )
+ pBindings->DENTERREGISTRATIONS();
+ }
+ }
+
+ if ( !pSfxApp->IsDowning() && pImp->aToDoStack.Count() )
+ {
+ //! if (SFX_APP()->AnyInput(INPUT_KEYBOARD | INPUT_MOUSE) )
+ //! AnyInput haut nicht hin; hier muss noch ein Kriterium gefunden
+ //! werden. Solange wieder immer mit Timer.
+
+ if (sal_True)
+ {
+ // Kein sofortiges Update gewuenscht
+ pImp->aTimer.SetTimeout(SFX_FLUSH_TIMEOUT);
+ pImp->aTimer.SetTimeoutHdl( LINK(this, SfxDispatcher, EventHdl_Impl ) );
+ pImp->aTimer.Start();
+ }
+ else
+ {
+ // Schnellstmoegliches Update (sollte Normalfall sein)
+ pImp->aTimer.Stop();
+ GetpApp()->PostUserEvent(pImp->nEventId, (void*)0);
+ }
+ }
+ else
+ {
+ // doch nichts zu tun
+ pImp->aTimer.Stop();
+
+ // ggf. Bindings wieder aufwecken
+ if ( !pImp->aToDoStack.Count() )
+ {
+ SfxBindings* pBindings = GetBindings();
+ if ( pBindings )
+ pBindings->DLEAVEREGISTRATIONS();
+ }
+ }
+}
+
+//--------------------------------------------------------------------
+
+IMPL_LINK_INLINE_START( SfxDispatcher, EventHdl_Impl, void *, pvoid )
+
+/* [Beschreibung]
+
+ Dieser Handler wird nach <SfxDispatcher::Invalidate()> oder Bewegungen
+ auf dem Stack (<SfxDispatcher::Push()> und <SfxDispatcher::Pop()) gerufen.
+
+ Er flusht den Stack, falls er dirty ist, f"uhrt also die ausstehenden
+ Push und Pop Befehle tats"achlich aus.
+*/
+
+{
+ DBG_MEMTEST();
+
+ Flush();
+ Update_Impl();
+ SfxBindings* pBindings = GetBindings();
+ if ( pBindings )
+ pBindings->StartUpdate_Impl(sal_False);
+ return 0;
+}
+IMPL_LINK_INLINE_END( SfxDispatcher, EventHdl_Impl, void *, pvoid )
+
+//--------------------------------------------------------------------
+sal_Bool SfxDispatcher::CheckVirtualStack( const SfxShell& rShell, sal_Bool bDeep )
+
+/* [Beschreibung]
+
+ Mit dieser Methode kann gepr"uft werden, ob sich die <SfxShell> rShell
+ auf dem Stack befindet, wenn er geflusht w"are. Dabei wird der
+ SfxDispatcher jedoch nicht tats"achlich geflusht.
+
+ Diese Methode ist u.a. dazu gedacht, Assertions zu erm"oglichen, ohne
+ als Seiteneffekt den SfxDispathcer flushen zu m"ussen.
+*/
+
+{
+ DBG_MEMTEST();
+ SFX_STACK(SfxDispatcher::CheckVirtualStack);
+
+ SfxShellStack_Impl aStack( pImp->aStack );
+ for ( short nToDo = pImp->aToDoStack.Count()-1; nToDo >= 0; --nToDo )
+ {
+ SfxToDo_Impl aToDo( pImp->aToDoStack.Top(nToDo) );
+ if ( aToDo.bPush )
+ aStack.Push( (SfxShell*) aToDo.pCluster );
+ else
+ {
+ SfxShell* pPopped = 0;
+ do
+ {
+ DBG_ASSERT( aStack.Count(), "popping from empty stack" );
+ pPopped = aStack.Pop();
+ }
+ while ( aToDo.bUntil && pPopped != aToDo.pCluster );
+ DBG_ASSERT( pPopped == aToDo.pCluster, "popping unpushed SfxInterface" );
+ }
+ }
+
+ sal_Bool bReturn;
+ if ( bDeep )
+ bReturn = aStack.Contains(&rShell);
+ else
+ bReturn = aStack.Top() == &rShell;
+ return bReturn;
+}
+
+//--------------------------------------------------------------------
+sal_uInt16 SfxDispatcher::GetShellLevel( const SfxShell& rShell )
+
+/* [Beschreibung]
+
+ Ermittelt die Position einer SfxShell im Stack des Dispatchers.
+ Dazu wird dieser ggf. zuvor geflusht.
+
+
+ [Rckgabewert]
+
+ sal_uInt16 == USRT_MAX
+ Die SfxShell befindet sich nicht auf
+ diesem SfxDispatcher.
+
+ < USHRT_MAX
+ Position der SfxShell auf dem Dispatcher
+ von oben mit 0 beginnend gez"ahlt.
+*/
+
+{
+ DBG_MEMTEST();
+ SFX_STACK(SfxDispatcher::GetShellLevel);
+ Flush();
+
+ for ( sal_uInt16 n = 0; n < pImp->aStack.Count(); ++n )
+ if ( pImp->aStack.Top( n ) == &rShell )
+ return n;
+ if ( pImp->pParent )
+ {
+ sal_uInt16 nRet = pImp->pParent->GetShellLevel(rShell);
+ if ( nRet == USHRT_MAX )
+ return nRet;
+ return nRet + pImp->aStack.Count();
+ }
+
+ return USHRT_MAX;
+}
+
+//--------------------------------------------------------------------
+SfxShell *SfxDispatcher::GetShell(sal_uInt16 nIdx) const
+
+/* [Beschreibung]
+
+ Liefert einen Pointer auf die <SfxShell>, welche sich an der Position
+ nIdx (von oben, letzt-gepushte liegt bei 0) auf dem Stack befindet.
+
+ Dabei wird der SfxDispatcher nicht geflusht.
+
+ Ist der Stack nicht tief genug, wird ein 0-Pointer zur"uckgegeben.
+*/
+
+{
+ DBG_MEMTEST();
+
+ sal_uInt16 nShellCount = pImp->aStack.Count();
+ if ( nIdx < nShellCount )
+ return pImp->aStack.Top(nIdx);
+ else if ( pImp->pParent )
+ return pImp->pParent->GetShell( nIdx - nShellCount );
+ return 0;
+}
+
+//--------------------------------------------------------------------
+SfxBindings* SfxDispatcher::GetBindings() const
+
+/* [Beschreibung]
+
+ Diese Methode liefert einen Pointer auf die <SfxBindings> Instanz
+ zur"uck, an die der SfxDispatcher gerade gebunden ist. Ein SfxDispatcher
+ ist nur dann an SfxBindings gebunden, wenn er <UI-aktiv> ist. Ist
+ er nicht UI-aktiv, wird ein 0-Pointer zur"uckgegeben.
+
+ Der zur"uckgegebene Pointer ist nur im <unmittelbaren Kontext> des
+ Methodenaufrufs g"ultig.
+*/
+
+{
+ if ( pImp->pFrame )
+ return &pImp->pFrame->GetBindings();
+ else
+ return NULL;
+}
+
+//--------------------------------------------------------------------
+SfxViewFrame* SfxDispatcher::GetFrame() const
+
+/* [Beschreibung]
+
+ Liefert einen Pointer auf die <SfxViewFrame> Instanz, der dieser
+ SfxDispatcher geh"ort. Falls es sich um den Applikations-Dispatcher
+ handelt, wird ein 0-Pointer zur"uckgegeben.
+*/
+
+{
+ DBG_MEMTEST();
+ return pImp->pFrame;
+}
+
+//--------------------------------------------------------------------
+void SfxDispatcher::DoActivate_Impl( sal_Bool bMDI )
+
+/* [Beschreibung]
+
+ Diese Methode steuert das Aktivieren eines Dispatchers.
+
+ Da der Applikations-Dispatcher immer aktiv ist, entweder als
+ Unterdispatcher des <SfxViewFrame>-Dispatchers oder selbst, wird
+ er nie als ganzes Aktiviert, sondern nur seine einzelnen <SfxShell>s
+ bei <SfxDispatcher::Push(SfxShell&)>.
+
+ Beim Aktivieren eines SfxDispatchers wird an allen auf seinem
+ Stack befindlichen SfxShells, beginnend mit der untersten, der Handler
+ <SfxShell::Activate(sal_Bool)> gerufen.
+*/
+
+{
+ DBG_MEMTEST();
+ SFX_STACK(SfxDispatcher::DoActivate);
+ if ( bMDI )
+ {
+ #ifdef DBG_UTIL
+ ByteString sTemp("Activate Dispatcher ");
+ sTemp += ByteString::CreateFromInt32( (sal_uInt32) this );
+ DBG_TRACE(sTemp.GetBuffer());
+ DBG_ASSERT( !pImp->bActive, "Activate-Fehler" );
+ #endif
+ pImp->bActive = sal_True;
+ pImp->bUpdated = sal_False;
+ SfxBindings* pBindings = GetBindings();
+ if ( pBindings )
+ {
+ pBindings->SetDispatcher(this);
+ pBindings->SetActiveFrame( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > () );
+ }
+ }
+ else
+ {
+ #ifdef DBG_UTIL
+ ByteString sTemp("Non-MDI-Activate Dispatcher");
+ sTemp += ByteString::CreateFromInt32( (sal_uInt32) this );
+ DBG_TRACE( sTemp.GetBuffer() );
+ #endif
+ }
+
+ if ( IsAppDispatcher() )
+ return;
+
+ for ( int i = int(pImp->aStack.Count()) - 1; i >= 0; --i )
+ pImp->aStack.Top( (sal_uInt16) i )->DoActivate(pImp->pFrame, bMDI);
+
+ if ( pImp->aToDoStack.Count() )
+ {
+ if (sal_True)
+ {
+ // Kein sofortiges Update gewuenscht
+ pImp->aTimer.SetTimeout(SFX_FLUSH_TIMEOUT);
+ pImp->aTimer.SetTimeoutHdl( LINK(this, SfxDispatcher, EventHdl_Impl ) );
+ pImp->aTimer.Start();
+ }
+ else
+ {
+ // Schnellstmoegliches Update (sollte Normalfall sein)
+ pImp->aTimer.Stop();
+ GetpApp()->PostUserEvent(pImp->nEventId, (void*)0);
+ }
+ }
+}
+
+void SfxDispatcher::DoParentActivate_Impl()
+{
+ for ( int i = int(pImp->aStack.Count()) - 1; i >= 0; --i )
+ pImp->aStack.Top( (sal_uInt16) i )->ParentActivate();
+}
+
+//--------------------------------------------------------------------
+void SfxDispatcher::DoDeactivate_Impl( sal_Bool bMDI )
+
+/* [Beschreibung]
+
+ Diese Methode steuert das Deaktivieren eines Dispatchers.
+
+ Da der Applikations-Dispatcher immer aktiv ist, entweder als
+ Unterdispatcher des <SfxViewFrame>-Dispatchers oder selbst, wird
+ er nie als ganzes Deaktiviert, sondern nur seine einzelnen <SfxShell>s
+ bei <SfxDispatcher::Pop(SfxShell&)>.
+
+ Beim Deaktivieren eines SfxDispatchers wird an allen auf seinem
+ Stack befindlichen SfxShells, beginnend mit der obersten, der Handler
+ <SfxShell::Deactivate(sal_Bool)> gerufen.
+*/
+
+{
+ DBG_MEMTEST();
+ SFX_STACK(SfxDispatcher::DoDeactivate);
+
+ SfxApplication *pSfxApp = SFX_APP();
+
+ if ( bMDI )
+ {
+ DBG_TRACE(ByteString("Deactivate Dispatcher ").Append(ByteString::CreateFromInt32( (sal_uInt32) this )).GetBuffer());
+ DBG_ASSERT( pImp->bActive, "Deactivate-Fehler" );
+ pImp->bActive = sal_False;
+
+ if ( pImp->pFrame && !pImp->pFrame->IsA(TYPE(SfxInPlaceFrame)) )
+ {
+ SfxWorkWindow *pWorkWin = pSfxApp->GetWorkWindow_Impl(pImp->pFrame);
+ for (sal_uInt16 n=0; n<pImp->aChildWins.Count();)
+ {
+ SfxChildWindow *pWin =
+ pWorkWin->GetChildWindow_Impl(
+ (sal_uInt16) ( pImp->aChildWins[n] & 0xFFFF ) );
+ if (!pWin || pWin && pWin->GetAlignment() == SFX_ALIGN_NOALIGNMENT)
+ pImp->aChildWins.Remove(n);
+ else
+ n++;
+ }
+ }
+ }
+ else
+ DBG_TRACE( ByteString ("Non-MDI-DeActivate Dispatcher").Append(ByteString::CreateFromInt32( (sal_uInt32) this )).GetBuffer() );
+
+ if ( IsAppDispatcher() && !pSfxApp->IsDowning() )
+ return;
+
+ for ( sal_uInt16 i = 0; i < pImp->aStack.Count(); ++i )
+ pImp->aStack.Top(i)->DoDeactivate(pImp->pFrame, bMDI);
+
+ Flush();
+}
+
+void SfxDispatcher::DoParentDeactivate_Impl()
+{
+ for ( int i = int(pImp->aStack.Count()) - 1; i >= 0; --i )
+ pImp->aStack.Top( (sal_uInt16) i )->ParentDeactivate();
+}
+
+//--------------------------------------------------------------------
+int SfxDispatcher::GetShellAndSlot_Impl
+(
+ sal_uInt16 nSlot, // die zu suchende Slot-Id
+ SfxShell** ppShell, // die SfxShell, welche nSlot z.Zt. bedient
+ const SfxSlot** ppSlot, // der SfxSlot, welcher nSlot z.Zt. bedient
+ sal_Bool bOwnShellsOnly,
+ sal_Bool bModal // trotz ModalMode
+)
+
+/* [Beschreibung]
+
+ Diese Methode sucht im SfxDispatcher nach der <SfxShell>, von der
+ die Slot-Id nSlot zur Zeit bedient wird. Dazu wird der Dispatcher
+ zuvor geflusht.
+
+
+ [R"uckgabewert]
+
+ int sal_True
+ Die SfxShell wurde gefunden, ppShell und ppSlot
+ sind g"ultig.
+
+ sal_True
+ Die SfxShell wurde nicht gefunden, ppShell und ppSlot
+ sind ung"ultig.
+*/
+
+{
+ SFX_STACK(SfxDispatcher::GetShellAndSlot_Impl);
+
+ Flush();
+ SfxSlotServer aSvr;
+ if ( _FindServer(nSlot, aSvr, bModal) )
+ {
+ if ( bOwnShellsOnly && aSvr.GetShellLevel() >= pImp->aStack.Count() )
+ return sal_False;
+
+ *ppShell = GetShell(aSvr.GetShellLevel());
+ *ppSlot = aSvr.GetSlot();
+ if ( 0 == (*ppSlot)->GetExecFnc() )
+ *ppSlot = (*ppShell)->GetInterface()->GetRealSlot(*ppSlot);
+
+#ifdef DBG_UTILx
+ ByteString aMsg( nSlot );
+ aMsg += " found in ";
+ aMsg += (*ppShell)->GetInterface()->GetClassName();
+ DbgTrace( aMsg.GetBuffer() );
+#endif
+
+ return sal_True;
+ }
+
+#ifdef DBG_UTILx
+ ByteString aMsg( nSlot );
+ aMsg += " not found";
+ DbgTrace( aMsg.GetBuffer() );
+#endif
+
+ return sal_False;
+}
+
+/*
+struct Executer : public SfxHint
+{
+ SfxRequest *pRequest;
+ const SfxSlot* pSlot;
+ sal_uInt16 nLevel;
+
+ Executer( SfxRequest* pReq, const SfxSlot* p, sal_uInt16 n )
+ : pRequest( pReq )
+ , pSlot(p)
+ , nLevel(n)
+ {}
+ ~Executer()
+ {delete pRequest;}
+};
+*/
+
+//--------------------------------------------------------------------
+void SfxDispatcher::_Execute
+(
+ SfxShell& rShell, // zu rufende <SfxShell>
+ const SfxSlot& rSlot, // zu rufender <SfxSlot>
+ SfxRequest& rReq, // auszuf"uhrende Funktion (Id und optional Parameter)
+ SfxCallMode eCallMode // synchron, asynchron oder wie beim Slot angegeben
+)
+
+/* [Beschreibung]
+
+ Diese Methode f"uhrt einen Request "uber einen gecachten <Slot-Server>
+ aus.
+*/
+
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( !pImp->bFlushing, "recursive call to dispatcher" );
+ DBG_ASSERT( !pImp->aToDoStack.Count(), "unprepared InPlace _Execute" );
+
+ if ( IsLocked( rSlot.GetSlotId() ) )
+ return;
+
+ sal_uInt16 nSlot = rSlot.GetSlotId();
+ if ( SfxMacroConfig::IsMacroSlot( nSlot ) )
+ SFX_APP()->GetMacroConfig()->RegisterSlotId( nSlot );
+
+ if ( (eCallMode & SFX_CALLMODE_ASYNCHRON) ||
+ ( !(eCallMode & SFX_CALLMODE_SYNCHRON) &&
+ rSlot.IsMode(SFX_SLOT_ASYNCHRON) ) )
+ {
+ SfxDispatcher *pDispat = this;
+ while ( pDispat )
+ {
+ sal_uInt16 nShellCount = pDispat->pImp->aStack.Count();
+ for ( sal_uInt16 n=0; n<nShellCount; n++ )
+ {
+ if ( &rShell == pDispat->pImp->aStack.Top(n) )
+ {
+ pDispat->pImp->xPoster->Post(new SfxRequest(rReq));
+// pDispat->pImp->xPoster->Post(new Executer(new SfxRequest(rReq), &rSlot, n ));
+ return;
+ }
+ }
+
+ pDispat = pDispat->pImp->pParent;
+ }
+ }
+ else
+ Call_Impl( rShell, rSlot, rReq, SFX_CALLMODE_RECORD==(eCallMode&SFX_CALLMODE_RECORD) );
+}
+
+//--------------------------------------------------------------------
+void MappedPut_Impl( SfxAllItemSet &rSet, const SfxPoolItem &rItem )
+
+/* [Beschreibung]
+
+ Hilfsfunktion zum putten von rItem unter der im Pool des Item-Sets
+ rSet geltenden Which-Id.
+*/
+
+{
+ // mit ggf. gemappter Which-Id putten
+ const SfxItemPool *pPool = rSet.GetPool();
+ sal_uInt16 nWhich = rItem.Which();
+#ifdef TF_POOLABLE
+ if ( pPool->IsSlot(nWhich) )
+#else
+ if ( pPool->HasMap() && pPool->IsSlot(nWhich) )
+#endif
+ nWhich = pPool->GetWhich(nWhich);
+ rSet.Put( rItem, nWhich );
+}
+
+//--------------------------------------------------------------------
+
+#ifndef SFX_USE_BINDINGS
+#define SFX_USE_BINDINGS 0x8000
+#endif
+
+sal_uInt16 SfxDispatcher::ExecuteFunction( sal_uInt16 nSlot, SfxPoolItem **pArgs,
+ sal_uInt16 nMode )
+{
+ if ( !nMode )
+ nMode = pImp->nStandardMode;
+
+ // via Bindings/Interceptor? (dann ist der Returnwert nicht exakt)
+ sal_Bool bViaBindings = SFX_USE_BINDINGS == ( nMode & SFX_USE_BINDINGS );
+ nMode &= ~sal_uInt16(SFX_USE_BINDINGS);
+ if ( bViaBindings && GetBindings() )
+ return GetBindings()->Execute( nSlot, (const SfxPoolItem **) pArgs, nMode )
+ ? EXECUTE_POSSIBLE
+ : EXECUTE_NO;
+
+ // sonst via Dispatcher
+ if ( IsLocked(nSlot) )
+ return 0;
+ SfxShell *pShell = 0;
+ SfxCallMode eCall = SFX_CALLMODE_SYNCHRON;
+ sal_uInt16 nRet = EXECUTE_NO;
+ const SfxSlot *pSlot = 0;
+ if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, sal_False, sal_False ) )
+ {
+ // Ausf"uhrbarkeit vorher testen
+ if ( pSlot->IsMode( SFX_SLOT_FASTCALL ) ||
+ pShell->CanExecuteSlot_Impl( *pSlot ) )
+ nRet = EXECUTE_POSSIBLE;
+
+ if ( nMode == EXECUTEMODE_ASYNCHRON )
+ eCall = SFX_CALLMODE_ASYNCHRON;
+ else if ( nMode == EXECUTEMODE_DIALOGASYNCHRON && pSlot->IsMode( SFX_SLOT_HASDIALOG ) )
+ eCall = SFX_CALLMODE_ASYNCHRON;
+ else if ( pSlot->GetMode() & SFX_SLOT_ASYNCHRON )
+ eCall = SFX_CALLMODE_ASYNCHRON;
+ sal_Bool bDone = sal_False;
+ if ( pArgs && *pArgs )
+ {
+ SfxAllItemSet aSet( pShell->GetPool() );
+ for ( SfxPoolItem **pArg = pArgs; *pArg; ++pArg )
+ MappedPut_Impl( aSet, **pArg );
+ SfxRequest aReq( nSlot, eCall, aSet );
+ _Execute( *pShell, *pSlot, aReq, eCall );
+ bDone = aReq.IsDone();
+ }
+ else
+ {
+ SfxRequest aReq( nSlot, eCall, pShell->GetPool() );
+ _Execute( *pShell, *pSlot, aReq, eCall );
+ bDone = aReq.IsDone();
+ }
+ }
+
+ return nRet;
+}
+
+sal_uInt16 SfxDispatcher::GetSlotId( const String& rCommand )
+{
+ // Anzahl der Shells auf den verkettenten Dispatchern z"ahlen
+ Flush();
+ sal_uInt16 nTotCount = pImp->aStack.Count();
+ if ( pImp->pParent )
+ {
+ SfxDispatcher *pParent = pImp->pParent;
+ while ( pParent )
+ {
+ nTotCount += pParent->pImp->aStack.Count();
+ pParent = pParent->pImp->pParent;
+ }
+ }
+
+ const SfxSlot *pSlot=NULL;
+ sal_uInt16 nFirstShell = 0;
+ for ( sal_uInt16 i = nFirstShell; i < nTotCount; ++i )
+ {
+ SfxShell *pObjShell = GetShell(i);
+ SfxInterface *pIFace = pObjShell->GetInterface();
+ pSlot = pIFace->GetSlot( rCommand );
+ if ( pSlot )
+ return pSlot->GetSlotId();
+ }
+
+ return 0;
+}
+
+//--------------------------------------------------------------------
+int SfxExecuteItem::operator==( const SfxPoolItem& rItem ) const
+{
+ SfxExecuteItem& rArg = (SfxExecuteItem& )rItem;
+ sal_uInt16 nCount = Count();
+ if( nCount != rArg.Count() )
+ return sal_False;
+ while( nCount -- )
+ if( *GetObject( nCount ) != *rArg.GetObject( nCount ) )
+ return sal_False;
+ return eCall == rArg.eCall;
+}
+
+//--------------------------------------------------------------------
+SfxPoolItem* SfxExecuteItem::Clone( SfxItemPool* pPool ) const
+{
+ return new SfxExecuteItem( *this );
+}
+
+//--------------------------------------------------------------------
+SfxExecuteItem::SfxExecuteItem( const SfxExecuteItem& rArg )
+ : SfxPoolItem( rArg ), nModifier( 0 )
+{
+ eCall = rArg.eCall;
+ nSlot = rArg.nSlot;
+ sal_uInt16 nCount = rArg.Count();
+ for( sal_uInt16 nPos = 0; nPos < nCount; nPos++ )
+ Insert( rArg[ nPos ]->Clone(), nPos );
+}
+
+//--------------------------------------------------------------------
+SfxExecuteItem::SfxExecuteItem(
+ sal_uInt16 nWhich, sal_uInt16 nSlotP, SfxCallMode eModeP,
+ const SfxPoolItem* pArg1, ... ) :
+ SfxPoolItem( nWhich ), eCall( eModeP ), nSlot( nSlotP ), nModifier( 0 )
+{
+ va_list pVarArgs;
+ va_start( pVarArgs, pArg1 );
+ for ( const SfxPoolItem *pArg = pArg1; pArg;
+ pArg = va_arg( pVarArgs, const SfxPoolItem* ) )
+ Insert( pArg->Clone(), Count() );
+ va_end(pVarArgs);
+}
+
+//--------------------------------------------------------------------
+SfxExecuteItem::SfxExecuteItem(
+ sal_uInt16 nWhich, sal_uInt16 nSlotP, SfxCallMode eModeP )
+ : SfxPoolItem( nWhich ), nSlot( nSlotP ), eCall( eModeP ), nModifier( 0 )
+{
+}
+
+//--------------------------------------------------------------------
+const SfxPoolItem* SfxDispatcher::Execute( const SfxExecuteItem& rItem )
+{
+ const SfxPoolItem** pPtr = new const SfxPoolItem*[ rItem.Count() + 1 ];
+ for( sal_uInt16 nPos = rItem.Count(); nPos--; )
+ pPtr[ nPos ] = rItem.GetObject( nPos );
+ pPtr[ rItem.Count() ] = 0;
+ const SfxPoolItem* pRet = Execute(
+ rItem.GetSlot(), rItem.GetCallMode(), pPtr, rItem.GetModifier() );
+
+ __DELETE(rItem.Count() + 1) (SfxPoolItem**)pPtr;
+
+ return pRet;
+}
+
+//--------------------------------------------------------------------
+const SfxPoolItem* SfxDispatcher::Execute
+(
+ sal_uInt16 nSlot, // die Id der auszufuehrenden Funktion
+ SfxCallMode eCall, // SFX_CALLMODE_SYNCRHON, ..._ASYNCHRON oder ..._SLOT
+ const SfxPoolItem **pArgs, // 0-terminiertes C-Array von Parametern
+ sal_uInt16 nModi,
+ const SfxPoolItem **pInternalArgs // 0-terminiertes C-Array von Parametern
+)
+
+/* [Beschreibung]
+
+ Methode zum Ausf"uhren eines <SfxSlot>s "uber die Slot-Id.
+
+
+ [R"uckgabewert]
+
+ const SfxPoolItem* Pointer auf ein bis zum n"achsten Durchlauf
+ der Message-Loop g"ultiges SfxPoolItem,
+ welches den R"uckgabewert enth"alt.
+
+ Oder ein 0-Pointer, wenn die Funktion nicht
+ ausgef"uhrt wurde (z.B. Abbruch durch den
+ Benutzer).
+*/
+
+{
+ if ( IsLocked(nSlot) )
+ return 0;
+
+ SfxShell *pShell = 0;
+ const SfxSlot *pSlot = 0;
+ if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, sal_False,
+ SFX_CALLMODE_MODAL==(eCall&SFX_CALLMODE_MODAL) ) )
+ {
+ SfxRequest* pReq;
+ if ( pArgs && *pArgs )
+ {
+ SfxAllItemSet aSet( pShell->GetPool() );
+ for ( const SfxPoolItem **pArg = pArgs; *pArg; ++pArg )
+ MappedPut_Impl( aSet, **pArg );
+ pReq = new SfxRequest( nSlot, eCall, aSet );
+ }
+ else
+ pReq = new SfxRequest( nSlot, eCall, pShell->GetPool() );
+ pReq->SetModifier( nModi );
+ if( pInternalArgs && *pInternalArgs)
+ {
+ SfxAllItemSet aSet( SFX_APP()->GetPool() );
+ for ( const SfxPoolItem **pArg = pInternalArgs; *pArg; ++pArg )
+ aSet.Put( **pArg );
+ pReq->SetInternalArgs_Impl( aSet );
+ }
+ _Execute( *pShell, *pSlot, *pReq, eCall );
+ const SfxPoolItem* pRet = pReq->GetReturnValue();
+ delete pReq; return pRet;
+ }
+ return 0;
+}
+
+//--------------------------------------------------------------------
+const SfxPoolItem* SfxDispatcher::Execute
+(
+ sal_uInt16 nSlot, // die Id der auszufuehrenden Funktion
+ SfxCallMode eCall, // SFX_CALLMODE_SYNCRHON, ..._ASYNCHRON oder ..._SLOT
+ const SfxItemSet &rArgs // <SfxItemSet> mit Parametern
+)
+
+/* [Beschreibung]
+
+ Methode zum Ausf"uhren eines <SfxSlot>s "uber die Slot-Id.
+
+
+ [R"uckgabewert]
+
+ const SfxPoolItem* Pointer auf ein bis zum n"achsten Durchlauf
+ der Message-Loop g"ultiges SfxPoolItem,
+ welches den R"uckgabewert enth"alt.
+
+ Oder ein 0-Pointer, wenn die Funktion nicht
+ ausgef"uhrt wurde (z.B. Abbruch durch den
+ Benutzer).
+*/
+
+{
+ if ( IsLocked(nSlot) )
+ return 0;
+
+ SfxShell *pShell = 0;
+ const SfxSlot *pSlot = 0;
+ if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, sal_False,
+ SFX_CALLMODE_MODAL==(eCall&SFX_CALLMODE_MODAL) ) )
+ {
+ SfxAllItemSet aSet( pShell->GetPool() );
+ SfxItemIter aIter(rArgs);
+ for ( const SfxPoolItem *pArg = aIter.FirstItem();
+ pArg;
+ pArg = aIter.NextItem() )
+ MappedPut_Impl( aSet, *pArg );
+ SfxRequest aReq( nSlot, eCall, aSet );
+ _Execute( *pShell, *pSlot, aReq, eCall );
+ return aReq.GetReturnValue();
+ }
+ return 0;
+}
+
+//--------------------------------------------------------------------
+const SfxPoolItem* SfxDispatcher::_Execute
+(
+ sal_uInt16 nSlot, // die Id der auszufuehrenden Funktion
+ SfxCallMode eCall, // SFX_CALLMODE_SYNCRHON, ..._ASYNCHRON oder ..._SLOT
+ va_list pVarArgs, // Parameterliste ab 2. Parameter
+ const SfxPoolItem* pArg1 // erster Parameter
+)
+
+/* [Beschreibung]
+
+ Methode zum Ausf"uhren eines <SfxSlot>s "uber die Slot-Id.
+
+
+ [R"uckgabewert]
+
+ const SfxPoolItem* Pointer auf ein bis zum n"achsten Durchlauf
+ der Message-Loop g"ultiges SfxPoolItem,
+ welches den R"uckgabewert enth"alt.
+
+ Oder ein 0-Pointer, wenn die Funktion nicht
+ ausgef"uhrt wurde (z.B. Abbruch durch den
+ Benutzer).
+*/
+
+{
+ if ( IsLocked(nSlot) )
+ return 0;
+
+ SfxShell *pShell = 0;
+ const SfxSlot *pSlot = 0;
+ if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, sal_False,
+ SFX_CALLMODE_MODAL==(eCall&SFX_CALLMODE_MODAL) ) )
+ {
+ SfxAllItemSet aSet( pShell->GetPool() );
+
+ for ( const SfxPoolItem *pArg = pArg1;
+ pArg;
+ pArg = va_arg( pVarArgs, const SfxPoolItem* ) )
+ MappedPut_Impl( aSet, *pArg );
+
+ SfxRequest aReq( nSlot, eCall, aSet );
+ _Execute( *pShell, *pSlot, aReq, eCall );
+ return aReq.GetReturnValue();
+ }
+ return 0;
+}
+
+//--------------------------------------------------------------------
+const SfxPoolItem* SfxDispatcher::Execute
+(
+ sal_uInt16 nSlot, // die Id der auszufuehrenden Funktion
+ SfxCallMode eCall, // SFX_CALLMODE_SYNCRHON, ..._ASYNCHRON oder ..._SLOT
+ const SfxPoolItem* pArg1, // erster Parameter
+ ... // 0-terminiertes Liste Parametern
+)
+
+/* [Beschreibung]
+
+ Methode zum Ausf"uhren eines <SfxSlot>s "uber die Slot-Id.
+
+
+ [Anmerkung]
+
+ Die Parameter werden kopiert, k"onnen daher als Adresse von
+ Stack-Objekten "ubergeben werden.
+
+
+ [R"uckgabewert]
+
+ const SfxPoolItem* Pointer auf ein bis zum n"achsten Durchlauf
+ der Message-Loop g"ultiges SfxPoolItem,
+ welches den R"uckgabewert enth"alt.
+
+ Oder ein 0-Pointer, wenn die Funktion nicht
+ ausgef"uhrt wurde (z.B. Abbruch durch den
+ Benutzer).
+
+
+ [Beispiel]
+
+ pDispatcher->Execute( SID_OPENDOCUMENT, SFX_CALLMODE_SYNCHRON,
+ &SfxStringItem( SID_FILE_NAME, "\\tmp\\temp.sdd" ),
+ &SfxStringItem( SID_FILTER_NAME, "StarDraw Presentation" ),
+ &SfxBoolItem( SID_DOC_READONLY, sal_False ),
+ 0L );
+*/
+
+{
+ if ( IsLocked(nSlot) )
+ return 0;
+
+ SfxShell *pShell = 0;
+ const SfxSlot *pSlot = 0;
+ if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, sal_False,
+ SFX_CALLMODE_MODAL==(eCall&SFX_CALLMODE_MODAL) ) )
+ {
+ SfxAllItemSet aSet( pShell->GetPool() );
+
+ va_list pVarArgs;
+ va_start( pVarArgs, pArg1 );
+ for ( const SfxPoolItem *pArg = pArg1;
+ pArg;
+ pArg = va_arg( pVarArgs, const SfxPoolItem* ) )
+ MappedPut_Impl( aSet, *pArg );
+ va_end(pVarArgs);
+
+ SfxRequest aReq( nSlot, eCall, aSet );
+ _Execute( *pShell, *pSlot, aReq, eCall );
+ return aReq.GetReturnValue();
+ }
+ return 0;
+}
+
+//--------------------------------------------------------------------
+
+IMPL_LINK( SfxDispatcher, PostMsgHandler, SfxRequest*, pReq )
+
+/* [Beschreibung]
+
+ Hilfsmethode zum Empfangen der asynchron auszuf"uhrenden <SfxRequest>s.
+*/
+
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( !pImp->bFlushing, "recursive call to dispatcher" );
+ SFX_STACK(SfxDispatcher::PostMsgHandler);
+
+ // ist auch der Pool noch nicht gestorben?
+// SfxRequest* pReq = pExec->pRequest;
+ if ( !pReq->IsCancelled() )
+ {
+ if ( !IsLocked(pReq->GetSlot()) )
+ {
+ Flush();
+ SfxSlotServer aSvr;
+ if ( _FindServer(pReq->GetSlot(), aSvr, HACK(x) sal_True ) )
+// SfxShell *pShell = GetShell(pExec->nLevel);
+// if ( pShell && pShell->GetInterface()->GetSlot( pExec->pSlot->GetSlotId() ) )
+ {
+ const SfxSlot *pSlot = aSvr.GetSlot();
+ SfxShell *pSh = GetShell(aSvr.GetShellLevel());
+
+ DBG( SfxApplication *pSfxApp = SFX_APP() );
+ DBG( pSfxApp->EnterAsynchronCall_Impl() );
+
+ // Wenn pSlot ein "Pseudoslot" f"ur Macros oder Verben ist, kann
+ // er im Call_Impl zerst"ort werden, also nicht mehr benutzen!
+ pReq->SetSynchronCall( sal_False );
+ Call_Impl( *pSh, *pSlot, *pReq, sal_True ); //! woher bRecord?
+// Call_Impl( *pShell, *pExec->pSlot, *pReq, sal_True ); //! woher bRecord?
+ DBG( pSfxApp->LeaveAsynchronCall_Impl() );
+ }
+
+// delete pExec;
+ }
+ else
+ {
+// pImp->xPoster->Post(pExec);
+ pImp->xPoster->Post(new SfxRequest(*pReq));
+ }
+ }
+// else
+// delete pExec;
+
+ delete pReq;
+ return 0;
+}
+//--------------------------------------------------------------------
+void SfxDispatcher::EnterAction( const String& rName )
+
+// marks the beginning of a block of actions
+
+{
+ DBG_MEMTEST();
+ Flush();
+ DBG_ASSERT( pImp->aStack.Count() > 0, "EnterAction on empty dispatcher stack" );
+ if ( ++pImp->nActionLevel == 1 )
+ {
+ SfxUndoManager *pUndoMgr = GetShell(0)->GetUndoManager();
+ if ( pUndoMgr )
+ pUndoMgr->EnterListAction( rName, rName HACK(RepeatComment), 0 HACK(ID) );
+ }
+}
+//--------------------------------------------------------------------
+void SfxDispatcher::LeaveAction()
+
+// marks the end of a block of actions
+
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( pImp->nActionLevel > 0, "EnterAction without LeaveAction" );
+ if ( --pImp->nActionLevel == 0 )
+ {
+ SfxUndoManager *pUndoMgr = GetShell(0)->GetUndoManager();
+ if ( pUndoMgr )
+ pUndoMgr->LeaveListAction();
+ }
+}
+//--------------------------------------------------------------------
+void SfxDispatcher::SetMenu_Impl()
+{
+ SfxApplication *pSfxApp = SFX_APP();
+ if ( pImp->pFrame )
+ {
+ if ( !pImp->pFrame->GetViewShell() )
+ return;
+
+ SfxTopViewFrame* pTop= PTR_CAST( SfxTopViewFrame, pImp->pFrame->GetTopViewFrame() );
+ if ( pTop && pTop->GetBindings().GetDispatcher() == this )
+ {
+ SfxTopFrame* pFrm = pTop->GetTopFrame_Impl();
+ SfxMenuBarManager* pMenuBar = pImp->pFrame->GetViewShell()->GetMenuBar_Impl();
+ if ( pMenuBar )
+ {
+ MenuBar* pMenu = (MenuBar*) pMenuBar->GetMenu()->GetSVMenu();
+ pFrm->LockResize_Impl( TRUE );
+ pFrm->SetMenuBar_Impl( pMenu );
+ pFrm->LockResize_Impl( FALSE );
+ }
+ else if ( pImp->pParent )
+ {
+ pImp->pParent->SetMenu_Impl();
+ }
+ }
+ }
+}
+
+long SfxDispatcher::Update_Impl( sal_Bool bForce )
+
+/* [Beschreibung]
+
+ Hilfsmethode zum Updaten der <Object-Bars> und <Object-Menus>,
+ nach Bewegungen auf dem Stack.
+*/
+
+{
+ SFX_STACK(SfxDispatcher::Update_Impl);
+
+ Flush();
+
+ if ( !pImp->pFrame )
+ return 0;
+
+ if ( pImp->bUILocked )
+ return 0;
+
+ SfxApplication *pSfxApp = SFX_APP();
+ SfxDispatcher *pDisp = this;
+ sal_Bool bUpdate = bForce;
+ while ( pDisp && pDisp->pImp->pFrame )
+ {
+ SfxWorkWindow *pWork = pSfxApp->GetWorkWindow_Impl( pDisp->pImp->pFrame );
+ SfxDispatcher *pAct = pWork->GetBindings().GetDispatcher_Impl();
+ if ( pAct == pDisp || pAct == this )
+ {
+ if ( !bUpdate )
+ bUpdate = !pDisp->pImp->bUpdated;
+ pDisp->pImp->bUpdated = sal_True;
+ }
+ else
+ break;
+
+ pDisp = pDisp->pImp->pParent;
+ }
+
+ if ( !bUpdate )
+ return 0;
+
+ SfxTopViewFrame* pTop = pImp->pFrame ? PTR_CAST( SfxTopViewFrame, pImp->pFrame->GetTopViewFrame() ) : NULL;
+ sal_Bool bUIActive = pTop && pTop->GetBindings().GetDispatcher() == this;
+ SfxMenuBarManager* pAppMenu = NULL;
+
+ if ( !bUIActive && pTop && GetBindings() == &pTop->GetBindings() )
+ // Eigene Tools nur intern festhalten und da"fur sorgen, da\s der
+ // aktive Dispatcher sie abholt
+ GetBindings()->GetDispatcher()->pImp->bUpdated = sal_False;
+
+ // Bindings schlafen legen
+ SfxBindings* pBindings = GetBindings();
+ if ( pBindings )
+ pBindings->DENTERREGISTRATIONS();
+
+ // Test auf InPlaceFrame und speziell internes InPlace
+ SfxInPlaceFrame *pIPFrame = PTR_CAST ( SfxInPlaceFrame, pImp->pFrame);
+ sal_Bool bIsIPOwner = (pIPFrame && pIPFrame->GetObjectShell()->GetInPlaceObject()->GetIPClient()->Owner());
+ SvInPlaceClient *pClient = pImp->pFrame ? pImp->pFrame->GetViewShell()->GetIPClient() : NULL;
+ if ( bUIActive && !pIPFrame && ( !pClient || !pClient->GetProtocol().IsUIActive() ) )
+ {
+ SetMenu_Impl();
+ pAppMenu = pImp->pFrame->GetViewShell()->GetMenuBar_Impl();
+ pAppMenu->ResetObjectMenus();
+ }
+
+ // Environment
+ SfxWorkWindow *pWorkWin = pSfxApp->GetWorkWindow_Impl(pImp->pFrame);
+
+ // der SfxInternalFrame oder SfxTopViewFrame, zu dem ich geh"ore
+ SfxViewFrame *pAct =
+ bIsIPOwner ?
+ pImp->pFrame->GetParentViewFrame_Impl() :
+ pImp->pFrame;
+
+ // Ich kontrolliere die StatusBar einer Task auch wenn ich nicht aktiv bin, aber
+ // zu einem internem InPlaceFrame oder einem anderen ViewFrame innerhalb der Task geh"ore
+ SfxFrame *pTask = pAct ? pAct->GetFrame()->GetTopFrame() : NULL;
+
+ SfxWorkWindow *pTaskWin = NULL;
+ sal_Bool bSet = sal_True;
+ if ( pImp->pFrame && pImp->pFrame->GetViewShell() )
+ {
+ SvInPlaceClient *pClient = pImp->pFrame->GetViewShell()->GetIPClient();
+ if ( pClient && pClient->GetProtocol().IsUIActive() )
+ bSet = sal_False;
+ }
+
+ if ( pTask && bSet )
+ {
+ pTaskWin = pTask->GetWorkWindow_Impl();
+ pTaskWin->ResetStatusBar_Impl();
+ }
+
+ SfxDispatcher *pDispat = this;
+ while ( pDispat )
+ {
+ SfxWorkWindow *pWork = pSfxApp->GetWorkWindow_Impl(pDispat->pImp->pFrame);
+ SfxDispatcher *pAct = pWork->GetBindings().GetDispatcher_Impl();
+ if ( pAct == pDispat || pAct == this )
+ {
+ pWork->ResetObjectBars_Impl();
+ pWork->ResetChildWindows_Impl();
+ }
+
+ pDispat = pDispat->pImp->pParent;
+ }
+
+ sal_Bool bIsActive = sal_False;
+ SfxDispatcher *pActDispat = pWorkWin->GetBindings().GetDispatcher_Impl();
+ pDispat = this;
+ while ( pActDispat && !bIsActive )
+ {
+ if ( pDispat == pActDispat )
+ bIsActive = sal_True;
+ pActDispat = pActDispat->pImp->pParent;
+ }
+
+ if ( !pIPFrame && !IsAppDispatcher() && bIsActive )
+ CollectTools_Impl( pWorkWin );
+
+ // Jetzt rekursiv die Dispatcher abklappern
+ sal_uInt32 nHelpId = _Update_Impl( bUIActive, !pIPFrame, bIsIPOwner, pAppMenu, bSet ? pTaskWin : NULL );
+ if ( bUIActive || bIsActive )
+ {
+ pWorkWin->UpdateObjectBars_Impl();
+
+ if ( pAppMenu )
+ pAppMenu->UpdateObjectMenus();
+
+ if ( bUIActive )
+ {
+ // ggf. Hilfe-PI antriggern
+ SfxHelpPI* pHelpPI = pSfxApp->GetHelpPI();
+ if (pHelpPI && nHelpId)
+ pHelpPI->LoadTopic( nHelpId );
+ }
+ }
+
+ if ( pTaskWin )
+ pTaskWin->UpdateStatusBar_Impl();
+
+ if ( pBindings )
+ pBindings->DLEAVEREGISTRATIONS();
+ return 1;
+}
+
+
+void SfxDispatcher::CollectTools_Impl( SfxWorkWindow* pWorkWin )
+{
+ // Innerhalb eines ToolSpace werden auch die Tools von nicht aktiven Frames
+ // angezeigt, damit es beim Wechsel der Frames nicht zappelt
+ SfxApplication *pSfxApp = SFX_APP();
+ SfxToolBoxConfig *pTbxCfg = SfxToolBoxConfig::GetOrCreate();
+
+ // Die Objectbars aller ViewFrames der aktuellen Task einsammeln
+ for ( SfxViewFrame* pViewFrame = SfxViewFrame::GetFirst();
+ pViewFrame;
+ pViewFrame = SfxViewFrame::GetNext(*pViewFrame) )
+ {
+ // Frames mit anderem WorkWindow interessieren hier nicht
+ if ( pViewFrame->GetFrame()->GetWorkWindow_Impl() != pWorkWin )
+ continue;
+
+ // Nur weitermachen, wenn es nicht sowieso einer meiner parents ist
+ SfxDispatcher *pDispat = pViewFrame->GetDispatcher();
+ SfxDispatcher *pParent = this;
+ while ( pParent )
+ {
+ if ( pParent == pDispat )
+ break;
+ pParent = pParent->pImp->pParent;
+ }
+
+ if ( pParent )
+ continue;
+
+ // Alle objectbars des ViewFrames vormerken
+ sal_uInt16 n;
+ for (n=0; n<SFX_OBJECTBAR_MAX; n++)
+ {
+ SfxObjectBars_Impl& rBar = pDispat->pImp->aObjBars[n];
+ sal_uInt16 nId = rBar.aResId.GetId();
+ if ( nId && pTbxCfg->GetAlignment(n) != SFX_ALIGN_NOALIGNMENT )
+ pWorkWin->SetObjectBar_Impl( rBar.nMode,
+ rBar.aResId, rBar.pIFace, &rBar.aName );
+ }
+
+ SfxShell *pShell = pDispat->GetShell(0);
+ SfxModule *pMod = pShell->GetInterface()->GetModule();
+ SfxSlotPool& rSlotPool = pMod ? *pMod->GetSlotPool() : pShell->GetSlotPool_Impl();
+
+ // ChildWindows auch "bunkern"
+ for (n=0; n<pDispat->pImp->aChildWins.Count(); n++)
+ {
+ sal_uInt32 nId = pDispat->pImp->aChildWins[n];
+ const SfxSlot *pSlot = rSlotPool.GetSlot( (sal_uInt16) nId );
+ sal_uInt16 nMode = SFX_VISIBILITY_STANDARD;
+ if( pSlot )
+ {
+ if ( pSlot->IsMode(SFX_SLOT_CONTAINER) )
+ {
+ if ( !pWorkWin->IsVisible_Impl( SFX_VISIBILITY_CLIENT ) )
+ continue;
+ nMode |= SFX_VISIBILITY_CLIENT;
+ }
+ else
+ {
+ if ( !pWorkWin->IsVisible_Impl( SFX_VISIBILITY_SERVER ) )
+ continue;
+ nMode |= SFX_VISIBILITY_SERVER;
+ }
+ }
+
+ pWorkWin->SetChildWindowVisible_Impl( nId, sal_False, nMode );
+ }
+ }
+}
+
+
+sal_uInt32 SfxDispatcher::_Update_Impl( sal_Bool bUIActive, sal_Bool bIsMDIApp,
+ sal_Bool bIsIPOwner, SfxMenuBarManager *pAppMenu, SfxWorkWindow *pTaskWin )
+{
+ sal_uInt32 nHelpId = 0L;
+ SfxApplication *pSfxApp = SFX_APP();
+ SfxWorkWindow *pWorkWin = pSfxApp->GetWorkWindow_Impl( pImp->pFrame );
+ sal_Bool bIsActive = sal_False;
+ sal_Bool bIsTaskActive = sal_False;
+ SfxDispatcher *pActDispat = pWorkWin->GetBindings().GetDispatcher_Impl();
+ SfxDispatcher *pDispat = this;
+ while ( pActDispat && !bIsActive )
+ {
+ if ( pDispat == pActDispat )
+ bIsActive = sal_True;
+ pActDispat = pActDispat->pImp->pParent;
+ }
+
+ if ( pImp->pParent && !pImp->bQuiet /* && bUIActive */ )
+ // Das Men"u kommt immer vom obersten Dispatcher, also pAppMenu nicht weiterreichen
+ nHelpId = pImp->pParent->_Update_Impl( bUIActive, bIsMDIApp, bIsIPOwner, NULL, pTaskWin );
+
+ // Internen Zwischenspeicher ObjectBars und ChildWindows zur"ucksetzen
+ for (sal_uInt16 n=0; n<SFX_OBJECTBAR_MAX; n++)
+ pImp->aObjBars[n].aResId = ResId( 0,0 );
+ pImp->aChildWins.Remove(0, pImp->aChildWins.Count());
+
+ // bQuiet : eigene Shells weder f"ur UI noch f"ur SlotServer ber"ucksichtigen
+ // bNoUI: eigene Shells f"ur das UI nicht ber"ucksichtigen
+ if ( pImp->bQuiet || pImp->bNoUI || pImp->pFrame && pImp->pFrame->GetObjectShell()->IsPreview() )
+ return nHelpId;
+
+ sal_uInt16 nStatBarId=0;
+ SfxShell *pStatusBarShell = NULL;
+
+ sal_uInt16 nTotCount = pImp->aStack.Count();
+ for ( sal_uInt16 nShell = nTotCount; nShell > 0; --nShell )
+ {
+ SfxShell *pShell = GetShell( nShell-1 );
+ SfxInterface *pIFace = pShell->GetInterface();
+ if (pShell->GetHelpId())
+ nHelpId = pShell->GetHelpId();
+
+ // Shells von Dispatcher mit Attribut "Hidden" oder "Quiet" auslassen
+ sal_Bool bReadOnlyShell = IsReadOnlyShell_Impl( nShell-1 );
+ SfxSlotPool& rSlotPool = pIFace->GetModule() ?
+ *pIFace->GetModule()->GetSlotPool() : pShell->GetSlotPool_Impl();
+
+ sal_uInt16 nNo;
+ for ( nNo = 0; pIFace && nNo<pIFace->GetObjectBarCount(); ++nNo )
+ {
+ sal_uInt16 nPos = pIFace->GetObjectBarPos(nNo);
+ if ( bReadOnlyShell && !( nPos & SFX_VISIBILITY_READONLYDOC ) )
+ continue;
+
+ // Soll die ObjectBar nur angezeigt werden, wenn die Shell
+ // einen bestimmten UI-Modus hat?
+ sal_uInt32 nFeature = pIFace->GetObjectBarFeature(nNo);
+ if ( nFeature && !pShell->HasUIFeature( nFeature ) )
+ continue;
+
+ // Auf jeden Fall eintragen, auch wenn unsichtbar. Dann kann
+ // WorkWindow anbieten, wieder anzuschalten
+ sal_Bool bVisible = pIFace->IsObjectBarVisible(nNo);
+ if ( !bVisible )
+ nPos &= SFX_POSITION_MASK;
+
+ SfxObjectBars_Impl& rBar = pImp->aObjBars[nPos & SFX_POSITION_MASK];
+ rBar.nMode = nPos;
+ rBar.aResId = pIFace->GetObjectBarResId(nNo);
+ const String *pName = pIFace->GetObjectBarName(nNo);
+ if ( pName )
+ rBar.aName = *pName;
+ else
+ rBar.aName.Erase();
+ rBar.pIFace = pIFace;
+
+ if ( bUIActive || bIsActive )
+ {
+ pWorkWin->SetObjectBar_Impl(
+ nPos, rBar.aResId, rBar.pIFace, &rBar.aName );
+ }
+
+ if ( !bVisible )
+ rBar.aResId = ResId( 0,0 );
+ }
+
+ for ( nNo=0; pIFace && nNo<pIFace->GetChildWindowCount(); nNo++ )
+ {
+ sal_uInt32 nId = pIFace->GetChildWindowId(nNo);
+ const SfxSlot *pSlot = rSlotPool.GetSlot( (sal_uInt16) nId );
+ DBG_ASSERT( pSlot, "Da fehlt ein Childwindow-Slot!");
+ if ( bReadOnlyShell )
+ {
+ // Bei read only documents nur solche ChildWindows anzeigen,
+ // die daf"ur freigegeben sind
+ if ( pSlot && !pSlot->IsMode( SFX_SLOT_READONLYDOC ) )
+ continue;
+ }
+
+ sal_uInt32 nFeature = pIFace->GetChildWindowFeature(nNo);
+ if ( nFeature && !pShell->HasUIFeature( nFeature ) )
+ continue;
+
+ // Bei den anderen auf CONTAINER/SERVER-Slots abfragen
+ sal_uInt16 nMode = SFX_VISIBILITY_STANDARD;
+ if( pSlot )
+ {
+ if ( pSlot->IsMode(SFX_SLOT_CONTAINER) )
+ {
+ if ( !pWorkWin->IsVisible_Impl( SFX_VISIBILITY_CLIENT ) )
+ continue;
+ nMode |= SFX_VISIBILITY_CLIENT;
+ }
+ else
+ {
+ if ( !pWorkWin->IsVisible_Impl( SFX_VISIBILITY_SERVER ) )
+ continue;
+ nMode |= SFX_VISIBILITY_SERVER;
+ }
+ }
+
+ if ( bUIActive || bIsActive )
+ pWorkWin->SetChildWindowVisible_Impl( nId, sal_True, nMode );
+ if ( bUIActive || bIsActive || !pWorkWin->IsFloating( (sal_uInt16) ( nId & 0xFFFF ) ) )
+ pImp->aChildWins.Insert( nId, pImp->aChildWins.Count());
+ }
+
+ if ( pAppMenu )
+ {
+ // update Object-Menus
+ for ( nNo = 0; pIFace && nNo<pIFace->GetObjectMenuCount(); ++nNo )
+ pAppMenu->SetObjectMenu( pIFace->GetObjectMenuPos(nNo),
+ pIFace->GetObjectMenuResId(nNo));
+ }
+
+ if ( bIsMDIApp || bIsIPOwner )
+ {
+ // Bei MDIEnvironment oder internem InPlace Statuszeile setzen
+ sal_uInt16 nId = pIFace->GetStatusBarResId().GetId();
+ if ( nId )
+ {
+ nStatBarId = nId;
+ pStatusBarShell = pShell;
+ }
+ }
+ }
+
+ for ( sal_uInt16 nPos=0; nPos<SFX_OBJECTBAR_MAX; nPos++ )
+ {
+ SfxObjectBars_Impl& rFixed = pImp->aFixedObjBars[nPos];
+ if ( rFixed.aResId.GetId() )
+ {
+ SfxObjectBars_Impl& rBar = pImp->aObjBars[nPos];
+ rBar = rFixed;
+ pWorkWin->SetObjectBar_Impl( rFixed.nMode,
+ rFixed.aResId, rFixed.pIFace, &rFixed.aName );
+ }
+ }
+
+ if ( pTaskWin && ( bIsMDIApp || bIsIPOwner ) )
+ {
+ SfxDispatcher *pActDispat = pTaskWin->GetBindings().GetDispatcher_Impl();
+ SfxDispatcher *pDispat = this;
+ if ( bIsIPOwner && pImp->pFrame )
+ pDispat = pImp->pFrame->GetParentViewFrame_Impl()->GetDispatcher();
+
+ while ( pActDispat && !bIsTaskActive )
+ {
+ if ( pDispat == pActDispat )
+ bIsTaskActive = sal_True;
+ pActDispat = pActDispat->pImp->pParent;
+ }
+
+ if ( bIsTaskActive && nStatBarId && pImp->pFrame )
+ {
+ // Ich kontrolliere die StatusBar einer Task auch wenn ich nicht aktiv bin, aber
+ // zu einem internem InPlaceFrame oder einem anderen ViewFrame innerhalb der Task geh"ore
+ SfxBindings& rBindings = pImp->pFrame->GetBindings();
+ pTaskWin->SetStatusBar_Impl( nStatBarId, pStatusBarShell, rBindings );
+ }
+ }
+
+ return nHelpId;
+}
+
+//--------------------------------------------------------------------
+long SfxDispatcher::UpdateObjectMenus_Impl( SfxMenuBarManager *pMenuMgr )
+
+/* [Beschreibung]
+
+ Hilfsmethode zum Updaten der <Object-Menus>.
+*/
+
+{
+ SFX_STACK(SfxDispatcher::UpdateObjecteMenus_Impl);
+
+ Flush();
+
+ if (!pImp->pFrame && !IsAppDispatcher())
+ {
+ DBG_ERROR( "Dispatcher ohne Frame aber mit Parent?!?" );
+ return 0;
+ }
+
+ // Bindings und App besorgen
+ SfxApplication *pSfxApp = SFX_APP();
+ SfxBindings* pBindings = GetBindings();
+ if ( pBindings )
+ pBindings->DENTERREGISTRATIONS();
+ pMenuMgr->ResetObjectMenus();
+
+ sal_uInt16 nTotCount = pImp->aStack.Count();
+ sal_uInt16 nMinCount = pImp->bQuiet || pImp->bNoUI ? nTotCount : 0;
+
+ if ( pImp->pParent ) // && !(pImp->pFrame->GetFrameType() & SFXFRAME_PLUGIN ) )
+ {
+ // Parents nur bei PlugIns nicht ber"ucksichtigen
+ // (AppDispatcher oder parent frame)
+ SfxDispatcher *pParent = pImp->pParent;
+ while ( pParent )
+ {
+ nTotCount += pParent->pImp->aStack.Count();
+ if ( pParent->pImp->bQuiet || pParent->pImp->bNoUI )
+ nMinCount = nTotCount;
+ pParent = pParent->pImp->pParent;
+ }
+ }
+
+ for ( sal_uInt16 nShell = nTotCount; nShell > nMinCount; --nShell )
+ {
+ SfxShell *pShell = GetShell( nShell-1 );
+ const SfxInterface *pIFace = pShell->GetInterface();
+
+ // update Object-Menus
+ for ( sal_uInt16 nNo = 0; pIFace && nNo<pIFace->GetObjectMenuCount(); ++nNo )
+ pMenuMgr->SetObjectMenu( pIFace->GetObjectMenuPos(nNo),
+ pIFace->GetObjectMenuResId(nNo));
+ }
+
+ pMenuMgr->UpdateObjectMenus();
+ if ( pBindings )
+ pBindings->DLEAVEREGISTRATIONS();
+ return 0;
+}
+
+//--------------------------------------------------------------------
+void SfxDispatcher::FlushImpl()
+
+/* [Beschreibung]
+
+ Hilfsmethode zum Ausf"uhren der ausstehenden Push- und Pop-Befehle.
+*/
+
+{
+ DBG_PROFSTART(SfxDispatcherFlush);
+ DBG_MEMTEST();
+ SFX_STACK(SfxDispatcher::FlushImpl);
+
+
+#ifdef DBG_UTIL
+ ByteString aMsg( "SfxDispatcher(" );
+ aMsg += ByteString::CreateFromInt32( (long) this );
+ aMsg += ")::Flush()";
+#endif
+
+ pImp->aTimer.Stop();
+
+ if ( pImp->pParent )
+ pImp->pParent->Flush();
+
+// if ( pImp->bQuiet )
+// return;
+
+ pImp->bFlushing = !pImp->bFlushing;
+ if ( !pImp->bFlushing )
+ {
+ pImp->bFlushing = sal_True;
+ DBG_PROFSTOP(SfxDispatcherFlush);
+//!
+#ifdef DBG_UTIL_MESSEHACK_AUSKOMMENT
+ DBG_ERROR( "reentering SfxDispatcher::Flush()" );
+ aMsg += " reentering, aborted";
+ DbgTrace( aMsg.GetBuffer() );
+#endif
+ return;
+ }
+
+ SfxApplication *pSfxApp = SFX_APP();
+
+ // in der 1. Runde den echten Stack 'um'bauen
+ SfxToDoStack_Impl aToDoCopy;
+ sal_Bool bModify = sal_False;
+ short nToDo;
+ for ( nToDo = pImp->aToDoStack.Count()-1; nToDo >= 0; --nToDo )
+ {
+ bModify = sal_True;
+
+ SfxToDo_Impl aToDo( pImp->aToDoStack.Top(nToDo) );
+ if ( aToDo.bPush )
+ {
+ // tats"aechlich pushen
+ DBG_ASSERT( !pImp->aStack.Contains( aToDo.pCluster ),
+ "pushed SfxShell already on stack" );
+ pImp->aStack.Push( aToDo.pCluster );
+ aToDo.pCluster->SetDisableFlags( pImp->nDisableFlags );
+
+ // die bewegte Shell merken
+ aToDoCopy.Push( aToDo );
+ }
+ else
+ {
+ // tats"aechlich poppen
+ SfxShell* pPopped = 0;
+ FASTBOOL bFound = sal_False;
+ do
+ {
+ DBG_ASSERT( pImp->aStack.Count(), "popping from empty stack" );
+ pPopped = pImp->aStack.Pop();
+ pPopped->SetDisableFlags( 0 );
+ bFound = pPopped == aToDo.pCluster;
+
+ // die bewegte Shell merken
+ aToDoCopy.Push( SfxToDo_Impl( sal_False, aToDo.bDelete, sal_False, *pPopped) );
+ }
+ while ( aToDo.bUntil && !bFound );
+ DBG_ASSERT( bFound, "wrong SfxShell popped" );
+ }
+
+ if ( nToDo == 0 )
+ pImp->aToDoStack.Clear();
+ }
+
+ // ggf. Bindings invalidieren
+ if ( !pSfxApp->IsDowning() )
+ {
+ if ( bModify )
+ {
+ pImp->pCachedServ1 = 0;
+ pImp->pCachedServ2 = 0;
+ }
+
+ InvalidateBindings_Impl( bModify );
+ }
+
+ pImp->bFlushing = sal_False;
+ pImp->bUpdated = sal_False; // nicht nur bei bModify, falls Doc/Template-Config
+ bFlushed = sal_True;
+
+ // in der 2. Runde die Shells aktivieren und ggf. l"oschen
+ for ( nToDo = aToDoCopy.Count()-1; nToDo >= 0; --nToDo )
+ {
+ SfxToDo_Impl aToDo( aToDoCopy.Top(nToDo) );
+ if ( aToDo.bPush )
+ {
+ if ( pImp->bActive )
+ aToDo.pCluster->DoActivate(pImp->pFrame, sal_True);
+ }
+ else
+ if ( pImp->bActive )
+ aToDo.pCluster->DoDeactivate(pImp->pFrame, sal_True);
+ }
+ for ( nToDo = aToDoCopy.Count()-1; nToDo >= 0; --nToDo )
+ {
+ SfxToDo_Impl aToDo( aToDoCopy.Top(nToDo) );
+ if ( aToDo.bDelete ) delete aToDo.pCluster;
+ }
+ sal_Bool bAwakeBindings = aToDoCopy.Count() != 0;
+ if( bAwakeBindings )
+ aToDoCopy.Clear();
+
+ // Wenn bei Activate/Deactivate/Delete weitere Stackbewegungen erfolgt sind :
+ if (!bFlushed)
+ // falls jemand Push/Pop gerufen hat, wurde auch EnterReg gerufen!
+ FlushImpl();
+
+ if( bAwakeBindings && GetBindings() )
+ GetBindings()->DLEAVEREGISTRATIONS();
+ DBG_PROFSTOP(SfxDispatcherFlush);
+
+ for (sal_uInt16 n=0; n<SFX_OBJECTBAR_MAX; n++)
+ pImp->aFixedObjBars[n].aResId = ResId( 0,0 );
+
+#ifdef DBG_UTIL
+ aMsg += " done";
+ DbgTrace( aMsg.GetBuffer() );
+#endif
+}
+
+//--------------------------------------------------------------------
+void SfxDispatcher::SetSlotFilter
+(
+ HACK(hier muss mal ein enum rein)
+ sal_Bool bEnable, /* sal_True:
+ nur angegebene Slots enablen,
+ alle anderen disablen
+
+ sal_False:
+ die angegebenen Slots disablen,
+ alle anderen zun"achst enablen
+ */
+ sal_uInt16 nCount, // Anzahl der SIDs im folgenden Array
+ const sal_uInt16* pSIDs // sortiertes Array von 'nCount' SIDs
+)
+
+/* [Beschreibung]
+
+ Mit dieser Methode wird ein Filter gesetzt, mit dem gezielt Slots
+ enabled bzw. disabled werden k"onnen. Das "ubergebene Array mu\s
+ bis zum Dtor bzw. n"achsten <SetSlotFilter()> erhalten bleiben, es
+ wird nicht vom Dispatcher gel"oscht, es kann daher static sein.
+
+ In ReadOnly-Dokumenten kann man mit 'bEnable==2' quasi das ReadOnlyDoc
+ Flag von Slots "ubersteuern, dieser werden also wieder gefunden. Auf
+ andere Slots hat das dann keine Auswirkung.
+
+
+ [Beispiel]
+
+ gezieltes disablen der Slots 1, 2 und 3:
+
+ static sal_uInt16 __READONLY_DATA pSIDs[] = { 1, 2, 3 };
+ pDisp->SetSlotFilter( sal_False, sizeof(pSIDs)/sizeof(sal_uInt16), pSIDs );
+
+ nur die Slots 5, 6 und 7 zulassen:
+
+ static sal_uInt16 __READONLY_DATA pSIDs[] = { 5, 6, 7 };
+ pDisp->SetSlotFilter( sal_True, sizeof(pSIDs)/sizeof(sal_uInt16), pSIDs );
+
+ Filter ausschalten:
+
+ pDisp->SetSlotFilter();
+*/
+
+{
+#ifdef DBG_UTIL
+ // Array "uberpr"ufen
+ for ( sal_uInt16 n = 1; n < nCount; ++n )
+ DBG_ASSERT( pSIDs[n] > pSIDs[n-1], "SetSlotFilter: SIDs not sortet" );
+#endif
+
+ if ( pImp->pFilterSIDs )
+ pImp->pFilterSIDs = 0;
+
+ pImp->bFilterEnabling = bEnable;
+ pImp->nFilterCount = nCount;
+ pImp->pFilterSIDs = pSIDs;
+
+ GetBindings()->InvalidateAll(sal_True);
+}
+
+//--------------------------------------------------------------------
+EXTERN_C
+#if defined( PM2 ) && (!defined( CSET ) && !defined ( MTW ) && !defined( WTC ))
+int _stdcall
+#else
+#ifdef WNT
+int _cdecl
+#else
+int
+#endif
+#endif
+
+SfxCompareSIDs_Impl( const void* pSmaller, const void* pBigger )
+{
+ DBG_MEMTEST();
+ return ( (long) *((sal_uInt16*)pSmaller) ) - ( (long) *((sal_uInt16*)pBigger) );
+}
+
+//--------------------------------------------------------------------
+sal_Bool SfxDispatcher::IsSlotEnabledByFilter_Impl( sal_uInt16 nSID ) const
+
+/* [Beschreibung]
+
+ Sucht 'nSID' in dem mit <SetSlotFilter()> gesetzten Filter und
+ liefert sal_True, falls die SID erlaubt ist, bzw. sal_False, falls sie
+ durch den Filter disabled ist.
+
+ [R"uckgabewert]
+ sal_Bool 0 => disabled
+ 1 => enabled
+ 2 => enabled even if ReadOnlyDoc
+*/
+
+{
+ // kein Filter?
+ if ( 0 == pImp->nFilterCount )
+ // => alle SIDs erlaubt
+ return sal_True;
+
+ // suchen
+ sal_Bool bFound = 0 != bsearch( &nSID, pImp->pFilterSIDs, pImp->nFilterCount,
+ sizeof(sal_uInt16), SfxCompareSIDs_Impl );
+
+ // even if ReadOnlyDoc
+ if ( 2 == pImp->bFilterEnabling )
+ return bFound ? 2 : 1;
+ // sonst je nach Negativ/Positiv Filter
+ return pImp->bFilterEnabling ? bFound : !bFound;
+}
+
+//--------------------------------------------------------------------
+sal_Bool SfxDispatcher::_TryIntercept_Impl
+(
+ sal_uInt16 nSlot, // zu suchende Slot-Id
+ SfxSlotServer& rServer, // zu f"uellende <SfxSlotServer>-Instanz
+ sal_Bool bSelf
+)
+{
+ // Eventuell geh"ort der parent auch zu einer Komponente
+ SfxDispatcher *pParent = pImp->pParent;
+ sal_uInt16 nLevels = pImp->aStack.Count();
+ while ( pParent && pParent->pImp->pFrame )
+ {
+ if ( pParent->pImp->pFrame->GetFrame()->HasComponent() )
+ {
+ // Components d"urfen intercepten
+ if ( pParent->_TryIntercept_Impl( nSlot, rServer, sal_True ) )
+ {
+ // Die eigenen Shells zum Shelllevel hinzuz"ahlen
+ rServer.SetShellLevel( rServer.GetShellLevel() + nLevels );
+ return sal_True;
+ }
+ else
+ // Keine weitere Interception
+ break;
+ }
+ else
+ nLevels += pParent->pImp->aStack.Count();
+
+ pParent = pParent->pImp->pParent;
+ }
+
+ if ( bSelf )
+ {
+ // Die ComponentViewShell befragen
+ Flush();
+ SfxShell *pObjShell = GetShell(0);
+ SfxInterface *pIFace = pObjShell->GetInterface();
+ const SfxSlot *pSlot = pIFace->GetSlot(nSlot);
+
+ if ( pSlot )
+ {
+ rServer.SetSlot(pSlot);
+ rServer.SetShellLevel(0);
+#ifdef DBG_UTILx
+ String aMsg( nSlot );
+ aMsg += " intercepted";
+ DbgTrace( aMsg.GetBuffer() );
+#endif
+ return sal_True;
+ }
+ }
+
+ return sal_False;
+}
+
+sal_Bool SfxDispatcher::_FindServer
+(
+ sal_uInt16 nSlot, // zu suchende Slot-Id
+ SfxSlotServer& rServer, // zu f"uellnde <SfxSlotServer>-Instanz
+ sal_Bool bModal // trotz ModalMode
+)
+
+/* [Beschreibung]
+
+ Diese Hilfsmethode sucht den <Slot-Server>, der nSlot zur Zeit bedient.
+ Als Ergebnis wird rServer entsprechend gef"ullt.
+
+ Falls bekannt, kann das SfxInterface mitgegeben werden, von welchem
+ nSlot momentan bedient wird.
+
+ Vor der Suche nach nSlot wird der SfxDispatcher geflusht.
+
+
+ [R"uckgabewert]
+
+ sal_Bool sal_True
+ Der Slot wurde gefunden, rServer ist g"ultig.
+
+ sal_False
+ Der Slot wird momentan nicht bedient, rServer
+ ist ung"ultig.
+*/
+
+{
+ SFX_STACK(SfxDispatcher::_FindServer);
+
+ // Dispatcher gelockt? (SID_BROWSE_STOP und SID_HELP_PI trotzdem durchlassen)
+ SfxApplication *pSfxApp = SFX_APP();
+ sal_Bool bAllLocked = pSfxApp->IsDispatcherLocked();
+ if ( IsLocked(nSlot) )
+ {
+ if ( bAllLocked )
+ pSfxApp->Get_Impl()->bInvalidateOnUnlock = sal_True;
+ pImp->bInvalidateOnUnlock = sal_True;
+ return sal_False;
+ }
+
+ // Anzahl der Shells auf den verkettenten Dispatchern z"ahlen
+ Flush();
+ sal_uInt16 nTotCount = pImp->aStack.Count();
+ if ( pImp->pParent )
+ {
+ SfxDispatcher *pParent = pImp->pParent;
+ while ( pParent )
+ {
+ nTotCount += pParent->pImp->aStack.Count();
+ pParent = pParent->pImp->pParent;
+ }
+ }
+
+ // Makro-Slot?
+ if ( SfxMacroConfig::IsMacroSlot( nSlot ) )
+ {
+ rServer.SetShellLevel(nTotCount-1);
+ rServer.SetSlot(pSfxApp->GetMacroConfig()->GetMacroInfo(nSlot)->GetSlot());
+ return sal_True;
+ }
+ // Verb-Slot?
+ else if (nSlot >= SID_VERB_START && nSlot <= SID_VERB_END)
+ {
+ SfxShell *pSh = 0;
+ for ( sal_uInt16 nShell = 0; pSh = GetShell(nShell); ++nShell )
+ {
+ if ( pSh->ISA(SfxViewShell) )
+ {
+ rServer.SetShellLevel(nShell);
+ rServer.SetSlot(pSh->GetVerbSlot_Impl(nSlot));
+ return sal_True;
+ }
+ }
+
+ return sal_False;
+ }
+
+ // SID gegen gesetzten Filter pr"ufen
+ sal_uInt16 nSlotEnableMode=0;
+ if ( pImp->pFrame )
+ {
+ nSlotEnableMode = IsSlotEnabledByFilter_Impl( nSlot );
+ if ( 0 == nSlotEnableMode )
+ return sal_False;
+ }
+
+ // im Quiet-Mode nur Parent-Dispatcher
+ if ( pImp->bQuiet )
+ {
+ if ( pImp->pParent )
+ {
+ sal_Bool bRet = pImp->pParent->_FindServer( nSlot, rServer, bModal );
+ rServer.SetShellLevel
+ ( rServer.GetShellLevel() + pImp->aStack.Count() );
+ return bRet;
+ }
+ else
+ return sal_False;
+ }
+
+ sal_Bool bReadOnly = ( 2 != nSlotEnableMode && pImp->bReadOnly ) ||
+ ( pImp->pFrame && pImp->pFrame->GetObjectShell() &&
+ pImp->pFrame->GetObjectShell()->IsLoading() );
+
+ // durch alle Shells der verketteten Dispatchern von oben nach unten suchen
+#ifdef DBG_UTILx
+ String aStack( "Stack:" );
+#endif
+ sal_uInt16 nFirstShell = pImp->bModal && !bModal ? pImp->aStack.Count() : 0;
+ for ( sal_uInt16 i = nFirstShell; i < nTotCount; ++i )
+ {
+ SfxShell *pObjShell = GetShell(i);
+ SfxInterface *pIFace = pObjShell->GetInterface();
+ const SfxSlot *pSlot = pIFace->GetSlot(nSlot);
+
+ if ( pSlot && pSlot->nDisableFlags && ( pSlot->nDisableFlags & pObjShell->GetDisableFlags() ) != 0 )
+ return sal_False;
+
+ if ( pSlot && !( pSlot->nFlags & SFX_SLOT_READONLYDOC ) && bReadOnly )
+ return sal_False;
+
+ if ( pSlot )
+ {
+ // Slot geh"ort zum Container?
+ FASTBOOL bIsContainerSlot = pSlot->IsMode(SFX_SLOT_CONTAINER);
+ FASTBOOL bIsInPlace = pImp->pFrame && pImp->pFrame->ISA( SfxInPlaceFrame );
+
+ // Shell geh"ort zum Server?
+ // AppDispatcher oder IPFrame-Dispatcher
+ FASTBOOL bIsServerShell = !pImp->pFrame || bIsInPlace;
+
+ // Nat"urlich sind ServerShell-Slots auch ausf"uhrbar, wenn sie auf
+ // einem Container-Dispatcher ohne IPClient ausgef"uhrt werden sollen.
+ if ( !bIsServerShell )
+ {
+ SfxViewShell *pViewSh = pImp->pFrame->GetViewShell();
+ bIsServerShell = !pViewSh || !pViewSh->GetIPClient();
+ }
+
+ // Shell geh"ort zum Container?
+ // AppDispatcher oder kein IPFrameDispatcher
+ FASTBOOL bIsContainerShell = !pImp->pFrame || !bIsInPlace;
+#ifdef MBA
+ if ( !bIsContainerShell )
+ {
+ // Bei internem InPlace auch den AppDispatcher zug"angig machen
+ if ( pImp->pFrame && pImp->pFrame->GetParentViewFrame_Impl() )
+ {
+ if ( i == nTotCount - 1 )
+ bIsContainerShell = sal_True;
+ }
+ }
+#endif
+ // Shell und Slot passen zusammen
+ if ( !( ( bIsContainerSlot && bIsContainerShell ) ||
+ ( !bIsContainerSlot && bIsServerShell ) ) )
+ pSlot = 0;
+ }
+
+#ifdef DBG_UTILx
+ if ( pSlot )
+ {
+ String aMsg( nSlot );
+ aMsg += " found in ";
+ aMsg += pObjShell->GetInterface()->GetClassName();
+ DbgTrace( aMsg.GetBuffer() );
+ }
+ else
+ {
+ aStack += " ";
+ aStack += pObjShell->GetInterface()->GetClassName();
+ }
+#endif
+ if ( pSlot && !IsAllowed( nSlot ) )
+ {
+ pSlot = NULL;
+ }
+
+ if ( pSlot )
+ {
+ rServer.SetSlot(pSlot);
+ rServer.SetShellLevel(i);
+ return sal_True;
+ }
+ }
+
+#ifdef DBG_UTILx
+ String aMsg( nSlot );
+ aMsg += " not found in ";
+ aMsg += aStack;
+ DbgTrace( aMsg.GetBuffer() );
+#endif
+ return sal_False;
+}
+//--------------------------------------------------------------------
+sal_Bool SfxDispatcher::_FillState
+(
+ const SfxSlotServer& rSvr, // abzufragende <Slot-Server>
+ SfxItemSet& rState, // zu f"ullendes <SfxItemSet>
+ const SfxSlot* pRealSlot // ggf. der tats"achliche Slot
+)
+
+/* [Beschreibung]
+
+ Hilfsmethode zum Abfragen des Status des <Slot-Server>s rSvr.
+ In rState m"ussen die gew"unschten Slots-Ids (teilweise in Which-Ids
+ des betreffenden Pools umgewandelt) vorhanden sein.
+
+ Der SfxDispatcher wird vor der Abfrage geflusht.
+*/
+
+{
+ SFX_STACK(SfxDispatcher::_FillState);
+
+ DBG_PROFSTART(SfxDispatcherFillState);
+
+ const SfxSlot *pSlot = rSvr.GetSlot();
+ SfxApplication *pSfxApp = SFX_APP();
+ sal_Bool bAllLocked = pSfxApp->IsDispatcherLocked();
+ if ( pSlot && IsLocked( pSlot->GetSlotId() ) )
+ {
+ if ( bAllLocked )
+ pSfxApp->Get_Impl()->bInvalidateOnUnlock = sal_True;
+ pImp->bInvalidateOnUnlock = sal_True;
+ DBG_PROFSTOP(SfxDispatcherFillState);
+ return sal_False;
+ }
+
+ if ( pSlot )
+ {
+ Flush();
+
+ // Objekt ermitteln und Message an diesem Objekt aufrufen
+ SfxShell *pSh = GetShell(rSvr.GetShellLevel());
+ DBG_ASSERT(pSh, "ObjektShell nicht gefunden");
+
+ SfxStateFunc pFunc;
+
+ if (pRealSlot)
+ pFunc = pRealSlot->GetStateFnc();
+ else
+ pFunc = pSlot->GetStateFnc();
+
+ pSh->CallState( pFunc, rState );
+#ifdef DBG_UTIL
+ // pr"ufen, ob IDL (SlotMap) und aktuelle Items "ubereinstimmen
+ if ( DbgIsAssertWarning() && rState.Count() )
+ {
+ SfxInterface *pIF = pSh->GetInterface();
+ SfxItemIter aIter( rState );
+ for ( const SfxPoolItem *pItem = aIter.FirstItem();
+ pItem;
+ pItem = aIter.NextItem() )
+ if ( !IsInvalidItem(pItem) && !pItem->ISA(SfxVoidItem) )
+ {
+ sal_uInt16 nSlotId = rState.GetPool()->GetSlotId(pItem->Which());
+ if ( !pItem->IsA(pIF->GetSlot(nSlotId)->GetType()->Type()) )
+ {
+ ByteString aMsg( "item-type unequal to IDL (=> no BASIC)" );
+ aMsg += "\nwith SID: ";
+ aMsg += ByteString::CreateFromInt32( nSlotId );
+ aMsg += "\nin ";
+ aMsg += pIF->GetClassName();
+ DbgOut( aMsg.GetBuffer(), DBG_OUT_ERROR, __FILE__, __LINE__);
+ }
+ }
+ }
+#endif
+
+ DBG_PROFSTOP(SfxDispatcherFillState);
+ return sal_True;
+ }
+
+ DBG_PROFSTOP(SfxDispatcherFillState);
+ return sal_False;
+}
+
+//--------------------------------------------------------------------
+const SfxPoolItem* SfxDispatcher::_Execute( const SfxSlotServer &rSvr )
+
+/* [Beschreibung]
+
+ Diese Methode f"uhrt einen Request "uber einen gecachten <Slot-Server>
+ aus.
+*/
+
+{
+ const SfxSlot *pSlot = rSvr.GetSlot();
+ if ( IsLocked( pSlot->GetSlotId() ) )
+ return 0;
+
+ if ( pSlot )
+ {
+ Flush();
+
+ sal_uInt16 nSlot = pSlot->GetSlotId();
+ if ( SfxMacroConfig::IsMacroSlot( nSlot ) )
+ SFX_APP()->GetMacroConfig()->RegisterSlotId( nSlot );
+
+ if ( pSlot->IsMode(SFX_SLOT_ASYNCHRON) )
+ //! ignoriert rSvr
+ {
+ SfxShell *pShell = GetShell( rSvr.GetShellLevel() );
+ SfxDispatcher *pDispat = this;
+ while ( pDispat )
+ {
+ sal_uInt16 nShellCount = pDispat->pImp->aStack.Count();
+ for ( sal_uInt16 n=0; n<nShellCount; n++ )
+ if ( pShell == pDispat->pImp->aStack.Top(n) )
+ {
+ pDispat->pImp->xPoster->Post(
+ new SfxRequest( pSlot->GetSlotId(),
+ SFX_CALLMODE_RECORD, pShell->GetPool() ) );
+// pDispat->pImp->xPoster->Post(new Executer(
+// new SfxRequest( pSlot->GetSlotId(),
+// SFX_CALLMODE_RECORD, pShell->GetPool() ),
+// pSlot, n ));
+ return 0;
+ }
+ }
+ }
+ else
+ {
+ // Objekt ermitteln und Message an diesem Objekt aufrufen
+ SfxShell *pSh = GetShell(rSvr.GetShellLevel());
+ SfxRequest aReq( pSlot->GetSlotId(), SFX_CALLMODE_RECORD, pSh->GetPool() );
+ if ( Call_Impl( *pSh, *pSlot, aReq, sal_True ) ) // von Bindings immer recorden
+ return aReq.GetReturnValue();
+ }
+ }
+ return 0;
+}
+
+//----------------------------------------------------------------------
+void SfxDispatcher::ExecutePopup( sal_uInt16 nConfigId,
+ Window *pWin, const Point *pPos,
+ const SfxPoolItem *pArg1, ... )
+
+/* [Beschreibung]
+
+ Diese Methode f"uhrt das unter der Id nConfigId registrierte PopupMenu
+ aus. Die Regisitrierung wird i.d.R. in <SFX_IMPL_INTERFACE> vorgenommen.
+
+ Bei nConfigId == 0 werden die auf dem Stack des Dispatchers befindlichen
+ <SfxShell>s von oben nach unten nach dem ersten registrieren PopupMenu
+ durchsucht.
+*/
+
+{
+ SfxDispatcher &rDisp = *SFX_APP()->GetDispatcher_Impl();
+ sal_uInt16 nShLevel = 0;
+
+ const SvVerbList *pVerbList = 0;
+
+ // Nur die eigenen Shells nehmen !!
+ sal_uInt16 nMaxShellLevel = rDisp.pImp->aStack.Count();
+
+ SfxShell *pSh;
+ for ( pSh = rDisp.GetShell(nShLevel);
+ pSh && nShLevel < nMaxShellLevel ;
+ ++nShLevel, pSh = rDisp.GetShell(nShLevel) )
+ {
+
+ if (pSh->GetVerbs())
+ {
+ pVerbList = pSh->GetVerbs();
+ break;
+ }
+ }
+
+ nShLevel=0;
+
+ if ( rDisp.pImp->bQuiet )
+ {
+ nConfigId = 0;
+ nShLevel = rDisp.pImp->aStack.Count();
+ }
+
+ Window *pWindow = pWin ? pWin :
+ SFX_APP()->GetWorkWindow_Impl( rDisp.pImp->pFrame )->GetWindow();
+
+ for ( pSh = rDisp.GetShell(nShLevel);
+ pSh;
+ ++nShLevel, pSh = rDisp.GetShell(nShLevel) )
+ {
+ const ResId& rResId = pSh->GetInterface()->GetPopupMenuResId();
+ if ( ( nConfigId == 0 && rResId.GetId() ) ||
+ ( nConfigId != 0 && rResId.GetId() == nConfigId ) )
+ {
+ SfxPopupMenuManager aPop(rResId.GetId(), *rDisp.GetBindings() );
+ aPop.SetResMgr(rResId.GetResMgr());
+ aPop.AddClipboardFunctions();
+ aPop.Initialize();
+
+ if (pVerbList && pVerbList->Count())
+ aPop.InsertVerbs(pVerbList);
+
+ aPop.RemoveDisabledEntries();
+ sal_uInt16 nRetId = aPop.Execute(
+ pPos ? *pPos : pWindow->GetPointerPosPixel(), pWindow );
+ return;
+ }
+ }
+}
+
+//----------------------------------------------------------------------
+void SfxDispatcher::ExecutePopup( sal_uInt16 nConfigId
+ , Window *pWin, const Point *pPos
+ )
+
+/* [Beschreibung]
+
+ Diese Methode f"uhrt das unter der Id nConfigId registrierte PopupMenu
+ aus. Die Regisitrierung wird i.d.R. in <SFX_IMPL_INTERFACE> vorgenommen.
+
+ Bei nConfigId == 0 werden die auf dem Stack des Dispatchers befindlichen
+ <SfxShell>s von oben nach unten nach dem ersten registrieren PopupMenu
+ durchsucht.
+*/
+
+{
+ SfxDispatcher &rDisp = *SFX_APP()->GetDispatcher_Impl();
+ sal_uInt16 nShLevel = 0;
+ const SvVerbList *pVerbList = 0;
+
+ // Nur die eigenen Shells nehmen !!
+ sal_uInt16 nMaxShellLevel = rDisp.pImp->aStack.Count();
+
+ SfxShell *pSh;
+ for ( pSh = rDisp.GetShell(nShLevel);
+ pSh && nShLevel < nMaxShellLevel ;
+ ++nShLevel, pSh = rDisp.GetShell(nShLevel) )
+ {
+
+ if (pSh->GetVerbs())
+ {
+ pVerbList = pSh->GetVerbs();
+ break;
+ }
+ }
+
+ nShLevel=0;
+
+ if ( rDisp.pImp->bQuiet )
+ {
+ nConfigId = 0;
+ nShLevel = rDisp.pImp->aStack.Count();
+ }
+
+ Window *pWindow = pWin ? pWin :
+ SFX_APP()->GetWorkWindow_Impl( rDisp.pImp->pFrame )->GetWindow();
+
+ for ( pSh = rDisp.GetShell(nShLevel);
+ pSh;
+ ++nShLevel, pSh = rDisp.GetShell(nShLevel) )
+ {
+
+ const ResId& rResId = pSh->GetInterface()->GetPopupMenuResId();
+ if ( ( nConfigId == 0 && rResId.GetId() ) ||
+ ( nConfigId != 0 && rResId.GetId() == nConfigId ) )
+ {
+ SfxPopupMenuManager aPop(rResId.GetId(), *rDisp.GetBindings() );
+ aPop.SetResMgr(rResId.GetResMgr());
+ aPop.AddClipboardFunctions();
+ aPop.Initialize();
+ if (pVerbList && pVerbList->Count())
+ aPop.InsertVerbs(pVerbList);
+
+ aPop.RemoveDisabledEntries();
+ sal_uInt16 nRetId = aPop.Execute(
+ pPos ? *pPos : pWindow->GetPointerPosPixel(), pWindow );
+ return;
+ }
+ }
+}
+
+//----------------------------------------------------------------------
+void SfxDispatcher::ExecutePopup( const ResId &rId
+ , Window *pWin, const Point *pPos
+ )
+
+/* [Beschreibung]
+
+ Diese Methode l"adt ein PopupMenu aus der angegebenen Resource und
+ f"uhrt es aus. Die Selektion wird "uber diesen SfxDispatcher ausgef"uhrt.
+*/
+
+{
+ Window *pWindow = pWin ? pWin :
+ SFX_APP()->GetWorkWindow_Impl( pImp->pFrame )->GetWindow();
+
+ SfxPopupMenuManager aPop( rId, *GetBindings() );
+ aPop.AddClipboardFunctions();
+ aPop.Initialize();
+ aPop.RemoveDisabledEntries();
+ sal_uInt16 nRetId = aPop.Execute( pPos ? *pPos : pWindow->GetPointerPosPixel(),
+ pWindow );
+}
+
+//--------------------------------------------------------------------
+void SfxDispatcher::Lock( sal_Bool bLock )
+
+/* [Beschreibung]
+
+ Mit dieser Methode kann der SfxDispatcher gesperrt und freigegeben
+ werden. Ein gesperrter SfxDispatcher f"uhrt keine <SfxRequest>s mehr
+ aus und liefert keine Status-Informationen mehr. Er verh"alt sich
+ so als w"aren alle Slots disabled.
+*/
+
+{
+ SfxBindings* pBindings = GetBindings();
+ if ( !bLock && pImp->bLocked && pImp->bInvalidateOnUnlock )
+ {
+ if ( pBindings )
+ pBindings->InvalidateAll(sal_True);
+ pImp->bInvalidateOnUnlock = sal_False;
+ }
+ else if ( pBindings )
+ pBindings->InvalidateAll(sal_False);
+ pImp->bLocked = bLock;
+}
+
+//--------------------------------------------------------------------
+void SfxDispatcher::ShowObjectBar(sal_uInt16 nId, SfxShell *pShell) const
+
+/* [Beschreibung]
+
+ Mit dieser Methode kann auf einer Objektleistenposition gezielt eine
+ bestimmte Objektleiste eingeblendet werden.
+*/
+
+{
+ ResId aResId(nId);
+ sal_uInt16 nPos = USHRT_MAX;
+ sal_uInt16 nNo;
+ SfxInterface *pIFace;
+
+ if ( pShell )
+ {
+ // Nur in der Shell suchen
+ pIFace = pShell->GetInterface();
+ for ( nNo=0; nNo<pIFace->GetObjectBarCount(); nNo++ )
+ {
+ if (pIFace->GetObjectBarResId(nNo).GetId() == nId)
+ {
+ nPos = pIFace->GetObjectBarPos(nNo);
+ break;
+ }
+ }
+ }
+ else
+ {
+ // Alle Shells absuchen
+ for ( sal_uInt16 nIdx=0; (pShell=GetShell(nIdx)); nIdx++ )
+ {
+ pIFace = pShell->GetInterface();
+ for ( nNo=0; nNo<pIFace->GetObjectBarCount(); nNo++ )
+ {
+ if (pIFace->GetObjectBarResId(nNo).GetId() == nId)
+ {
+ nPos = pIFace->GetObjectBarPos(nNo);
+ break;
+ }
+ }
+
+ if ( nPos != USHRT_MAX )
+ break;
+ }
+ }
+
+ if ( nPos != USHRT_MAX )
+ {
+ // Auf jeden Fall eintragen, auch wenn unsichtbar. Dann kann
+ // WorkWindow anbieten, wieder anzuschalten
+ SfxObjectBars_Impl& rBar = pImp->aObjBars[nPos & SFX_POSITION_MASK];
+ SfxObjectBars_Impl& rFixed = pImp->aFixedObjBars[nPos & SFX_POSITION_MASK];
+
+ sal_uInt16 nOldId = rBar.aResId.GetId();
+
+ if ( pImp->bReadOnly && !( nPos & SFX_VISIBILITY_READONLYDOC ) )
+ return;
+
+ sal_uInt32 nFeature = pIFace->GetObjectBarFeature(nNo);
+ if ( nFeature && !pShell->HasUIFeature( nFeature ) )
+ return;
+
+ sal_Bool bVisible = pIFace->IsObjectBarVisible(nNo);
+ if ( !bVisible )
+ // Alle Sichtbarkeitsflags ausschalten
+ nPos &= SFX_POSITION_MASK;
+
+ aResId.SetResMgr( pIFace->GetObjectBarResId(nNo).GetResMgr() );
+ rBar.aResId = aResId;
+ rBar.nMode = nPos;
+ const String *pName = pIFace->GetObjectBarName(nNo);
+ if ( pName )
+ rBar.aName = *pName;
+ else
+ rBar.aName.Erase();
+ rBar.pIFace = pIFace;
+
+ rFixed = rBar;
+
+ if ( nOldId != aResId.GetId() && pImp->bUpdated )
+ {
+ SfxWorkWindow *pWorkWin = SFX_APP()->GetWorkWindow_Impl(pImp->pFrame);
+ pWorkWin->SetObjectBar_Impl( nPos, aResId, pIFace, pName );
+ pWorkWin->UpdateObjectBars_Impl();
+ }
+
+ if ( !bVisible )
+ {
+ rBar.aResId = ResId( 0,0 );
+ rFixed.aResId = ResId( 0,0 );
+ }
+
+ return;
+ }
+
+// DBG_ERROR("Objektleiste nicht bekannt!");
+}
+
+sal_uInt16 SfxDispatcher::GetObjectBarId( sal_uInt16 nPos ) const
+{
+ return pImp->aObjBars[nPos].aResId.GetId();
+}
+
+//--------------------------------------------------------------------
+void SfxDispatcher::ResetObjectBars_Impl()
+
+/* [Beschreibung]
+
+ Mit dieser Methode werden alle Objectbar-Anforderungen, die dieser
+ Dispatcher an das AppWindow hat, beseitigt.
+*/
+{
+ for (sal_uInt16 n=0; n<SFX_OBJECTBAR_MAX; n++)
+ pImp->aObjBars[n].aResId = ResId( 0,0 );
+ pImp->aChildWins.Remove(0, pImp->aChildWins.Count());
+}
+
+
+//--------------------------------------------------------------------
+void SfxDispatcher::DebugOutput_Impl() const
+{
+#ifdef DBG_UTIL
+
+ sal_uInt16 nOld = (sal_uInt16) DbgGetData()->nTraceOut;
+ DbgGetData()->nTraceOut = DBG_OUT_FILE;
+
+ if (pImp->bFlushed)
+ DBG_TRACE("Flushed");
+ if (pImp->bUpdated)
+ DBG_TRACE("Updated");
+
+ for ( sal_uInt16 nShell = pImp->aStack.Count(); nShell > 0; --nShell )
+ {
+ SfxShell *pShell = GetShell(nShell-1);
+ const SfxInterface *pIFace = pShell->GetInterface();
+ DBG_TRACE (pIFace->GetClassName());
+ }
+
+ DbgGetData()->nTraceOut = nOld;
+
+#endif
+}
+
+void SfxDispatcher::LockUI_Impl( sal_Bool bLock )
+{
+ sal_Bool bWasLocked = pImp->bUILocked;
+ pImp->bUILocked = bLock;
+ if ( !bLock && bWasLocked )
+ Update_Impl( sal_True );
+}
+
+//-------------------------------------------------------------------------
+void SfxDispatcher::HideUI( sal_Bool bHide )
+{
+// if ( !bHide && pImp->bReadOnly )
+// bHide = sal_True;
+ sal_Bool bWasHidden = pImp->bNoUI;
+ pImp->bNoUI = bHide;
+ if ( bHide != bWasHidden )
+ Update_Impl( sal_True );
+}
+
+void SfxDispatcher::SetReadOnly_Impl( sal_Bool bOn )
+{
+ pImp->bReadOnly = bOn;
+// pImp->bNoUI = bOn;
+}
+
+sal_Bool SfxDispatcher::GetReadOnly_Impl() const
+{
+ return pImp->bReadOnly;
+}
+
+//-------------------------------------------------------------------------
+void SfxDispatcher::SetQuietMode_Impl( sal_Bool bOn )
+
+/* [Beschreibung]
+
+ Bei 'bOn' stellt sich dieser Dispatcher quasi tot und leitet alles
+ an den Parent-Dispatcher weiter.
+*/
+
+{
+ pImp->bQuiet = bOn;
+ SfxBindings* pBindings = GetBindings();
+ if ( pBindings )
+ pBindings->InvalidateAll(sal_True);
+}
+
+//-------------------------------------------------------------------------
+void SfxDispatcher::SetModalMode_Impl( sal_Bool bOn )
+
+/* [Beschreibung]
+
+ Bei 'bOn' werden nur noch Slots des Parent-Dispatchers gefunden.
+*/
+
+{
+ pImp->bModal = bOn;
+ SfxBindings* pBindings = GetBindings();
+ if ( pBindings )
+ pBindings->InvalidateAll(sal_True);
+}
+
+void SfxDispatcher::SetExecuteMode( sal_uInt16 nMode )
+{
+ pImp->nStandardMode = nMode;
+}
+
+SfxItemState SfxDispatcher::QueryState( sal_uInt16 nSlot, const SfxPoolItem* &rpState )
+{
+ SfxShell *pShell = 0;
+ const SfxSlot *pSlot = 0;
+ if ( GetShellAndSlot_Impl( nSlot, &pShell, &pSlot, sal_False, sal_False ) )
+ {
+ rpState = pShell->GetSlotState(nSlot);
+ if ( !rpState )
+ return SFX_ITEM_DISABLED;
+ else
+ return SFX_ITEM_AVAILABLE;
+ }
+
+ return SFX_ITEM_DISABLED;
+}
+
+sal_Bool SfxDispatcher::IsReadOnlyShell_Impl( sal_uInt16 nShell ) const
+{
+ sal_uInt16 nShellCount = pImp->aStack.Count();
+ if ( nShell < nShellCount )
+ {
+ if( nShell == nShellCount - 1 )
+ return pImp->aStack.Bottom()->ISA( SfxModule ) ?
+ sal_False : pImp->bReadOnly;
+ else return pImp->bReadOnly;
+ }
+ else if ( pImp->pParent )
+ return pImp->pParent->IsReadOnlyShell_Impl( nShell - nShellCount );
+ return sal_True;
+}
+
+// Ein dirty trick, um an die Methoden der private base class von
+// SfxShellStack_Impl heranzukommen
+class StackAccess_Impl : public SfxShellStack_Implarr_
+{};
+
+void SfxDispatcher::InsertShell_Impl( SfxShell& rShell, sal_uInt16 nPos )
+{
+ Flush();
+
+ // Der cast geht, weil SfxShellStack_Impl keine eigenen member hat
+ ((StackAccess_Impl*) (&pImp->aStack))->Insert( nPos, &rShell );
+ rShell.SetDisableFlags( pImp->nDisableFlags );
+ rShell.DoActivate(pImp->pFrame, sal_True);
+
+ if ( !SFX_APP()->IsDowning() )
+ {
+ pImp->bUpdated = sal_False;
+ pImp->pCachedServ1 = 0;
+ pImp->pCachedServ2 = 0;
+ InvalidateBindings_Impl(sal_True);
+ }
+}
+
+void SfxDispatcher::RemoveShell_Impl( SfxShell& rShell )
+{
+ Flush();
+
+ // Der cast geht, weil SfxShellStack_Impl keine eigenen member hat
+ StackAccess_Impl& rStack = *((StackAccess_Impl*) (&pImp->aStack));
+ sal_uInt16 nCount = rStack.Count();
+ for ( sal_uInt16 n=0; n<nCount; ++n )
+ {
+ if ( rStack[n] == &rShell )
+ {
+ rStack.Remove( n );
+ rShell.SetDisableFlags( 0 );
+ rShell.DoDeactivate(pImp->pFrame, sal_True);
+ break;
+ }
+ }
+
+ if ( !SFX_APP()->IsDowning() )
+ {
+ pImp->bUpdated = sal_False;
+ pImp->pCachedServ1 = 0;
+ pImp->pCachedServ2 = 0;
+ InvalidateBindings_Impl(sal_True);
+ }
+}
+
+sal_Bool SfxDispatcher::IsAllowed
+(
+ sal_uInt16 nSlot
+) const
+/*
+ [Beschreibung]
+ Die Methode prueft, ob der Zugriff auf diese Schnittstelle erlaubt ist.
+ */
+{
+ if ( !pImp->pDisableList )
+ {
+ return sal_True;
+ }
+
+ // BinSearch in der DisableListe
+ SvUShorts& rList = *pImp->pDisableList;
+ sal_uInt16 nCount = rList.Count();
+ sal_uInt16 nLow = 0, nMid, nHigh;
+ sal_Bool bFound = sal_False;
+ nHigh = nCount - 1;
+
+ while ( !bFound && nLow <= nHigh )
+ {
+ nMid = (nLow + nHigh) >> 1;
+ DBG_ASSERT( nMid < nCount, "bsearch ist buggy" );
+
+ int nDiff = (int) nSlot - (int) rList[nMid];
+ if ( nDiff < 0)
+ {
+ if ( nMid == 0 )
+ break;
+ nHigh = nMid - 1;
+ }
+ else if ( nDiff > 0 )
+ {
+ nLow = nMid + 1;
+ if ( nLow == 0 )
+ break;
+ }
+ else
+ bFound = sal_True;
+ }
+
+ // Slot in der Liste gefunden ?
+ sal_uInt16 nPos = bFound ? nMid : nLow;
+
+ DBG_ASSERT( nPos <= nCount, "" );
+ DBG_ASSERT( nPos == nCount || nSlot <= rList[nPos], "" );
+ DBG_ASSERT( nPos == 0 || nSlot > rList[nPos-1], "" );
+ DBG_ASSERT( ( (nPos+1) >= nCount ) || nSlot < rList[nPos+1], "" );
+
+ return !bFound;
+}
+
+void SfxDispatcher::InvalidateBindings_Impl( sal_Bool bModify )
+{
+ // App-Dispatcher?
+ if ( IsAppDispatcher() )
+ {
+ for ( SfxViewFrame *pFrame = SfxViewFrame::GetFirst();
+ pFrame;
+ pFrame = SfxViewFrame::GetNext( *pFrame ) )
+ pFrame->GetBindings().InvalidateAll(bModify);
+/*
+ // alle Bindings sind betroffen
+ for ( SfxInPlaceFrame *pIPFrame = (SfxInPlaceFrame*)
+ SfxViewFrame::GetFirst(0, TYPE(SfxInPlaceFrame));
+ pIPFrame;
+ pIPFrame = (SfxInPlaceFrame*)
+ SfxViewFrame::GetNext(*pIPFrame, 0, TYPE(SfxInPlaceFrame)) )
+ pIPFrame->GetBindings().InvalidateAll(bModify);
+
+ for ( SfxPlugInFrame *pPIFrame = (SfxPlugInFrame*)
+ SfxViewFrame::GetFirst(0, TYPE(SfxPlugInFrame));
+ pPIFrame;
+ pPIFrame = (SfxPlugInFrame*)
+ SfxViewFrame::GetNext(*pPIFrame, 0, TYPE(SfxPlugInFrame)) )
+ pPIFrame->GetBindings().InvalidateAll(bModify);
+
+ for ( SfxTask* pTask = SfxTask::GetFirst(); pTask;
+ pTask = SfxTask::GetNext( *pTask ) )
+ if ( !pTask->IsExternal() )
+ pTask->GetBindings()->InvalidateAll(bModify);
+*/
+ }
+ else
+ {
+ SfxDispatcher *pDisp = GetBindings()->GetDispatcher_Impl();
+ while ( pDisp )
+ {
+ if ( pDisp == this )
+ {
+ GetBindings()->InvalidateAll( bModify );
+ break;
+ }
+
+ pDisp = pDisp->pImp->pParent;
+ }
+ }
+}
+
+sal_uInt16 SfxDispatcher::GetNextToolBox_Impl( sal_uInt16 nPos, sal_uInt16 nType, String *pStr )
+{
+ SfxShell *pShell;
+ sal_Bool bReadOnly = sal_False;
+ SfxViewFrame *pFrame = pImp->pFrame;
+ if ( pFrame )
+ {
+ SfxObjectShell *pObj = pFrame->GetObjectShell();
+ bReadOnly = !pObj || pObj->IsReadOnly();
+ }
+
+ sal_Bool bFound = sal_False;
+ SfxWorkWindow *pWorkWin = GetBindings()->GetWorkWindow_Impl();
+
+ // Wenn die aktuelle Toolbox die letzte ist, mu\s die erste zur"uckgegeben
+ // werden
+ sal_uInt16 nNext = 0;
+
+ if ( nPos != 0xFFFF )
+ {
+ SfxDispatcher *pDispat = this;
+ while ( pDispat )
+ {
+ SfxBindings* pBindings = pDispat->GetBindings();
+ if ( !pBindings || pBindings->GetWorkWindow_Impl() != pWorkWin )
+ break;
+
+ sal_uInt16 nCount = pDispat->pImp->aStack.Count();
+ // Alle interfaces auf dem Dispatcher-Stack durchsuchen
+ for ( sal_uInt16 nIdx=0; nIdx<nCount; nIdx++ )
+ {
+ pShell = pDispat->pImp->aStack.Top(nIdx);
+ const SfxInterface *pInterFace = pShell->GetInterface();
+ for ( sal_uInt16 nNo = 0; pInterFace && nNo<pInterFace->GetObjectBarCount(); ++nNo )
+ {
+ // Ist die Objectbar an der richtigen Position und sichtbar ?
+ sal_uInt16 nP = pInterFace->GetObjectBarPos(nNo);
+
+ if ( (nP & SFX_POSITION_MASK) == (nPos & SFX_POSITION_MASK) &&
+ pInterFace->IsObjectBarVisible(nNo) &&
+ ( !bReadOnly || ( nP & SFX_VISIBILITY_READONLYDOC ) ) )
+ {
+ sal_uInt16 nId = pInterFace->GetObjectBarResId(nNo).GetId();
+ if ( nId != nType )
+ {
+ // Es ist eine andere Toolbox
+ // Ist sie aktivierbar ?
+ sal_uInt32 nFeature = pInterFace->GetObjectBarFeature( nNo );
+ if ( nFeature && !pShell->HasUIFeature( nFeature ) )
+ continue;
+
+ // Kommt sie nach der aktuellen ?
+ if ( bFound )
+ {
+ // Ja, also ist sie die n"achste
+ if ( pStr )
+ *pStr = *pInterFace->GetObjectBarName( nNo );
+ return nId;
+ }
+ else if ( !nNext )
+ {
+ // Nein, aber vielleicht ist es die erste ?
+ nNext = nId;
+ if ( pStr )
+ *pStr = *pInterFace->GetObjectBarName( nNo );
+ }
+ }
+ else
+ // das ist die aktuelle!
+ bFound = sal_True;
+ }
+ }
+ }
+
+ pDispat = pDispat->pImp->pParent;
+ }
+ }
+
+ return nNext;
+}
+
+sal_Bool SfxDispatcher::IsUpdated_Impl() const
+{
+ return pImp->bUpdated;
+}
+
+void SfxDispatcher::SetDisableFlags( sal_uInt32 nFlags )
+{
+ pImp->nDisableFlags = nFlags;
+ for ( int i = int(pImp->aStack.Count()) - 1; i >= 0; --i )
+ pImp->aStack.Top( (sal_uInt16) i )->SetDisableFlags( nFlags );
+}
+
+sal_uInt32 SfxDispatcher::GetDisableFlags() const
+{
+ return pImp->nDisableFlags;
+}
+
+sal_Bool SfxDispatcher::HasSlot_Impl( sal_uInt16 nSlot )
+{
+ Flush();
+ sal_uInt16 nTotCount = pImp->aStack.Count();
+
+ if ( pImp->pParent && !pImp->pParent->pImp->pFrame )
+ {
+ // the last frame also uses the AppDispatcher
+ nTotCount += pImp->aStack.Count();
+ }
+
+ if ( SfxMacroConfig::IsMacroSlot( nSlot ) )
+ // Makro-Slot?
+ return sal_True;
+ else if (nSlot >= SID_VERB_START && nSlot <= SID_VERB_END)
+ {
+ // Verb-Slot?
+ SfxShell *pSh = 0;
+ for ( sal_uInt16 nShell = 0; pSh = GetShell(nShell); ++nShell )
+ {
+ if ( pSh->ISA(SfxViewShell) )
+ return sal_True;
+ }
+
+ return sal_False;
+ }
+
+ // SID gegen gesetzten Filter pr"ufen
+ sal_uInt16 nSlotEnableMode=0;
+ if ( pImp->pFrame )
+ {
+ nSlotEnableMode = IsSlotEnabledByFilter_Impl( nSlot );
+ if ( 0 == nSlotEnableMode )
+ return sal_False;
+ }
+
+ // im Quiet-Mode nur Parent-Dispatcher
+ if ( pImp->bQuiet )
+ return sal_False;
+
+ sal_Bool bReadOnly = ( 2 != nSlotEnableMode && pImp->bReadOnly ) ||
+ ( pImp->pFrame && pImp->pFrame->GetObjectShell() &&
+ pImp->pFrame->GetObjectShell()->IsLoading() );
+
+ for ( sal_uInt16 i=0 ; i < nTotCount; ++i )
+ {
+ SfxShell *pObjShell = GetShell(i);
+ SfxInterface *pIFace = pObjShell->GetInterface();
+ const SfxSlot *pSlot = pIFace->GetSlot(nSlot);
+ if ( pSlot && pSlot->nDisableFlags && ( pSlot->nDisableFlags & pObjShell->GetDisableFlags() ) != 0 )
+ return sal_False;
+
+ if ( pSlot && !( pSlot->nFlags & SFX_SLOT_READONLYDOC ) && bReadOnly )
+ return sal_False;
+
+ if ( pSlot )
+ {
+ // Slot geh"ort zum Container?
+ FASTBOOL bIsContainerSlot = pSlot->IsMode(SFX_SLOT_CONTAINER);
+ FASTBOOL bIsInPlace = pImp->pFrame && pImp->pFrame->ISA( SfxInPlaceFrame );
+
+ // Shell geh"ort zum Server?
+ // AppDispatcher oder IPFrame-Dispatcher
+ FASTBOOL bIsServerShell = !pImp->pFrame || bIsInPlace;
+
+ // Nat"urlich sind ServerShell-Slots auch ausf"uhrbar, wenn sie auf
+ // einem Container-Dispatcher ohne IPClient ausgef"uhrt werden sollen.
+ if ( !bIsServerShell )
+ {
+ SfxViewShell *pViewSh = pImp->pFrame->GetViewShell();
+ bIsServerShell = !pViewSh || !pViewSh->GetIPClient();
+ }
+
+ // Shell geh"ort zum Container?
+ // AppDispatcher oder kein IPFrameDispatcher
+ FASTBOOL bIsContainerShell = !pImp->pFrame || !bIsInPlace;
+
+ // Shell und Slot passen zusammen
+ if ( !( ( bIsContainerSlot && bIsContainerShell ) ||
+ ( !bIsContainerSlot && bIsServerShell ) ) )
+ pSlot = 0;
+ }
+
+ if ( pSlot && !IsAllowed( nSlot ) )
+ pSlot = NULL;
+
+ if ( pSlot )
+ return sal_True;
+ }
+
+ return sal_False;
+}
+
+
diff --git a/sfx2/source/control/macrconf.cxx b/sfx2/source/control/macrconf.cxx
new file mode 100644
index 000000000000..2e9625af311f
--- /dev/null
+++ b/sfx2/source/control/macrconf.cxx
@@ -0,0 +1,947 @@
+/*************************************************************************
+ *
+ * $RCSfile: macrconf.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 16:52:29 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+#if SUPD<582
+#ifndef _SFXSFXJS_HXX //autogen
+#include <sfxjs.hxx>
+#endif
+#ifndef _SJIMPL2_HXX //autogen
+#include <sj2/sjimpl2.hxx>
+#endif
+#endif
+#ifndef _SB_SBSTAR_HXX //autogen
+#include <basic/sbstar.hxx>
+#endif
+#ifndef _BASMGR_HXX //autogen
+#include <basic/basmgr.hxx>
+#endif
+#ifndef _SBX_HXX //autogen
+#include <svtools/sbx.hxx>
+#endif
+#ifndef _SB_SBMETH_HXX //autogen
+#include <basic/sbmeth.hxx>
+#endif
+#ifndef _SB_SBMOD_HXX //autogen
+#include <basic/sbmod.hxx>
+#endif
+#ifndef _INTN_HXX //autogen
+#include <tools/intn.hxx>
+#endif
+#ifndef _BASIC_SBUNO_HXX
+#include <basic/sbuno.hxx>
+#endif
+
+#include <osl/mutex.hxx>
+
+#include <com/sun/star/script/XEngine.hpp>
+
+#pragma hdrstop
+
+#include "msgpool.hxx"
+#include "macrconf.hxx"
+#include "sfxbasic.hxx"
+#include "sfx.hrc"
+#include "app.hxx"
+#include "objsh.hxx"
+#include "dispatch.hxx"
+#include "minfitem.hxx"
+#include "imgmgr.hxx"
+#include "evntconf.hxx"
+#include "docfile.hxx"
+#include "genlink.hxx"
+#include <viewfrm.hxx>
+#include <appdata.hxx>
+
+static const sal_uInt16 nCompatVersion = 2;
+static const sal_uInt16 nVersion = 3;
+
+// Static member
+SfxMacroConfig* SfxMacroConfig::pMacroConfig = NULL;
+
+SfxMacroConfig* SfxMacroConfig::GetOrCreate()
+{
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
+ if ( !pMacroConfig )
+ pMacroConfig = new SfxMacroConfig;
+ return pMacroConfig;
+}
+
+void SfxMacroConfig::Release_Impl()
+{
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
+ DELETEZ( pMacroConfig );
+}
+
+//==========================================================================
+
+struct SfxMacroConfig_Impl
+{
+ SfxMacroInfoArr_Impl aArr;
+ sal_uInt32 nEventId;
+ sal_Bool bWaitingForCallback;
+
+ SfxMacroConfig_Impl()
+ : nEventId( 0 )
+ , bWaitingForCallback( sal_False )
+ {}
+};
+
+//==========================================================================
+
+SbMethod* SfxQueryMacro_Impl( BasicManager* pMgr , const String& rMacro,
+ const String &rLibName, const String& rModule )
+{
+ const International &rInter = Application::GetAppInternational();
+
+ sal_uInt16 nLibCount = pMgr->GetLibCount();
+ for ( sal_uInt16 nLib = 0; nLib < nLibCount; ++nLib )
+ {
+ if ( COMPARE_EQUAL == rInter.Compare( pMgr->GetLibName( nLib ), rLibName, INTN_COMPARE_IGNORECASE ) )
+ {
+ StarBASIC* pLib = pMgr->GetLib( nLib );
+ if( !pLib )
+ {
+ pMgr->LoadLib( nLib );
+ pLib = pMgr->GetLib( nLib );
+ }
+
+ if( pLib )
+ {
+ sal_uInt16 nModCount = pLib->GetModules()->Count();
+ for( sal_uInt16 nMod = 0; nMod < nModCount; ++nMod )
+ {
+ SbModule* pMod = (SbModule*)pLib->GetModules()->Get( nMod );
+ if ( pMod &&
+ COMPARE_EQUAL == rInter.Compare( pMod->GetName(), rModule, INTN_COMPARE_IGNORECASE ) )
+ {
+ SbMethod* pMethod =
+ (SbMethod*)pMod->Find( rMacro, SbxCLASS_METHOD );
+ if( pMethod )
+ return pMethod;
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+SbMethod* SfxQueryMacro( BasicManager* pMgr , const String& rMacro )
+{
+ sal_uInt16 nLast = 0;
+ String aMacro = rMacro;
+ String aLibName = aMacro.GetToken( 0, '.', nLast );
+ String aModule = aMacro.GetToken( 0, '.', nLast );
+ aMacro.Erase( 0, nLast );
+
+ return SfxQueryMacro_Impl( pMgr, aMacro, aLibName, aModule );
+}
+
+ErrCode SfxCallMacro( BasicManager* pMgr, const String& rCode,
+ SbxArray *pArgs, SbxValue *pRet )
+{
+ ErrCode nErr;
+ SfxApplication *pApp = SFX_APP();
+ pApp->EnterBasicCall();
+ SbMethod* pMethod = SfxQueryMacro( pMgr, rCode );
+ if ( pMethod )
+ {
+ if ( pArgs )
+ pMethod->SetParameters( pArgs );
+ nErr = pMethod->Call( pRet );
+ }
+ else
+ nErr = ERRCODE_BASIC_PROC_UNDEFINED;
+
+ pApp->LeaveBasicCall();
+ return nErr;
+}
+
+//==========================================================================
+
+SfxMacroInfo::SfxMacroInfo( SfxObjectShell *pDoc ) :
+ bAppBasic(pDoc == NULL),
+ nSlotId(0),
+ nRefCnt(0),
+ pSlot(0),
+ pHelpText(0)
+{}
+
+//==========================================================================
+
+SfxMacroInfo::SfxMacroInfo(SfxObjectShell *pDoc, const String& rLibName,
+ const String& rModuleName, const String& rMethodName) :
+ aLibName(rLibName),
+ aModuleName(rModuleName),
+ aMethodName(rMethodName),
+ nSlotId(0),
+ nRefCnt(0),
+ pSlot(0),
+ pHelpText(0)
+{
+ bAppBasic = (pDoc == 0);
+}
+
+//==========================================================================
+
+SfxMacroInfo::SfxMacroInfo(SfxObjectShell *pDoc, const String& rQualifiedName )
+: nSlotId(0),
+ nRefCnt(0),
+ pSlot(0),
+ pHelpText(0)
+{
+ sal_uInt16 nCount = rQualifiedName.GetTokenCount('.');
+ aMethodName = rQualifiedName.GetToken( nCount-1, '.' );
+ if ( nCount > 1 )
+ aModuleName = rQualifiedName.GetToken( nCount-2, '.' );
+ if ( nCount > 2 )
+ aLibName = rQualifiedName.GetToken( 0, '.' );
+ bAppBasic = (pDoc == 0);
+}
+
+//==========================================================================
+
+SfxMacroInfo::SfxMacroInfo(SfxMacroInfo& rOther) :
+ bAppBasic(rOther.bAppBasic),
+ aLibName(rOther.aLibName),
+ aModuleName(rOther.aModuleName),
+ aMethodName(rOther.aMethodName),
+ nSlotId(rOther.nSlotId),
+ pSlot(0),
+ nRefCnt(0),
+ pHelpText(0)
+{}
+
+//==========================================================================
+
+SfxMacroInfo::~SfxMacroInfo()
+{
+ delete pSlot;
+ delete pHelpText;
+}
+
+//==========================================================================
+
+sal_Bool SfxMacroInfo::operator==(const SfxMacroInfo& rOther) const
+{
+ if ( GetQualifiedName() == rOther.GetQualifiedName() &&
+ bAppBasic == rOther.bAppBasic )
+ return sal_True;
+ else
+ return sal_False;
+}
+
+//==========================================================================
+
+String SfxMacroInfo::GetMacroName() const
+{
+ String aMacroName = aMethodName;
+ aMacroName += '(';
+ aMacroName += aLibName;
+ aMacroName += '.';
+ aMacroName += aModuleName;
+ aMacroName += ')';
+ return aMacroName;
+}
+
+//==========================================================================
+
+String SfxMacroInfo::GetQualifiedName() const
+{
+ String aMacroName;
+ if( aMacroName.Len() || aLibName.Len() )
+ {
+ // Altes Format
+ aMacroName = aLibName;
+ aMacroName += '.';
+ aMacroName += aModuleName;
+ aMacroName += '.';
+ }
+
+ // Wg. ::com::sun::star::script::JavaScript kein Zerlegen des Strings mehr
+ aMacroName += aMethodName;
+ return aMacroName;
+}
+
+String SfxMacroInfo::GetFullQualifiedName() const
+{
+ // Liefert nur Unsinn, wenn f"ur ein ::com::sun::star::script::JavaScript aufgerufen !
+ String aRet;
+ if ( bAppBasic )
+ aRet = SFX_APP()->GetName();
+ aRet += '.';
+ aRet += GetQualifiedName();
+ return aRet;
+}
+
+//==========================================================================
+
+BasicManager* SfxMacroInfo::GetBasicManager() const
+{
+ if (bAppBasic)
+ {
+ return SFX_APP()->GetBasicManager();
+ }
+ else
+ {
+ SfxObjectShell *pDocShell = SfxObjectShell::Current();
+ return pDocShell ? pDocShell->GetBasicManager() :
+ SFX_APP()->GetBasicManager();
+ }
+}
+
+//==========================================================================
+
+String SfxMacroInfo::GetBasicName() const
+{
+ if (bAppBasic)
+ {
+ return SFX_APP()->GetName();
+ }
+ else
+ {
+ SfxObjectShell *pDocShell = SfxObjectShell::Current();
+ if ( pDocShell )
+ return pDocShell->GetTitle();
+ else
+ return SFX_APP()->GetName();
+ }
+}
+
+String SfxMacroInfo::GetHelpText() const
+{
+ if ( pHelpText )
+ return *pHelpText;
+ return String();
+}
+
+String SfxMacroConfig::RequestHelp( sal_uInt16 nId )
+{
+ SfxMacroInfo *pInfo = SFX_APP()->GetMacroConfig()->GetMacroInfo( nId );
+ if ( !pInfo )
+ return String();
+
+ if ( !pInfo->pHelpText )
+ {
+ SbMethod *pMethod =
+ SfxQueryMacro_Impl( pInfo->GetBasicManager(), pInfo->aMethodName,
+ pInfo->aLibName, pInfo->aModuleName );
+ if ( pMethod && pMethod->GetInfo() )
+ pInfo->pHelpText = new String( pMethod->GetInfo()->GetComment() );
+ }
+
+ return pInfo->GetHelpText();
+}
+
+void SfxMacroInfo::SetHelpText( const String& rName )
+{
+ if ( !pHelpText )
+ pHelpText = new String;
+ *pHelpText = rName;
+}
+
+//==========================================================================
+
+SvStream& operator >> (SvStream& rStream, SfxMacroInfo& rInfo)
+{
+ sal_uInt16 nAppBasic, nFileVersion;
+ String aDocName;
+
+ rStream >> nFileVersion;
+ if ( nVersion < nCompatVersion )
+ {
+ // In der 1.Version ohne Versionskennung
+ nAppBasic = nVersion;
+ nFileVersion = 1;
+ rStream.ReadByteString(aDocName,RTL_TEXTENCODING_UTF8);
+ rStream.ReadByteString(rInfo.aLibName,RTL_TEXTENCODING_UTF8);
+ rStream.ReadByteString(rInfo.aModuleName,RTL_TEXTENCODING_UTF8);
+ rStream.ReadByteString(rInfo.aMethodName,RTL_TEXTENCODING_UTF8);
+ }
+ else
+ {
+ String aInput;
+ rStream >> nAppBasic;
+ rStream.ReadByteString(aDocName,RTL_TEXTENCODING_UTF8); // Vorsicht: kann bei AppName Unsinn sein!
+ rStream.ReadByteString(rInfo.aLibName,RTL_TEXTENCODING_UTF8);
+ rStream.ReadByteString(rInfo.aModuleName,RTL_TEXTENCODING_UTF8);
+ rStream.ReadByteString(aInput,RTL_TEXTENCODING_UTF8);
+
+ if ( nFileVersion == nCompatVersion )
+ rInfo.aMethodName = aInput;
+ else
+ {
+ sal_uInt16 nCount = aInput.GetTokenCount('.');
+ rInfo.aMethodName = aInput.GetToken( nCount-1, '.' );
+ if ( nCount > 1 )
+ rInfo.aModuleName = aInput.GetToken( nCount-2, '.' );
+ if ( nCount > 2 )
+ rInfo.aLibName = aInput.GetToken( 0, '.' );
+ }
+ }
+
+ rInfo.bAppBasic = (sal_Bool) nAppBasic;
+ rInfo.nSlotId = SFX_APP()->GetMacroConfig()->GetSlotId(&rInfo);
+ return rStream;
+}
+
+//==========================================================================
+
+SvStream& operator << (SvStream& rStream, const SfxMacroInfo& rInfo)
+{
+ if ( rInfo.bAppBasic )
+ {
+ rStream << nVersion
+ << (sal_uInt16) rInfo.bAppBasic;
+ rStream.WriteByteString(rInfo.GetBasicName(),RTL_TEXTENCODING_UTF8);
+ rStream.WriteByteString(rInfo.aLibName,RTL_TEXTENCODING_UTF8);
+ rStream.WriteByteString(rInfo.aModuleName,RTL_TEXTENCODING_UTF8);
+ rStream.WriteByteString(rInfo.aMethodName,RTL_TEXTENCODING_UTF8);
+ }
+ else
+ {
+ rStream << nVersion
+ << (sal_uInt16) rInfo.bAppBasic;
+ rStream.WriteByteString(SFX_APP()->GetName(),RTL_TEXTENCODING_UTF8);
+ rStream.WriteByteString(rInfo.aLibName,RTL_TEXTENCODING_UTF8);
+ rStream.WriteByteString(rInfo.aModuleName,RTL_TEXTENCODING_UTF8);
+ rStream.WriteByteString(rInfo.aMethodName,RTL_TEXTENCODING_UTF8);
+ }
+
+ return rStream;
+}
+
+sal_Bool SfxMacroInfo::Compare( const SvxMacro& rMacro ) const
+{
+ String aName = rMacro.GetLibName();
+ aName += '.';
+ aName += rMacro.GetMacName();
+ if ( GetFullQualifiedName() == aName )
+ return sal_True;
+ return sal_False;
+}
+
+//==========================================================================
+
+SfxMacroConfig::SfxMacroConfig()
+{
+ pImp = new SfxMacroConfig_Impl;
+}
+
+//==========================================================================
+
+SfxMacroConfig::~SfxMacroConfig()
+{
+ if ( pImp->nEventId )
+ Application::RemoveUserEvent( pImp->nEventId );
+ delete pImp;
+}
+
+//==========================================================================
+
+SFX_STATE_STUB( SfxApplication, MacroState_Impl )
+SFX_EXEC_STUB( SfxApplication, MacroExec_Impl )
+
+sal_uInt16 SfxMacroConfig::GetSlotId(SfxMacroInfoPtr pInfo)
+{
+ sal_uInt16 nCount = pImp->aArr.Count(); // Macro suchen
+ sal_uInt16 i;
+ for (i=0; i<nCount; i++)
+ if ((*(pImp->aArr)[i]) == (*pInfo))
+ break;
+
+ if (i == nCount)
+ { // Macro noch unbekannt
+ nCount = aIdArray.Count();
+ sal_uInt16 n;
+ for (n=0; n<nCount; n++) // freie SlotId suchen
+ if (aIdArray[n] > SID_MACRO_START + n)
+ break;
+
+ sal_uInt16 nNewSlotId = SID_MACRO_START + n;
+ if ( nNewSlotId > SID_MACRO_END )
+ return 0;
+ aIdArray.Insert( SID_MACRO_START + n, n );
+
+ SfxSlot *pNewSlot = new SfxSlot;
+ pNewSlot->nSlotId = SID_MACRO_START + n;
+ pNewSlot->nGroupId = 0;
+ pNewSlot->nFlags = SFX_SLOT_ASYNCHRON;
+ pNewSlot->nMasterSlotId = 0;
+ pNewSlot->nValue = 0;
+ pNewSlot->fnExec = SFX_STUB_PTR(SfxApplication,MacroExec_Impl);
+ pNewSlot->fnState = SFX_STUB_PTR(SfxApplication,MacroState_Impl);
+ pNewSlot->pType = 0; HACK(SFX_TYPE(SfxVoidItem))
+ pNewSlot->pName = pNewSlot->pMethodName = U2S(pInfo->aMethodName).getStr();
+ pNewSlot->pLinkedSlot = 0;
+ pNewSlot->nArgDefCount = 0;
+ pNewSlot->pFirstArgDef = 0;
+ pNewSlot->pUnoName = 0;
+
+ if (nCount)
+ {
+ SfxSlot *pSlot = (pImp->aArr)[0]->pSlot;
+ pNewSlot->pNextSlot = pSlot->pNextSlot;
+ pSlot->pNextSlot = pNewSlot;
+ }
+ else
+ pNewSlot->pNextSlot = pNewSlot;
+
+ // Macro uebernehmen
+ SfxMacroInfoPtr pNewInfo = new SfxMacroInfo(*pInfo);
+ pNewInfo->nSlotId = SID_MACRO_START + n;
+ pImp->aArr.Insert(pNewInfo,n);
+ pNewInfo->pSlot = pNewSlot;
+ pInfo->nSlotId = pNewInfo->nSlotId;
+ pNewInfo->nRefCnt++;
+ }
+ else
+ {
+ pInfo->nSlotId = (pImp->aArr)[i]->nSlotId;
+ (pImp->aArr)[i]->nRefCnt++;
+ }
+
+ return pInfo->nSlotId;
+}
+
+//==========================================================================
+
+void SfxMacroConfig::ReleaseSlotId(sal_uInt16 nId)
+{
+ DBG_ASSERT( IsMacroSlot( nId ), "SlotId ist kein Macro!");
+
+ sal_uInt16 nCount = pImp->aArr.Count();
+ for (sal_uInt16 i=0; i<nCount; i++)
+ {
+ SfxMacroInfo *pInfo = (pImp->aArr)[i];
+ if (pInfo->nSlotId == nId)
+ {
+ pInfo->nRefCnt--;
+ if (pInfo->nRefCnt == 0)
+ {
+ // Slot wird nicht mehr referenziert, also holen
+ SfxSlot *pSlot = pInfo->pSlot;
+
+ // Slot aus der Verkettung rausnehmen
+ while (pSlot->pNextSlot != pInfo->pSlot)
+ pSlot = (SfxSlot*) pSlot->pNextSlot;
+ pSlot->pNextSlot = pInfo->pSlot->pNextSlot;
+
+ // Slot selbst kurz schlie\sen
+ pSlot = pInfo->pSlot;
+ pSlot->pNextSlot = pSlot;
+
+ // MacroInfo aus Array entfernen, damit sie kein Unheil
+ // anrichten kann
+ pImp->aArr.Remove(i);
+
+ // SlotId wieder freigeben
+ sal_uInt16 nCount = aIdArray.Count();
+ for (sal_uInt16 n=0; n<nCount; n++)
+ {
+ if (aIdArray[n] == nId)
+ {
+ aIdArray.Remove(n);
+ break;
+ }
+ }
+
+ // Falls ein Image belegt wwurde, kann das jetzt wieder frei
+ // gegeben werden (wenn nicht aus dtor gerufen, da ist der
+ // ImageManager schon weg)
+ SfxImageManager *pImgMgr = SFX_IMAGEMANAGER();
+ if (pImgMgr)
+ pImgMgr->ReplaceImage(nId, 0);
+
+ // Sofern nicht die Applikation heruntergefahren wird, mu\s
+ // der Slot asynchron gel"oscht werden, falls er in seinem
+ // eigenen Execute abgeschossen wird!
+ if ( !SFX_APP()->IsDowning() )
+ pImp->nEventId = Application::PostUserEvent( LINK(this, SfxMacroConfig, EventHdl_Impl), pInfo );
+ else
+ EventHdl_Impl( pInfo );
+ }
+ return;
+ }
+ }
+
+ DBG_ERROR("Macro-SlotId nicht gefunden!");
+}
+
+//==========================================================================
+
+void SfxMacroConfig::RegisterSlotId(sal_uInt16 nId)
+{
+ DBG_ASSERT( IsMacroSlot( nId ), "SlotId ist kein Macro!");
+
+ sal_uInt16 nCount = pImp->aArr.Count();
+ for (sal_uInt16 i=0; i<nCount; i++)
+ {
+ if ((pImp->aArr)[i]->nSlotId == nId)
+ {
+ (pImp->aArr)[i]->nRefCnt++;
+ return;
+ }
+ }
+
+ DBG_ERROR("Macro-SlotId nicht gefunden!");
+}
+
+//==========================================================================
+
+const SfxMacroInfoPtr SfxMacroConfig::GetMacroInfo(sal_uInt16 nId) const
+{
+ sal_uInt16 nCount = pImp->aArr.Count();
+ for (sal_uInt16 i=0; i<nCount; i++)
+ if ((pImp->aArr)[i]->nSlotId == nId)
+ return (pImp->aArr)[i];
+
+ return 0;
+}
+
+//==========================================================================
+
+const SfxMacroInfoPtr SfxMacroConfig::GetMacroInfo_Impl( const SvxMacro *pMacro ) const
+{
+ sal_uInt16 nCount = pImp->aArr.Count();
+ for (sal_uInt16 i=0; i<nCount; i++)
+ if ((pImp->aArr)[i]->Compare(*pMacro) )
+ return (pImp->aArr)[i];
+ return 0;
+}
+
+//==========================================================================
+
+sal_Bool SfxMacroConfig::ExecuteMacro( sal_uInt16 nId, const String& rArgs ) const
+{
+ const SfxMacroInfoPtr pInfo = GetMacroInfo( nId );
+ if ( !pInfo )
+ return sal_False;
+
+ SfxObjectShell* pSh = SfxObjectShell::Current();
+
+ SvxMacro aMacro( pInfo->GetQualifiedName(), pInfo->GetBasicName(), STARBASIC );
+ sal_Bool bRet = ExecuteMacro( pSh, &aMacro, rArgs );
+
+ // Release, da im Dispatcher-Execute ein Register gemacht wurde
+ ((SfxMacroConfig*)this)->ReleaseSlotId( nId );
+ return bRet;
+}
+
+sal_Bool SfxMacroConfig::ExecuteMacro( SfxObjectShell *pSh, const SvxMacro* pMacro, const String& rArgs ) const
+{
+ SfxApplication *pApp = SFX_APP();
+
+ // Name des Macros oder Scripts bzw. ScriptCode
+ String aCode( pMacro->GetMacName() );
+ ErrCode nErr = ERRCODE_NONE;
+
+ // Ist es ein Basic-Macro ?
+ ScriptType eSType = pMacro->GetScriptType();
+ sal_Bool bIsBasic = eSType == STARBASIC;
+ sal_Bool bIsStarScript = ( eSType == EXTENDED_STYPE && pMacro->GetLibName().SearchAscii( "StarScript" ) != STRING_NOTFOUND );
+ sal_Bool bIsBasicLibBased = bIsBasic || bIsStarScript || !pSh;
+
+#if SUPD<582
+ if ( !bIsBasicLibBased && pSh && pApp->GetIniManager()->IsJavaScriptEnabled() )
+ {
+ // AB: #49303# hier muss Window als this gesetzt werden
+ SfxJS* pJS = pSh->GetMedium()->GetJavaScript();
+ SjJScriptWindowObject* pWindow = pJS ? pJS->GetWindowObject() : NULL;
+
+ Link aLink = LINK( this, SfxMacroConfig, CallbackHdl_Impl );
+ pImp->bWaitingForCallback = sal_True;
+ nErr = pSh->CallJavaScript( *pMacro, pWindow, &aLink );
+ sal_uInt32 nTicks = Time::GetSystemTicks();
+ nTicks += 5000;
+ while ( pImp->bWaitingForCallback && nTicks > Time::GetSystemTicks() )
+ Application::Yield();
+ pImp->bWaitingForCallback = sal_False;
+ return nErr != ERRCODE_NONE;
+ }
+ else
+#endif
+
+ if ( bIsBasicLibBased )
+ {
+ pApp->EnterBasicCall();
+ BasicManager *pAppMgr = SFX_APP()->GetBasicManager();
+ if( bIsBasic )
+ {
+ // BasicManager von Document?
+ BasicManager *pMgr = pSh ? pSh->GetBasicManager() : NULL;
+
+ // Da leider der Name zwischendurch h"aufig gewechselt hat ...
+ if( SFX_APP()->GetName() == pMacro->GetLibName() ||
+ pMacro->GetLibName().EqualsAscii("StarDesktop") )
+ pMgr = pAppMgr;
+ else if ( pMgr == pAppMgr )
+ pMgr = NULL;
+
+ if ( pSh && pMgr && pMgr == pAppMgr )
+ {
+/*
+ SfxViewFrame *pFrame = SfxViewFrame::GetFirst( pSh, 0, sal_False );
+ SbxVariable *pDocVar = pAppMgr->GetLib(0)->Find( "ThisDocument", SbxCLASS_PROPERTY );
+ if ( pDocVar )
+ pDocVar->PutObject( pSh->GetSbxObject() );
+
+ SbxVariable *pWinVar = pAppMgr->GetLib(0)->Find( "ThisWindow", SbxCLASS_PROPERTY );
+ if ( pWinVar )
+ pWinVar->PutObject( pFrame->GetSbxObject() );
+*/
+ SFX_APP()->Get_Impl()->pThisDocument = pSh;
+ SbxVariable *pCompVar = pAppMgr->GetLib(0)->Find( DEFINE_CONST_UNICODE("ThisComponent"), SbxCLASS_PROPERTY );
+ if ( pCompVar )
+ {
+ ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xInterface ( pSh->GetModel() , ::com::sun::star::uno::UNO_QUERY );
+ ::com::sun::star::uno::Any aAny;
+ aAny <<= xInterface;
+ pCompVar->PutObject( GetSbUnoObject( DEFINE_CONST_UNICODE("ThisComponent"), aAny ) );
+ }
+
+ nErr = Call( 0, aCode, pMgr );
+
+ SFX_APP()->Get_Impl()->pThisDocument = NULL;
+/*
+ if ( pDocVar )
+ pDocVar->PutObject( NULL );
+ if ( pWinVar )
+ pWinVar->PutObject( NULL );
+ */
+ if ( pCompVar )
+ pCompVar->PutObject( NULL );
+ }
+ else if ( pMgr )
+ nErr = Call( 0, aCode, pMgr );
+ else
+ nErr = SbxERR_NO_METHOD;
+
+ }
+#if SUPD<582
+ else if( bIsStarScript )
+ {
+ ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xSource;
+
+ // Haben wir eine Shell?
+ if( pSh )
+ {
+ // dann dort callen
+ nErr = pSh->CallScript( pMacro->GetLibName(), aCode, xSource, NULL, NULL );
+ }
+ else
+ {
+ // ::com::sun::star::script::Engine von der Standard-Bibliothek anfordern
+ StarBASIC* pStdLib = pAppMgr->GetStdLib();
+ ::com::sun::star::uno::Reference< ::com::sun::star::script::XEngine > xEngine= pStdLib->getEngine( pAppMgr );
+ SfxMacroConfig::CallStarScript( xEngine, aCode, xSource, NULL, NULL );
+ }
+ }
+#endif
+ pApp->LeaveBasicCall();
+ }
+ else
+ {
+ nErr = SbxERR_NO_METHOD;
+ }
+
+ return ( nErr == ERRCODE_NONE );
+}
+
+sal_Bool SfxMacroConfig::CheckMacro( SfxObjectShell *pSh, const SvxMacro* pMacro ) const
+{
+ SfxApplication *pApp = SFX_APP();
+
+ // Name des Macros oder Scripts bzw. ScriptCode
+ String aCode( pMacro->GetMacName() );
+ ErrCode nErr = ERRCODE_NONE;
+
+#if SUPD<582
+ // Ist es ein Basic-Macro ?
+ sal_Bool bIsBasic = pMacro->GetScriptType() == STARBASIC;
+ if ( !bIsBasic )
+ return pSh != NULL;
+#endif
+
+ // BasicManager von Document oder Application
+ pApp->EnterBasicCall();
+ BasicManager *pAppMgr = SFX_APP()->GetBasicManager();
+ BasicManager *pMgr = pSh ? pSh->GetBasicManager() : NULL;
+
+ // Da leider der Name zwischendurch h"aufig gewechselt hat ...
+ if( SFX_APP()->GetName() == pMacro->GetLibName() ||
+ pMacro->GetLibName().EqualsAscii("StarDesktop") )
+ pMgr = pAppMgr;
+ else if ( pMgr == pAppMgr )
+ pMgr = NULL;
+
+ if ( !pMgr || !SfxQueryMacro( pMgr, aCode ) )
+ nErr = SbxERR_NO_METHOD;
+ pApp->LeaveBasicCall();
+ return ( nErr == ERRCODE_NONE );
+}
+
+//==========================================================================
+
+sal_Bool SfxMacroConfig::CheckMacro( sal_uInt16 nId ) const
+{
+ const SfxMacroInfoPtr pInfo = GetMacroInfo( nId );
+ if ( !pInfo )
+ return sal_False;
+
+ // Basic nur initialisieren, wenn default nicht ::com::sun::star::script::JavaScript; dann mu\s
+ // in IsBasic() sowieso das Basic angelegt werden
+ SfxObjectShell* pSh = SfxObjectShell::Current();
+
+ SfxApplication *pApp = SFX_APP();
+ pApp->EnterBasicCall();
+
+ // BasicManager von Document oder Application
+ BasicManager *pAppMgr = SFX_APP()->GetBasicManager();
+ BasicManager *pMgr = pSh ? pSh->GetBasicManager() : NULL;
+
+ if( SFX_APP()->GetName() == pInfo->GetBasicName() )
+ pMgr = SFX_APP()->GetBasicManager();
+ else if ( pMgr == pAppMgr )
+ pMgr = NULL;
+
+ String aFull( pInfo->GetQualifiedName() );
+ sal_Bool bIsBasic = pMgr ? IsBasic( 0, aFull, pMgr ) : sal_False;
+ pApp->LeaveBasicCall();
+ return bIsBasic;
+}
+
+//==========================================================================
+
+IMPL_LINK( SfxMacroConfig, CallbackHdl_Impl, SfxMacroConfig*, pConfig )
+{
+ pImp->bWaitingForCallback = sal_False;
+ return 0;
+}
+
+IMPL_LINK( SfxMacroConfig, EventHdl_Impl, SfxMacroInfo*, pInfo )
+{
+ delete pInfo;
+ pImp->nEventId = 0;
+ return 0;
+}
+
+sal_Bool SfxMacroConfig::IsBasic( SbxObject* pVCtrl, const String& rCode, BasicManager* pMgr )
+{
+ sal_Bool bFound;
+ SFX_APP()->EnterBasicCall();
+ bFound = SfxQueryMacro( pMgr, rCode ) != 0;
+ SFX_APP()->LeaveBasicCall();
+ return bFound;
+}
+
+ErrCode SfxMacroConfig::Call( SbxObject* pVCtrl,
+ const String& rCode, BasicManager* pMgr, SbxArray *pArgs, SbxValue *pRet )
+{
+ SfxApplication *pApp = SFX_APP();
+ pApp->EnterBasicCall();
+ SbMethod* pMethod = SfxQueryMacro( pMgr, rCode );
+ ErrCode nErr = 0;
+ if( pMethod )
+ {
+ if ( pArgs )
+ pMethod->SetParameters( pArgs );
+ nErr = pMethod->Call( pRet );
+ }
+ else
+ nErr = ERRCODE_BASIC_PROC_UNDEFINED;
+
+ pApp->LeaveBasicCall();
+ return nErr;
+}
+
+#if SUPD<582
+void SfxMacroConfig::CallStarScript( const ::com::sun::star::uno::Reference< ::com::sun::star::script::XEngine > & rxEngine, const String & rCode,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > & rSource, void *pArgs, void *pRet )
+{
+ static String aCallPrefix( "();" );
+
+ ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > aArgs;
+ if( pArgs )
+ aArgs = *(::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > *)pArgs;
+
+ // HACK!!! TODO: Klaeren, wie das wirklich laufen soll
+ String aCode = rCode;
+ aCode += aCallPrefix;
+
+ ::rtl::OUString aUCode = StringToOUString( aCode, RTL_TEXTENCODING_UTF8 );
+ if ( pRet )
+ {
+ *((::com::sun::star::uno::Any*)pRet) = rxEngine->run( aUCode, rSource, aArgs );
+ }
+ else
+ {
+ ::com::sun::star::uno::Reference< ::com::sun::star::script::XEngineListener > xCB;
+ rxEngine->runAsync( aUCode, rSource, aArgs, xCB );
+ }
+}
+#endif
+
+sal_Bool SfxMacroConfig::IsMacroSlot( sal_uInt16 nId )
+{
+ return ( nId >= SID_MACRO_START && nId <= SID_MACRO_END );
+}
+
+
diff --git a/sfx2/source/control/macro.cxx b/sfx2/source/control/macro.cxx
new file mode 100644
index 000000000000..8affc5acfa37
--- /dev/null
+++ b/sfx2/source/control/macro.cxx
@@ -0,0 +1,858 @@
+/*************************************************************************
+ *
+ * $RCSfile: macro.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 16:52:29 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _ARGS_HXX //autogen
+#include <svtools/args.hxx>
+#endif
+
+#ifndef _SBXVAR_HXX //autogen
+#include <svtools/sbxvar.hxx>
+#endif
+#pragma hdrstop
+
+#include <app.hxx>
+#include <module.hxx>
+#include <shell.hxx>
+#include <request.hxx>
+#include <objsh.hxx>
+#include <viewsh.hxx>
+#include <viewfrm.hxx>
+#include <msg.hxx>
+#include <macro.hxx>
+#include <sfxtypes.hxx>
+
+//====================================================================
+
+SV_DECL_PTRARR_DEL( SfxStatements_Impl, SfxMacroStatement*, 16, 8 );
+SV_IMPL_PTRARR( SfxStatements_Impl, SfxMacroStatement* );
+TYPEINIT1(SfxMacroItem,SfxPoolItem);
+
+//--------------------------------------------------------------------
+
+struct SfxMacro_Impl
+
+/* [Beschreibung]
+
+ Implementations-Struktur der Klasse <SfxMacro>.
+*/
+
+{
+ SfxMacroMode eMode; /* Zweck der <SfxMacro>-Instanz,
+ Bedeutung siehe enum <SfxMacroMode> */
+ SfxStatements_Impl aList; /* Liste von aufgezeichneten Statements */
+ USHORT nObjNo; // Durchnumerierung der SbxObjects
+};
+
+//====================================================================
+
+SfxMacroStatement::SfxMacroStatement
+(
+ const SfxShell& rShell, // <SfxShell>, die den Request ausf"uhrte
+ const String& rTarget, // Name des Zielobjektes vor der Ausf"urhung
+ BOOL bAbsolute, // obsolet
+ const SfxSlot& rSlot, // der <SfxSlot>, der das Statement abspielen kann
+ BOOL bRequestDone, // wurde der Request tats"achlich ausgef"uhrt
+ SfxArguments* pArguments // aktuelle Parameter (werden "ubernommen)
+)
+
+/* [Beschreibung]
+
+ Dieser Konstruktor der Klasse SfxMacroStatement erzeugt ein Statement,
+ bei dem ein Objekt angesprochen wird, welches durch 'rShell' angegeben
+ ist. Dabei erfolgt die Addressierung je nach 'bAbsolute' absolut,
+ also z.B. als '[mydoc.sdc]' oder relativ, also z.B. 'ActiveDocument'.
+
+ Je nach Art der Subklasse von 'rShell' ergeben sich folgende
+ Ausdr"ucke:
+
+ |absolut relativ
+ -----------------------------------------------------------------------
+ SfxApplication' | 'StarCalc' 'Application'
+ SfxViewFrame' |'[mydoc.sdc:1]' 'ActiveWindow'
+ SfxViewShell' | '[mydoc.sdc:1]' 'AvtiveWindow'
+ SfxObjectShell' | '[mydoc.sdc]' 'ActiveDocument'
+ sonstige (Sub-Shells) | '[mydoc.sdc:1]' 'ActiveWindow'
+
+ Dabei sind 'StarCalc' stellvertretend fr den Namen der Applikation
+ (Application::GetAppName()const). In der absoluten Fassung k"onnte
+ die Selektion auch deskriptiv z.B. als 'CellSelection("A5-D8")')
+ angesprochen werden, dazu mu\ jedoch vom Anwendungsprogrammierer der
+ Konstruktor <SfxMacroStatement::SfxMacroStatement(const String&,
+ const SfxSlot&,BOOL,SfxArguments*)> verwendet werden.
+
+ F"ur das so bezeichnete Objekt wird dann je nach Typ des Slots
+ eine Zuweisung an eines seiner Properties oder der Aufruf einer seiner
+ Methoden ausgedr"uckt.
+
+
+ [Beispiele]
+
+ absolut:
+ SCalc3.OpenDocument( "\docs\mydoc.sdd", "StarDraw Presentation", 0, 0 )
+ [mydoc.sdd].Activate()
+ [mydoc.sdd:1].SwitchToView( 2 )
+ [mydoc.sdc:1:1].CellSelection( "A5-D8" ).LineColor = 192357
+
+ relativ:
+ ActiveWindow.LineColor = 192357
+
+
+ [Querverweise]
+
+ <SfxMacroStatement::SfxMacroStatement(const String&,const SfxSlot&,BOOL,SfxArguments*)>
+ <SfxMacroStatement::SfxMacroStatement(const String&)>
+*/
+
+: nSlotId( rSlot.GetSlotId() ),
+ pArgs( pArguments ),
+ bDone( bRequestDone ),
+ pDummy( 0 )
+{
+ // Workaround Recording nicht exportierter Slots (#25386#)
+ if ( !rSlot.pName )
+ return;
+
+ // Objekt-Typ bestimmen
+ FASTBOOL bIsApp = rShell.ISA(SfxApplication);
+ FASTBOOL bIsDoc = rShell.ISA(SfxObjectShell);
+ FASTBOOL bIsWin = !bIsApp && !bIsDoc &&
+ ( rShell.ISA(SfxViewShell) || rShell.ISA(SfxViewFrame) );
+ FASTBOOL bIsSel = !bIsApp && !bIsDoc && !bIsWin;
+
+ // Objekt nicht schon im Slot-Namen enthalten?
+ if ( bIsSel || rSlot.pName[0] == '.' )
+ {
+ // absolutes Aufzeichnen?
+ if ( rSlot.IsMode( SFX_SLOT_RECORDABSOLUTE ) )
+ {
+ // an der Applikation oder am Modul
+ if ( rShell.ISA(SfxApplication) || rShell.ISA(SfxModule) )
+ aStatement = rTarget;
+
+ // am Dokument?
+ // '[' = 5Bh
+ // ']' = 5Dh
+ else if ( rShell.ISA(SfxObjectShell) )
+ {
+ aStatement = 0x005B;
+ aStatement += rTarget;
+ aStatement += 0x005D;
+ }
+
+ else if ( rShell.ISA(SfxViewFrame) )
+ {
+ aStatement = 0x005B;
+ aStatement += rShell.GetSbxObject()->GetName();
+ aStatement += 0x005D;
+ }
+
+ else
+ {
+ // an der View oder Sub-Shell
+ SfxViewShell *pViewShell = rShell.GetViewShell();
+ aStatement = 0x005B;
+ aStatement += pViewShell->GetViewFrame()->GetSbxObject()->GetName();
+ aStatement += 0x005D;
+ if ( !rShell.ISA(SfxViewFrame) )
+ // an einer Sub-Shell zus"atlich .Selection anh"angen
+ aStatement += DEFINE_CONST_UNICODE(".Selection");
+ }
+ }
+ else // relatives Aufzeichnen
+ {
+ // an der Application?
+ if ( rShell.ISA(SfxApplication) )
+ aStatement = DEFINE_CONST_UNICODE("Application");
+
+ // am Modul?
+ else if ( rShell.ISA(SfxModule) )
+ aStatement = DEFINE_CONST_UNICODE("ActiveModule");
+
+ // am Dokument
+ else if ( rShell.ISA(SfxObjectShell) )
+ aStatement = DEFINE_CONST_UNICODE("ActiveDocument");
+
+ // am Window
+ else if ( rShell.ISA(SfxViewShell) || rShell.ISA(SfxViewFrame) )
+ aStatement = DEFINE_CONST_UNICODE("ActiveWindow");
+
+ else
+ // an einer Sub-Shell
+ aStatement = DEFINE_CONST_UNICODE("Selection");
+ }
+ }
+/*
+ if ( bIsSel )
+ {
+ // bei Selection ggf. noch den Namen der SubShell anh"angen
+ const SfxShellObject *pShObj =
+ (const SfxShellObject*) rShell.GetSbxObject();
+ if ( pShObj )
+ {
+ const SfxShellObject *pParentObj =
+ (const SfxShellObject*) pShObj->GetParent();
+ SfxShell *pParentSh = pParentObj->GetShell();
+ DBG_ASSERT( pParentSh->ISA(SfxViewFrame),
+ "parent of SubShell must be a Frame" );
+ if ( rSlot.pName[0] == '.' )
+ {
+ aStatement += '.';
+ aStatement += rShell.GetSbxObject()->GetName();
+ }
+ }
+ else
+ DBG_ASSERT( rSlot.pName[0] != '0', "recording unnamed object" );
+ }
+*/
+ // an diesen Objekt-Ausdruck den Methoden-/Property-Namen und Parameter
+ GenerateNameAndArgs_Impl( SfxRequest::GetRecordingMacro(),
+ rSlot, bRequestDone, pArgs);
+}
+
+//--------------------------------------------------------------------
+
+SfxMacroStatement::SfxMacroStatement
+(
+ const String& rTarget, // Objekt, was beim Playing angesprochen wird
+ const SfxSlot& rSlot, // der <SfxSlot>, der das Statement abspielen kann
+ BOOL bRequestDone, // wurde der Request tats"achlich ausgef"uhrt
+ SfxArguments* pArguments // aktuelle Parameter (werden "ubernommen)
+)
+
+/* [Beschreibung]
+
+
+ [Querverweise]
+
+ <SfxMacroStatement::SfxMacroStatement(const String&)>
+ <SfxMacroStatement::SfxMacroStatement(const SfxShell&,BOOL,const SfxSlot&,BOOL,SfxArguments*)>
+*/
+
+: nSlotId( rSlot.GetSlotId() ),
+ pArgs( pArguments ),
+ bDone( bRequestDone ),
+ pDummy( 0 )
+{
+ aStatement = rTarget;
+ aStatement += 0x002E; // '.' = 2Eh
+ GenerateNameAndArgs_Impl( SfxRequest::GetRecordingMacro(),
+ rSlot, bRequestDone, pArgs);
+}
+
+//--------------------------------------------------------------------
+
+SfxMacroStatement::SfxMacroStatement
+(
+ const String& rStatement // manuell erzeugte(s) Statement(s)
+)
+
+/* [Beschreibung]
+
+ Dieser Konstruktor erzeugt eine SfxMacroStatement-Instanz, deren
+ Aufbau vollst"andig vom Applikationsentwickler bestimmt wird. Da der
+ angegebene String auch mehrere mit CR/LF getrennte Statements
+ enthalten darf, ist damit ein weitgehender Eingriff in das Aufzeichnen
+ von BASIC-Makros m"oglich, um Spezialf"alle zu behandeln.
+
+
+ [Querverweise]
+
+ <SfxMacroStatement::SfxMacroStatement(const String&,const SfxSlot&,BOOL,SfxArguments*)>
+ <SfxMacroStatement::SfxMacroStatement(const SfxShell&,BOOL,const SfxSlot&,BOOL,SfxArguments*)>
+*/
+
+: aStatement( rStatement ),
+ nSlotId( 0 ),
+ pArgs( 0 ),
+ bDone( TRUE ),
+ pDummy( 0 )
+{
+}
+
+//--------------------------------------------------------------------
+
+SfxMacroStatement::SfxMacroStatement
+(
+ const SfxMacroStatement& rOrig // Original, von dem kopiert wird
+)
+
+/* [Beschreibung]
+
+ Copy-Konstruktor der SfxMacroStatement-Klasse.
+*/
+
+: aStatement( rOrig.aStatement ),
+ nSlotId( rOrig.nSlotId ),
+ pArgs( 0 ),
+ bDone( rOrig.bDone ),
+ pDummy( 0 )
+{
+ if ( rOrig.pArgs )
+ pArgs = new SfxArguments( *rOrig.pArgs );
+}
+
+//--------------------------------------------------------------------
+
+SfxMacroStatement::~SfxMacroStatement()
+
+/* [Beschreibung]
+
+ Destruktor der Klasse SfxMacroStatement. Gibt die Liste der
+ aktuellen Parameter frei.
+*/
+
+{
+ delete pArgs;
+}
+
+//--------------------------------------------------------------------
+
+void SfxMacroStatement::GenerateNameAndArgs_Impl
+(
+ SfxMacro* pMacro, // darin wird aufgezeichnet
+ const SfxSlot& rSlot, // der Slot, der das Statement abspielen kann
+ BOOL bRequestDone, // TRUE=wurde ausgef"uhrt, FALSE=abgebrochen
+ SfxArguments* pArgs // die aktuellen Parameter
+)
+
+/* [Beschreibung]
+
+ Interne Hilfsmethode zum generieren des Funktions-/Property-Names
+ sowie der Parameter. Diese Methode wird nur verwendet, wenn der
+ Anwendungsprogrammierer keinen eigenen Source an den <SfxRequest>
+ geh"angt hat.
+*/
+
+{
+ // . zwsischen Object und Prop/Meth-Name
+ // '.' = 2Eh
+ if ( aStatement.Len() && aStatement.GetChar( aStatement.Len() - 1 ) != 0x002E &&
+ rSlot.pName[0] != 0x002E )
+ aStatement += 0x002E;
+
+ // der Name des Slots ist der Name der Methode / des Properties
+ aStatement += String::CreateFromAscii(rSlot.pName);
+ if ( rSlot.IsMode(SFX_SLOT_METHOD) )
+ aStatement += DEFINE_CONST_UNICODE("( ");
+ else
+ aStatement += DEFINE_CONST_UNICODE(" = ");
+
+ // alle zusammengesuchten Parameter rausschreiben
+ if ( pArgs && pArgs->Count() ) // Abfrage doppelt wegen BLC-Bug
+ for ( USHORT nArg = 0; nArg < pArgs->Count(); ++nArg )
+ {
+ // den Parameter textuell darstellen
+ String aArg;
+ const SbxVariable& rVar = pArgs->Get(nArg);
+ switch ( rVar.GetType() & (2*SbxUSERn+1) )
+ {
+ case SbxEMPTY:
+ case SbxNULL:
+ // kein Argument
+ break;
+
+ case SbxSTRING:
+ {
+ // Anf"uhrungszeichen werden verdoppelt
+ XubString aRecordable( rVar.GetString() );
+ USHORT nPos = 0;
+ while ( TRUE )
+ {
+ nPos = aRecordable.SearchAndReplace( DEFINE_CONST_UNICODE('"'), DEFINE_CONST_UNICODE("\"\""), nPos );
+ if ( STRING_NOTFOUND == nPos )
+ break;
+ nPos += 2;
+ }
+
+ // nicht druckbare Zeichen werden als chr$(...) geschrieben
+ FASTBOOL bPrevReplaced = FALSE;
+ for ( USHORT n = 0; n < aRecordable.Len(); ++n )
+ {
+ sal_Unicode cChar = aRecordable.GetChar(n);
+ if ( !( cChar>=32 && cChar!=127 ) ) // ALS ERSATZ FUER String::IsPrintable()!
+ {
+ XubString aReplacement( DEFINE_CONST_UNICODE("+chr$(") );
+ aReplacement += cChar;
+
+ if ( bPrevReplaced )
+ {
+ aRecordable.Insert( aReplacement, n - 2 );
+ n += aReplacement.Len();
+ aRecordable.SetChar((unsigned short) (n-2), 0x0029);// ')' = 29h
+ aRecordable.Replace( n-1, 2, DEFINE_CONST_UNICODE("+\"") );
+ // ++n;
+ }
+ else
+ {
+ aReplacement += DEFINE_CONST_UNICODE(")+\"");
+ aRecordable.SetChar(n, 0x0022 );// '"' = 22h
+ aRecordable.Insert( aReplacement, n + 1 );
+ n += aReplacement.Len();
+ }
+ bPrevReplaced = TRUE;
+ }
+ else
+ bPrevReplaced = FALSE;
+ }
+
+ // Argument in Anf"uhrungszeichen
+ aArg = 0x0022; // '"' = 22h
+ aArg += aRecordable;
+ aArg += 0x0022;
+ break;
+ }
+
+ case SbxBOOL:
+ {
+ // symbolisch als TRUE und FALSE
+ aArg = rVar.GetBool() ? DEFINE_CONST_UNICODE("TRUE") : DEFINE_CONST_UNICODE("FALSE");
+ break;
+ }
+
+ case SbxBYTE:
+ {
+ // als Zahl darstellen
+ aArg = (USHORT) rVar.GetByte();
+ break;
+ }
+
+ case SbxOBJECT:
+ {
+ HACK(only an experimental implementation)
+ SbxObjectRef xObj = (SbxObject*) rVar.GetObject();
+
+ // einen Objektnamen generieren
+ String aObjectName( 'a' );
+ aObjectName += xObj->GetClassName();
+ aObjectName += pMacro->NextObjectNo();
+
+ // das Objekt mit Daten belegen
+ String aObjectDef( DEFINE_CONST_UNICODE("\nDIM ") );
+ aObjectDef += aObjectName;
+ aObjectDef += DEFINE_CONST_UNICODE(" AS NEW ");
+ aObjectDef += xObj->GetClassName();
+ aObjectDef += DEFINE_CONST_UNICODE("\nWITH ");
+ aObjectDef += aObjectName;
+ aObjectDef += DEFINE_CONST_UNICODE("\n");
+ aObjectDef += xObj->GenerateSource( DEFINE_CONST_UNICODE("\t"), 0 );
+ aObjectDef += DEFINE_CONST_UNICODE("\nEND WITH\n");
+ aStatement.Insert( aObjectDef, 0 );
+ aObjectDef += DEFINE_CONST_UNICODE("\n\n");
+
+ // Objektname als Parameter anh"angen
+ aArg = aObjectName;
+ break;
+ }
+
+ default:
+ // alles andere als String ohne Anf"uhrungszeichen
+ aArg = rVar.GetString();
+ }
+
+ // den Parameter anh"angen
+ aStatement += aArg;
+ aStatement += DEFINE_CONST_UNICODE(", ");
+ }
+
+ // Statement beeden
+ if ( pArgs && pArgs->Count() )
+ aStatement.Erase( aStatement.Len() - 2, 1 );
+ else
+ aStatement.Erase( aStatement.Len() - 1, 1 );
+ if ( rSlot.IsMode(SFX_SLOT_METHOD) )
+ aStatement += 0x0029; // ')' = 29h
+
+ if ( !bRequestDone )
+ // nicht als "Done()" gekennzeichnete Statements auskommentieren
+ aStatement.InsertAscii( "rem ", 0 );
+}
+
+//--------------------------------------------------------------------
+
+SfxMacro::SfxMacro
+(
+ SfxMacroMode eMode // Zweck der Instanz, siehe <SfxMacroMode>
+)
+
+/* [Beschreibung]
+
+ Konstruktor der Klasse SfxMacro. Instanzen dieser Klasse werden im
+ SFx zu zwei Zwecken ben"otigt:
+
+ 1. zum Aufzeichnen von Makros
+ In diesem Fall wird der Konstruktor mit SFX_MACRO_RECORDINGABSOLUTE
+ oder SFX_MACRO_RECORDINGRELATIVE aufgerufen. Es sollte sich um eine
+ Instanz einer abgeleiteten Klasse handeln, um in der Ableitung
+ die Information dar"uber unterzubringen, wo das Makro gespeichert
+ werden soll. Ein solches Makro solle sich dann in seinem Destruktor
+ an der vom Benutzer gew"ahlten Stelle speichern.
+
+ 2. zum Zuordnen von exisitierenden Makros
+ In diesem Fall wird der Konstruktor mit SFX_MACRO_EXISTING aufgerufen.
+ Eine solche Instanz wird z.B. ben"otigt, wenn Makros auf Events
+ oder <SfxControllerItem>s konfiguriert werden sollen.
+*/
+
+: pImp( new SfxMacro_Impl )
+
+{
+ pImp->eMode = eMode;
+ pImp->nObjNo = 0;
+}
+
+//--------------------------------------------------------------------
+
+SfxMacro::~SfxMacro()
+
+/* [Beschreibung]
+
+ Virtueller Destruktor der Klasse SfxMacro. Dieser sollte in den
+ abgeleiteten Klassen "uberladen werden, um in den Modi
+ SFX_MACRO_RECORDINGABSOLUTE und SFX_MACRO_RECORDINGRELATIVE den
+ aufgezeichneten Source abzuspeichern.
+
+
+ [Querverweise]
+
+ <SfxMacro::GenerateSource()const>
+*/
+
+{
+#ifdef DBG_UTIL
+#ifdef MAC
+ SvFileStream aStream( DEFINE_CONST_UNICODE("record.bas"), STREAM_STD_WRITE );
+#else
+ SvFileStream aStream( DEFINE_CONST_UNICODE("/tmp/record.bas"), STREAM_STD_WRITE );
+#endif
+ aStream.WriteLine( ByteString(U2S(GenerateSource())) );
+#endif
+ delete pImp;
+}
+
+//--------------------------------------------------------------------
+
+SfxMacroMode SfxMacro::GetMode() const
+
+/* [Beschreibung]
+
+ Liefert den Modus, der besagt zu welchem Zweck das SfxMacro konstruiert
+ wurde.
+
+
+ [Querverweise]
+
+ enum <SfxMacroMode>
+*/
+
+{
+ return pImp->eMode;
+}
+
+//--------------------------------------------------------------------
+
+USHORT SfxMacro::NextObjectNo()
+
+/* [Beschreibung]
+
+ Liefert eine Nummer, die als Namens-Erweiterung f"ur SbxObjects,
+ die per DIM angelegt werden m"ussen, verwendet werden kann. Bei jedem
+ Abfragen kommt eine um 1 erh"ohte Nummer zur"uck, die in diesem Makro
+ einmalig ist.
+*/
+
+{
+ return ++pImp->nObjNo;
+}
+
+//--------------------------------------------------------------------
+
+void SfxMacro::Record
+(
+ SfxMacroStatement* pStatement // aufzuzeichnendes <SfxMacroStatement>
+)
+
+/* [Beschreibung]
+
+ Diese Methode zeichnet das als Parameter "ubergeben Statement auf.
+ Die Instanz auf die der "ubergebe Pointer zeigt, geht in das Eigentum
+ des SfxMacro "uber.
+
+ Der Aufruf ist nur g"ultig, wenn es sich um ein SfxMacro handelt,
+ welches mit SFX_MACRO_RECORDINGABSOLUTE oder SFX_MACRO_RECORDINGRELATIVE
+ konstruiert wirde.
+
+
+ [Querverweise]
+
+ <SfxMacro::Replace(SfxMacroStatement*)>
+ <SfxMacro::Remove()>
+ <SfxMacro::GetLastStatement()const>
+*/
+
+{
+ DBG_ASSERT( pImp->eMode != SFX_MACRO_EXISTING,
+ "invalid call to non-recording SfxMacro" );
+ pImp->aList.C40_INSERT( SfxMacroStatement, pStatement, pImp->aList.Count() );
+}
+
+//--------------------------------------------------------------------
+
+void SfxMacro::Replace
+(
+ SfxMacroStatement* pStatement // aufzuzeichnendes <SfxMacroStatement>
+)
+
+/* [Beschreibung]
+
+ Diese Methode zeichnet das als Parameter "ubergeben Statement auf.
+ Dabei wird das jeweils zuletzt aufgezeichnete Statement "uberschrieben.
+ Die Instanz auf die der "ubergebe Pointer zeigt, geht in das Eigentum
+ des SfxMacro "uber.
+
+ Mit dieser Methode ist es m"oglich, Statements zusammenzufassen. Z.B.
+ anstelle f"unfmal hintereinander 'CursorLeft()' aufzurufen, k"onnte
+ das zu 'CursorLeft(5)' zusammengefa\st werden. Oder anstelle ein Wort
+ Buchstabe f"ur Buchstabe aufzubauen, k"onnte dies durch ein einziges
+ Statement 'InsertString("Hallo")' ersetzt werden.
+
+ Der Aufruf ist nur g"ultig, wenn es sich um ein SfxMacro handelt,
+ welches mit SFX_MACRO_RECORDINGABSOLUTE oder SFX_MACRO_RECORDINGRELATIVE
+ konstruiert wurde und bereits ein aufgezeichnetes Statement vorhanden
+ ist.
+
+
+ [Anmerkung]
+
+ Diese Methode wird typischerweise aus den Execute-Methoden der
+ <SfxSlot>s von den Applikationsentwicklern gerufen.
+
+
+ [Querverweise]
+
+ <SfxMacro::Record(SfxMacroStatement*)>
+ <SfxMacro::Remove()>
+ <SfxMacro::GetLastStatement()const>
+*/
+
+{
+ DBG_ASSERT( pImp->eMode != SFX_MACRO_EXISTING,
+ "invalid call to non-recording SfxMacro" );
+ DBG_ASSERT( pImp->aList.Count(), "no replaceable statement available" )
+ pImp->aList.Remove( pImp->aList.Count() - 1 );
+ pImp->aList.C40_INSERT( SfxMacroStatement,pStatement, pImp->aList.Count() );
+}
+
+//--------------------------------------------------------------------
+
+void SfxMacro::Remove()
+
+/* [Beschreibung]
+
+ Diese Methode l"oscht das zuletzt aufgezeichnete <SfxMacroStatement>
+ und entfernt es aus dem Macro.
+
+ Mit dieser Methode ist es m"oglich, Statements zusammenzufassen. Z.B.
+ anstelle f"unfmal hintereinander 'CursorLeft()' aufzurufen, k"onnte
+ das zu 'CursorLeft(5)' zusammengefa\st werden. Oder anstelle ein Wort
+ Buchstabe f"ur Buchstabe aufzubauen, k"onnte dies durch ein einziges
+ Statement 'InsertString("Hallo")' ersetzt werden.
+
+ Der Aufruf ist nur g"ultig, wenn es sich um ein SfxMacro handelt,
+ welches mit SFX_MACRO_RECORDINGABSOLUTE oder SFX_MACRO_RECORDINGRELATIVE
+ konstruiert wurde und bereits ein aufgezeichnetes Statement vorhanden
+ ist.
+
+
+ [Anmerkung]
+
+ Diese Methode wird typischerweise aus den Execute-Methoden der
+ <SfxSlot>s von den Applikationsentwicklern gerufen.
+
+
+ [Querverweise]
+
+ <SfxMacro::Replace(SfxMacroStatement*)>
+ <SfxMacro::Record(SfxMacroStatement*)>
+ <SfxMacro::GetLastStatement()const>
+*/
+
+{
+ DBG_ASSERT( pImp->eMode != SFX_MACRO_EXISTING,
+ "invalid call to non-recording SfxMacro" );
+ DBG_ASSERT( pImp->aList.Count(), "no replaceable statement available" )
+ pImp->aList.Remove( pImp->aList.Count() - 1 );
+}
+
+//--------------------------------------------------------------------
+
+const SfxMacroStatement* SfxMacro::GetLastStatement() const
+
+/* [Beschreibung]
+
+ Mit dieser Methode kann auf das jeweils zuletzt aufgezeichnete Statement
+ lesend zugegriffen werden. Zusammen mit der Methode
+ <SfxMacro::Replace(SfxMacroStatement*)> ergibt sich dadurch die
+ M"oglichkeit, Statements zusammenzufassen.
+
+ Der Aufruf ist nur g"ultig, wenn es sich um ein SfxMacro handelt,
+ welches mit SFX_MACRO_RECORDINGABSOLUTE oder SFX_MACRO_RECORDINGRELATIVE
+ konstruiert wurde.
+
+
+ [Querverweise]
+
+ <SfxMacro::Record(SfxMacroStatement*)>
+ <SfxMacro::Replace(SfxMacroStatement*)>
+*/
+
+{
+ DBG_ASSERT( pImp->eMode != SFX_MACRO_EXISTING,
+ "invalid call to non-recording SfxMacro" );
+ if ( pImp->aList.Count() )
+ return pImp->aList.GetObject( pImp->aList.Count() - 1 );
+ return 0;
+}
+
+//--------------------------------------------------------------------
+
+String SfxMacro::GenerateSource() const
+
+/* [Beschreibung]
+
+ Diese Funktion generiert aus den, seit dem Konstruieren der Instanz
+ bis zum Zeitpunkt des Aufrufs dieser Methode aufgezeichneten
+ <SfxMacroStatement>s einen BASIC-Sourcecode, der die Statements,
+ jedoch nicht den Header ('Sub X') und den Footer ('End Sub') enth"alt.
+
+
+ [Querverweise]
+
+ <SfxMacro::Record(SfxMacroStatement*)>
+ <SfxMacro::Repeat(SfxMacroStatement*)>
+*/
+
+{
+ DBG_ASSERT( pImp->eMode != SFX_MACRO_EXISTING,
+ "invalid call to non-recording SfxMacro" );
+ String aSource;
+ for ( USHORT n = 0; n < pImp->aList.Count(); ++n )
+ {
+ aSource += pImp->aList.GetObject(n)->GetStatement();
+ if ( (n+1) < pImp->aList.Count() )
+ aSource += DEFINE_CONST_UNICODE("\n");
+ }
+
+ return aSource;
+}
+
+//--------------------------------------------------------------------
+
+SbxError SfxMacro::Call
+(
+ SbxArray* pArgs // aktuelle Parameter f"ur den Aufruf
+)
+
+/* [Beschreibung]
+
+ Diese Methode sollte von Suklassen "uberladen werden, damit der
+ SFx das in der Ableitung beschriebene BASIC-Programm rufen kann,
+ wenn es an ein Event oder in einem Controller gebunden ist.
+
+ Der Aufruf ist nur g"ultig, wenn es sich um ein SfxMacro handelt,
+ welches mit SFX_MACRO_RECORDINGABSOLUTE oder SFX_MACRO_RECORDINGRELATIVE
+ konstruiert wurde.
+
+ Die Basisimplementierung liefert immer SbxERR_NOTIMP zur"uck.
+
+
+ [Anmerkung]
+
+ I.d.R. ist pArgs == 0, der Parameter ist f"ur Zuk"unftige Erweiterungen
+ gedacht.
+*/
+
+{
+ return SbxERR_NOTIMP;
+}
+
+//--------------------------------------------------------------------
+
+SfxMacroItem::SfxMacroItem( USHORT nWhich, SfxMacro *pTheMacro )
+: SfxPoolItem( nWhich ),
+ pMacro( pTheMacro )
+{
+}
+
+//--------------------------------------------------------------------
+
+SfxPoolItem* SfxMacroItem::Clone( SfxItemPool *pPool ) const
+{
+ return new SfxMacroItem( Which(), pMacro );
+}
+
+//--------------------------------------------------------------------
+
+int SfxMacroItem::operator==( const SfxPoolItem &rOther ) const
+{
+ return pMacro == ((const SfxMacroItem&)rOther).pMacro;
+}
+
+
diff --git a/sfx2/source/control/makefile.mk b/sfx2/source/control/makefile.mk
new file mode 100644
index 000000000000..53723b82cebf
--- /dev/null
+++ b/sfx2/source/control/makefile.mk
@@ -0,0 +1,120 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: hr $ $Date: 2000-09-18 16:52:29 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=sfx2
+TARGET=control
+ENABLE_EXCEPTIONS=TRUE
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+AUTOSEG=true
+
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : svpre.mk
+.INCLUDE : settings.mk
+.INCLUDE : sv.mk
+
+# w.g. compilerbugs
+.IF "$(GUI)"=="WNT"
+CFLAGS+=-Od
+.ENDIF
+
+# --- Files --------------------------------------------------------
+
+CXXFILES = \
+ unoctitm.cxx \
+ macro.cxx \
+ request.cxx \
+ dispatch.cxx \
+ ctrlitem.cxx \
+ statcach.cxx \
+ msgpool.cxx \
+ shell.cxx \
+ objface.cxx \
+ msg.cxx \
+ bindings.cxx \
+ macrconf.cxx \
+ minfitem.cxx \
+ srchitem.cxx \
+ $(PROJECTPCHSOURCE).cxx
+
+SLOFILES = \
+ $(SLO)$/unoctitm.obj \
+ $(SLO)$/request.obj \
+ $(SLO)$/dispatch.obj \
+ $(SLO)$/msgpool.obj \
+ $(SLO)$/objface.obj \
+ $(SLO)$/ctrlitem.obj \
+ $(SLO)$/statcach.obj \
+ $(SLO)$/shell.obj \
+ $(SLO)$/msg.obj \
+ $(SLO)$/bindings.obj \
+ $(SLO)$/minfitem.obj \
+ $(SLO)$/srchitem.obj \
+ $(SLO)$/macrconf.obj
+
+# --- Targets -------------------------------------------------------
+
+.INCLUDE : target.mk
+
diff --git a/sfx2/source/control/minfitem.cxx b/sfx2/source/control/minfitem.cxx
new file mode 100644
index 000000000000..9a6735d7a9c8
--- /dev/null
+++ b/sfx2/source/control/minfitem.cxx
@@ -0,0 +1,136 @@
+/*************************************************************************
+ *
+ * $RCSfile: minfitem.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 16:52:29 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+// INCLUDE ---------------------------------------------------------------
+
+#pragma hdrstop
+
+#include "minfitem.hxx"
+
+// STATIC DATA -----------------------------------------------------------
+
+TYPEINIT1(SfxMacroInfoItem, SfxPoolItem);
+
+// -----------------------------------------------------------------------
+
+SfxMacroInfoItem::SfxMacroInfoItem(USHORT nWhich, // Slot-ID
+ const BasicManager* pMgr,
+ const String &rLibName,
+ const String &rModuleName,
+ const String &rMethodName,
+ const String &rComment) :
+ SfxPoolItem(nWhich),
+ pBasicManager(pMgr),
+ aLibName(rLibName),
+ aModuleName(rModuleName),
+ aMethodName(rMethodName),
+ aCommentText(rComment)
+{
+}
+
+// -----------------------------------------------------------------------
+
+// copy ctor
+
+SfxMacroInfoItem::SfxMacroInfoItem(const SfxMacroInfoItem& rCopy):
+ SfxPoolItem(rCopy),
+ pBasicManager(rCopy.pBasicManager),
+ aLibName(rCopy.aLibName),
+ aModuleName(rCopy.aModuleName),
+ aMethodName(rCopy.aMethodName),
+ aCommentText(rCopy.aCommentText)
+{
+}
+
+// -----------------------------------------------------------------------
+
+// op ==
+
+int SfxMacroInfoItem::operator==( const SfxPoolItem& rCmp) const
+{
+ return SfxPoolItem::operator==(rCmp) &&
+ pBasicManager == ((const SfxMacroInfoItem&)rCmp).pBasicManager &&
+ aLibName == ((const SfxMacroInfoItem&)rCmp).aLibName &&
+ aModuleName == ((const SfxMacroInfoItem&)rCmp).aModuleName &&
+ aMethodName == ((const SfxMacroInfoItem&)rCmp).aMethodName &&
+ aCommentText == ((const SfxMacroInfoItem&)rCmp).aCommentText;
+}
+
+// -----------------------------------------------------------------------
+
+SfxPoolItem *SfxMacroInfoItem::Clone( SfxItemPool *) const
+{
+ return new SfxMacroInfoItem(*this);
+}
+
+// -----------------------------------------------------------------------
+
+String SfxMacroInfoItem::GetQualifiedName() const
+{
+ String aMacroName = aLibName;
+ aMacroName += '.';
+ aMacroName += aModuleName;
+ aMacroName += '.';
+ aMacroName += aMethodName;
+ return aMacroName;
+}
+
+
diff --git a/sfx2/source/control/msg.cxx b/sfx2/source/control/msg.cxx
new file mode 100644
index 000000000000..028f05b17a5d
--- /dev/null
+++ b/sfx2/source/control/msg.cxx
@@ -0,0 +1,101 @@
+/*************************************************************************
+ *
+ * $RCSfile: msg.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 16:52:29 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _SFXITEMPOOL_HXX //autogen
+#include <svtools/itempool.hxx>
+#endif
+#ifndef _SFXENUMITEM_HXX //autogen
+#include <svtools/eitem.hxx>
+#endif
+#pragma hdrstop
+
+#include "msg.hxx"
+
+//====================================================================
+
+SfxSlotKind SfxSlot::GetKind() const
+{
+ if( !nMasterSlotId && !nValue)
+ return (SfxSlotKind) SFX_KIND_STANDARD;
+ if ( nMasterSlotId && fnExec==0 && fnState==0 )
+ {
+ if ( pType->Type() == TYPE(SfxBoolItem) )
+ return (SfxSlotKind) SFX_KIND_ENUM;
+ else
+ {
+ DBG_ERROR( "invalid slot kind detected" );
+ return SFX_KIND_ENUM;
+ }
+ }
+ else
+ return (SfxSlotKind) SFX_KIND_ATTR;
+}
+
+//--------------------------------------------------------------------
+
+USHORT SfxSlot::GetWhich( const SfxItemPool &rPool ) const
+{
+ if ( !nMasterSlotId || nMasterSlotId == USHRT_MAX )
+ ((SfxSlot*) this) -> nMasterSlotId = rPool.GetWhich(nSlotId);
+ return nMasterSlotId;
+}
+
+
diff --git a/sfx2/source/control/msgpool.cxx b/sfx2/source/control/msgpool.cxx
new file mode 100644
index 000000000000..6e98f8e9e074
--- /dev/null
+++ b/sfx2/source/control/msgpool.cxx
@@ -0,0 +1,627 @@
+/*************************************************************************
+ *
+ * $RCSfile: msgpool.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 16:52:29 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _STREAM_HXX //autogen
+#include <tools/stream.hxx>
+#endif
+#ifndef _RSCSFX_HXX //autogen
+#include <rsc/rscsfx.hxx>
+#endif
+#pragma hdrstop
+
+#include "msgpool.hxx"
+#include "minarray.hxx"
+#include "msg.hxx"
+#include "app.hxx"
+#include "objface.hxx"
+#include "idpool.hxx"
+#include "sfxtypes.hxx"
+#include "slotinfo.hxx"
+#include "macrconf.hxx"
+#include "sfxresid.hxx"
+#include "arrdecl.hxx"
+
+#include "sfx.hrc"
+
+//====================================================================
+
+struct SfxSIDRegistration_Impl
+{
+ String _aGroup;
+ String _aName;
+ USHORT _nSID;
+};
+
+struct SfxSlotType_Impl
+{
+ USHORT nId;
+ TypeId nType;
+
+ SfxSlotType_Impl( USHORT nTheId, TypeId nTheType ):
+ nId(nTheId), nType(nTheType)
+ {}
+};
+
+DECL_2BYTEARRAY(SfxSlotGroupArr_Impl, USHORT, 6, 4);
+DECL_PTRARRAY(SfxInterfaceArr_Impl, SfxInterface*, 6, 3);
+DECL_PTRARRAY(SfxSlotTypeArr_Impl, SfxSlotType_Impl*, 8, 8);
+
+
+//====================================================================
+
+SfxSlotPool::SfxSlotPool( SfxSlotPool *pParent, ResMgr* pResManager )
+ : _pParentPool( pParent )
+ , _pIdPool(0)
+ , _pTypes(0)
+ , _pGroups(0)
+ , _nCurGroup(0)
+ , _pInterfaces(0)
+ , _nCurInterface(0)
+ , _nCurMsg(0)
+ , _pResMgr( pResManager )
+ , _pUnoSlots( 0 )
+{
+ if ( !_pResMgr )
+ _pResMgr = Resource::GetResManager();
+}
+
+//====================================================================
+
+SfxSlotPool::~SfxSlotPool()
+{
+ _pParentPool = 0;
+ for ( SfxInterface *pIF = FirstInterface(); pIF; pIF = FirstInterface() )
+ delete pIF;
+ delete _pInterfaces;
+ delete _pGroups;
+ delete _pUnoSlots;
+ if ( _pTypes )
+ {
+ for ( USHORT n =_pTypes->Count(); n--; )
+ delete _pTypes->GetObject(n);
+ delete _pTypes;
+ }
+ delete _pIdPool;
+}
+
+//====================================================================
+
+// registers the availability of the Interface of functions
+
+void SfxSlotPool::RegisterInterface( SfxInterface& rInterface )
+{
+ DBG_MEMTEST();
+
+ // add to the list of SfxObjectInterface instances
+ if ( _pInterfaces == 0 )
+ _pInterfaces = new SfxInterfaceArr_Impl;
+ _pInterfaces->Append(&rInterface);
+
+ // bei einem (einzelnen) Null-Slot abbrechen (aus syntaktischen Gr"unden
+ // enthalten interfaces immer mindestens einen Slot)
+ if ( rInterface.Count() == 1 && !rInterface[0]->nSlotId )
+ return;
+
+ // possibly add Interface-id and group-ids of funcs to the list of groups
+ if ( !_pGroups )
+ {
+ _pGroups = new SfxSlotGroupArr_Impl;
+
+ if ( _pParentPool )
+ {
+ // Die Groups im parent Slotpool sind auch hier bekannt
+ SfxSlotGroupArr_Impl& rGroups = *_pParentPool->_pGroups;
+ for ( USHORT n=0; n<rGroups.Count(); n++ )
+ _pGroups->Append( rGroups[n] );
+ }
+ }
+
+ if ( !_pTypes )
+ _pTypes = new SfxSlotTypeArr_Impl;
+ for ( USHORT nFunc = 0; nFunc < rInterface.Count(); ++nFunc )
+ {
+ SfxSlot *pDef = rInterface[nFunc];
+ if ( pDef->GetUnoName() )
+ {
+ if ( !_pUnoSlots )
+ _pUnoSlots = new SfxSlotArr_Impl;
+ _pUnoSlots->Insert( pDef, _pUnoSlots->Count() );
+ }
+
+ if ( pDef->GetGroupId() && /* pDef->GetGroupId() != GID_INTERN && */
+ !_pGroups->Contains(pDef->GetGroupId()) )
+ {
+ if (pDef->GetGroupId() == GID_INTERN)
+ _pGroups->Insert(0, pDef->GetGroupId());
+ else
+ _pGroups->Append(pDef->GetGroupId());
+ }
+
+ const TypeId &rTypeId = pDef->GetType()->Type();
+ if ( rTypeId != TYPE(SfxVoidItem) && rTypeId != 0 )
+ {
+ USHORT nPos;
+ for ( nPos = 0; nPos < _pTypes->Count(); ++nPos )
+ {
+ if ( _pTypes->GetObject(nPos)->nId == pDef->GetSlotId() )
+ {
+ DBG_ASSERT( rTypeId == _pTypes->GetObject(nPos)->nType,
+ "same slot id with unequal item types" );
+ }
+ else if ( _pTypes->GetObject(nPos)->nId > pDef->GetSlotId() )
+ break;
+ }
+ if ( nPos >= _pTypes->Count() ||
+ _pTypes->GetObject(nPos)->nId > pDef->GetSlotId() )
+ _pTypes->Append( new SfxSlotType_Impl( pDef->GetSlotId(), rTypeId ) );
+ }
+ }
+}
+
+//====================================================================
+
+TypeId SfxSlotPool::GetSlotType( USHORT nId ) const
+{
+ for ( USHORT nPos = 0; nPos < _pTypes->Count(); ++nPos )
+ {
+ if ( _pTypes->GetObject(nPos)->nId == nId )
+ return _pTypes->GetObject(nPos)->nType;
+ }
+ return _pParentPool ? _pParentPool->GetSlotType( nId ) : 0;
+}
+
+//====================================================================
+
+// unregisters the availability of the Interface of functions
+
+void SfxSlotPool::ReleaseInterface( SfxInterface& rInterface )
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( _pInterfaces, "releasing SfxInterface, but there are none" );
+ // remove from the list of SfxInterface instances
+ _pInterfaces->Remove(&rInterface);
+}
+
+//--------------------------------------------------------------------
+
+// get the first SfxMessage for a special Id (e.g. for getting check-mode)
+
+const SfxSlot* SfxSlotPool::GetSlot( USHORT nId )
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( _pInterfaces != 0, "no Interfaces registered" );
+
+ // Zun"achst die eigenen Interfaces absuchen
+ for ( USHORT nInterf = 0; nInterf < _pInterfaces->Count(); ++nInterf )
+ {
+ const SfxSlot *pDef =
+ _pInterfaces->GetObject(nInterf)->GetSlot(nId);
+ if ( pDef )
+ return pDef;
+ }
+
+ // Dann beim eventuell vorhandenen parent versuchen
+ return _pParentPool ? _pParentPool->GetSlot( nId ) : 0;
+}
+
+//--------------------------------------------------------------------
+
+// returns the pool of unused ids for macros, menus etc.
+
+IdPool& SfxSlotPool::GetIdPool()
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( _pInterfaces != 0 && _pInterfaces->Count(),
+ "no Interfaces registered" );
+
+ if ( !_pIdPool )
+ {
+ _pIdPool = new IdPool();
+
+ // create a set of all registered function-ids
+ BitSet aRegIds;
+ for ( USHORT nInterface = 0; nInterface < _pInterfaces->Count(); ++nInterface )
+ {
+ SfxInterface* pInterface = (*_pInterfaces)[nInterface];
+ for ( USHORT nFunc = 0; nFunc < pInterface->Count(); ++nFunc )
+ aRegIds |= (*pInterface)[nFunc]->GetGroupId();
+ }
+
+ //lock all registered ids
+ _pIdPool->Lock(aRegIds);
+ }
+
+ return *_pIdPool;
+}
+
+
+//--------------------------------------------------------------------
+
+// stores the id persistent to a stream (expand macros-names)
+
+void SfxSlotPool::StoreId( SvStream& rStream, USHORT nId )
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( _pInterfaces != 0, "no Interfaces registered" );
+
+ rStream << nId;
+ //! later: write 0 and macro-lib/name
+}
+
+
+//--------------------------------------------------------------------
+
+// load a persistent id from a stream (assign id if a macro)
+
+void SfxSlotPool::LoadId( SvStream& rStream, USHORT &rId )
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( _pInterfaces != 0, "no Interfaces registered" );
+
+ rStream >> (unsigned short&) rId;
+}
+
+
+//--------------------------------------------------------------------
+
+// skips to the next group
+
+String SfxSlotPool::SeekGroup( USHORT nNo )
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( _pInterfaces != 0, "no Interfaces registered" );
+
+ // if the group exists, use it
+ if ( _pGroups && nNo < _pGroups->Count() )
+ {
+ _nCurGroup = nNo;
+ if ( _pParentPool )
+ {
+ // Meistens stimmt die Reihenfolge der Ids "uberein
+ USHORT nParentCount = _pParentPool->_pGroups->Count();
+ if ( nNo < nParentCount && (*_pGroups)[nNo] == (*_pParentPool->_pGroups)[nNo] )
+ _pParentPool->_nCurGroup = nNo;
+ else
+ {
+ // Ansonsten mu\s gesucht werden
+ // Wenn die Gruppe im parent pool nicht gefunden wird, wird
+ // _nCurGroup au\serhalb des g"ultigen Bereiches gesetzt
+ USHORT i;
+ for ( i=1; i<nParentCount; i++ )
+ if ( (*_pGroups)[nNo] == (*_pParentPool->_pGroups)[i] )
+ break;
+ _pParentPool->_nCurGroup = i;
+ }
+ }
+
+ SfxResId aResId( (*_pGroups)[_nCurGroup] );
+ aResId.SetRT(RSC_STRING);
+ if ( !aResId.GetResMgr()->IsAvailable(aResId) )
+ {
+ DBG_ERROR( "GroupId-Name nicht im SFX definiert!" );
+ return String();
+ }
+
+ return String( aResId );
+ }
+
+ return String();
+}
+
+
+//--------------------------------------------------------------------
+
+USHORT SfxSlotPool::GetGroupCount()
+{
+ return _pGroups->Count();
+}
+
+
+//--------------------------------------------------------------------
+
+// internal search loop
+
+const SfxSlot* SfxSlotPool::SeekSlot( USHORT nStartInterface )
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( _pInterfaces != 0, "no Interfaces registered" );
+
+ // Die Numerierung der interfaces startet beim parent pool
+ USHORT nFirstInterface = _pParentPool ? _pParentPool->_pInterfaces->Count() : 0;
+
+ // sind wir am Ende des Parent-Pools angekommen?
+ if ( nStartInterface < nFirstInterface &&
+ _pParentPool->_nCurGroup >= _pParentPool->_pGroups->Count() )
+ nStartInterface = nFirstInterface;
+
+ // liegt das Interface noch im Parent-Pool?
+ if ( nStartInterface < nFirstInterface )
+ {
+ DBG_ASSERT( _pParentPool, "Kein parent pool!" );
+ _nCurInterface = nStartInterface;
+ return _pParentPool->SeekSlot( nStartInterface );
+ }
+
+ // find the first func-def with the current group id
+ USHORT nCount = _pInterfaces->Count() + nFirstInterface;
+ for ( _nCurInterface = nStartInterface;
+ _nCurInterface < nCount;
+ ++_nCurInterface )
+ {
+ SfxInterface* pInterface = (*_pInterfaces)[_nCurInterface-nFirstInterface];
+ for ( _nCurMsg = 0;
+ _nCurMsg < pInterface->Count();
+ ++_nCurMsg )
+ {
+ const SfxSlot* pMsg = (*pInterface)[_nCurMsg];
+ if ( pMsg->GetGroupId() == _pGroups->GetObject(_nCurGroup) )
+ return pMsg;
+ }
+ }
+
+ return 0;
+}
+
+//--------------------------------------------------------------------
+
+// skips to the next func in the current group
+
+const SfxSlot* SfxSlotPool::NextSlot()
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( _pInterfaces != 0, "no Interfaces registered" );
+
+ // Die Numerierung der interfaces startet beim parent pool
+ USHORT nFirstInterface = _pParentPool ? _pParentPool->_pInterfaces->Count() : 0;
+
+ if ( _nCurInterface < nFirstInterface && _nCurGroup >= _pParentPool->_pGroups->Count() )
+ _nCurInterface = nFirstInterface;
+
+ if ( _nCurInterface < nFirstInterface )
+ {
+ DBG_ASSERT( _pParentPool, "Kein parent pool!" );
+ const SfxSlot *pSlot = _pParentPool->NextSlot();
+ _nCurInterface = _pParentPool->_nCurInterface;
+ if ( pSlot )
+ return pSlot;
+ if ( _nCurInterface == nFirstInterface )
+ // parent pool ist fertig
+ return SeekSlot( nFirstInterface );
+ }
+
+ USHORT nInterface = _nCurInterface - nFirstInterface;
+ // possibly we are already at the end
+ if ( nInterface >= _pInterfaces->Count() )
+ return 0;
+
+ // look for further matching func-defs within the same Interface
+ SfxInterface* pInterface = (*_pInterfaces)[nInterface];
+ while ( ++_nCurMsg < pInterface->Count() )
+ {
+ SfxSlot* pMsg = (*pInterface)[_nCurMsg];
+ if ( pMsg->GetGroupId() == _pGroups->GetObject(_nCurGroup) )
+ return pMsg;
+ }
+
+ return SeekSlot(++_nCurInterface );
+}
+
+
+//--------------------------------------------------------------------
+
+// SlotName erfragen, gfs. mit HilfeText
+
+String SfxSlotPool::GetSlotName_Impl(USHORT nId, String *pHelpText) const
+{
+ // ist es eine Makro-SlotId?
+ if ( SfxMacroConfig::IsMacroSlot( nId ) )
+ {
+ const SfxMacroInfo *pMacro = SFX_APP()->GetMacroConfig()->GetMacroInfo(nId);
+ if ( pMacro )
+ return pMacro->GetMacroName();
+ else
+ return String();
+ }
+
+ // Zun"achst den eigenen ResManager testen, dann evtl. den des parent pools
+ ResId aResId( nId, _pResMgr );
+ aResId.SetRT( RSC_SFX_SLOT_INFO );
+ if( !Resource::GetResManager()->IsAvailable( aResId ) && _pParentPool )
+ aResId.SetResMgr( _pParentPool->_pResMgr );
+ if( Resource::GetResManager()->IsAvailable( aResId ) )
+ {
+ SfxSlotInfo aInfo(aResId);
+ if(pHelpText)
+ *pHelpText = aInfo.GetHelpText();
+ return aInfo.GetName();
+ }
+
+#ifdef DBG_UTIL
+ String aError(DEFINE_CONST_UNICODE("Slot ohne ConfigName: "));
+ aError += String::CreateFromInt32( nId );
+// DBG_ERROR( aError );
+ return aError;
+#endif
+ return String();
+}
+
+
+//--------------------------------------------------------------------
+
+// SlotName erfragen, gfs. mit HilfeText
+
+String SfxSlotPool::GetSlotHelpText_Impl(USHORT nId) const
+{
+ String aHelpText;
+ GetSlotName_Impl( nId, &aHelpText );
+ return aHelpText;
+}
+
+//--------------------------------------------------------------------
+#ifdef STARBASIC
+
+
+// assignes a request-id for a specific macro
+
+USHORT SfxSlotPool::RegisterMacro( sbToken aToken )
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( pInterfaces != 0, "no Interfaces registered" );
+ DBG_ASSERT( TRUE, "not implemented - call MI" );
+ return 0;
+}
+
+
+//--------------------------------------------------------------------
+
+// frees the request-id of a specific macro
+
+void SfxSlotPool::ReleaseMacro( sbToken aToken )
+{
+ DBG_MEMTEST();
+ DBG_ASSERT( pInterfaces != 0, "no Interfaces registered" );
+ DBG_ASSERT( TRUE, "not implemented - call MI" );
+}
+
+#endif
+
+//--------------------------------------------------------------------
+
+SfxInterface* SfxSlotPool::FirstInterface()
+{
+ _nCurInterface = 0;
+ if ( !_pInterfaces || !_pInterfaces->Count() )
+ return 0;
+ return _pParentPool ? _pParentPool->FirstInterface() : (*_pInterfaces)[0];
+}
+
+
+//--------------------------------------------------------------------
+
+SfxInterface* SfxSlotPool::NextInterface()
+{
+ _nCurInterface++;
+ USHORT nFirstInterface = _pParentPool ? _pParentPool->_pInterfaces->Count() : 0;
+ if ( _nCurInterface < nFirstInterface )
+ return (*_pParentPool->_pInterfaces)[_nCurInterface];
+ USHORT nInterface = _nCurInterface - nFirstInterface;
+ return nInterface < _pInterfaces->Count() ? (*_pInterfaces)[nInterface] : 0;
+}
+
+//--------------------------------------------------------------------
+
+USHORT SfxSlotPool::RegisterSID( const String &rGroup, const String &rName )
+{
+ return 0;
+}
+
+//--------------------------------------------------------------------
+
+void SfxSlotPool::ReleaseSID( const String &rGroup, const String &rName )
+{
+}
+
+const SfxSlot* SfxSlotPool::GetUnoSlot( USHORT nId )
+{
+ const SfxSlot *pSlot = NULL;
+ if ( _pParentPool )
+ pSlot = _pParentPool->GetUnoSlot( nId );
+
+ if ( !pSlot && _pUnoSlots )
+ {
+ USHORT nCount = _pUnoSlots->Count();
+ for ( USHORT n=0; n<nCount; n++ )
+ {
+ if ( (*_pUnoSlots)[n]->GetSlotId() == nId )
+ {
+ pSlot = (*_pUnoSlots)[n];
+ break;
+ }
+ }
+ }
+
+ return pSlot;
+}
+
+const SfxSlot* SfxSlotPool::GetUnoSlot( const String& rName )
+{
+ const SfxSlot *pSlot = NULL;
+ if ( _pParentPool )
+ pSlot = _pParentPool->GetUnoSlot( rName );
+
+ if ( !pSlot && _pUnoSlots )
+ {
+ USHORT nCount = _pUnoSlots->Count();
+ for ( USHORT n=0; n<nCount; n++ )
+ {
+ if ( rName.EqualsAscii((*_pUnoSlots)[n]->GetUnoName()) )
+ {
+ pSlot = (*_pUnoSlots)[n];
+ break;
+ }
+ }
+ }
+
+ return pSlot;
+}
+
+
+
diff --git a/sfx2/source/control/objface.cxx b/sfx2/source/control/objface.cxx
new file mode 100644
index 000000000000..15b8d55a2753
--- /dev/null
+++ b/sfx2/source/control/objface.cxx
@@ -0,0 +1,1427 @@
+/*************************************************************************
+ *
+ * $RCSfile: objface.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 16:52:29 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <stdlib.h>
+
+#ifndef _TOOLS_RCID_H
+#include <tools/rcid.h>
+#endif
+#pragma hdrstop
+
+#ifndef _STREAM_HXX //autogen
+#include <tools/stream.hxx>
+#endif
+
+#include "module.hxx"
+#include "objface.hxx"
+#include "msg.hxx"
+#include "msgpool.hxx"
+#include "cfgitem.hxx"
+#include "sfxresid.hxx"
+#include "minarray.hxx"
+#include "cfgmgr.hxx"
+#include "tbxmgr.hxx"
+#ifdef _PROXYSHELL_VERWENDEN
+#include "bindings.hxx" // fuer ProxyInterface
+#include "dispatch.hxx" // fuer ProxyInterface
+#endif
+
+DBG_NAME(SfxInterface);
+
+static const USHORT nVersion = 5;
+
+//====================================================================
+
+EXTERN_C
+#if defined( PM2 ) && (!defined( CSET ) && !defined ( MTW ) && !defined( WTC ))
+int _stdcall
+#else
+#ifdef WNT
+int _cdecl
+#else
+int
+#endif
+#endif
+
+SfxCompareSlots_Impl( const void* pSmaller, const void* pBigger )
+{
+ DBG_MEMTEST();
+ return ( (int) ((SfxSlot*)pSmaller)->GetSlotId() ) -
+ ( (int) ((SfxSlot*)pBigger)->GetSlotId() );
+}
+
+//=========================================================================
+
+struct SfxObjectUI_Impl
+{
+ USHORT nPos;
+ USHORT nInterfaceId;
+ ResId aResId;
+ BOOL bVisible;
+ BOOL bContext;
+ String* pName;
+ ULONG nFeature;
+
+ SfxObjectUI_Impl(USHORT n, const ResId& rResId, BOOL bVis, ULONG nFeat,
+ USHORT nClassId=0xFFFF) :
+ nPos(n),
+ aResId(rResId.GetId(), rResId.GetResMgr()),
+ nInterfaceId(nClassId),
+ bVisible(bVis),
+ pName(0),
+ bContext(FALSE),
+ nFeature(nFeat)
+ {
+ aResId.SetRT(rResId.GetRT());
+ }
+
+ ~SfxObjectUI_Impl()
+ {
+ delete pName;
+ }
+};
+
+DECL_PTRARRAY(SfxObjectUIArr_Impl, SfxObjectUI_Impl*, 2, 2);
+
+struct SfxInterface_Impl
+{
+ SfxObjectUIArr_Impl* pObjectBars; // registered ObjectBars
+ SfxObjectUIArr_Impl* pObjectMenues; // registered ObjectMenues
+ SfxObjectUIArr_Impl* pChildWindows; // registered ChildWindows
+ ResId aPopupRes; // registered PopupMenu
+ ResId aStatBarRes; // registered StatusBar
+ SfxModule* pModule;
+
+ SfxInterface_Impl() :
+ aPopupRes((USHORT)0),
+ aStatBarRes((USHORT)0)
+ {
+ pObjectBars = new SfxObjectUIArr_Impl;
+ pObjectMenues = new SfxObjectUIArr_Impl;
+ pChildWindows = new SfxObjectUIArr_Impl;
+ }
+
+ ~SfxInterface_Impl()
+ {
+ USHORT n;
+ for (n=0; n<pObjectBars->Count(); n++)
+ delete (*pObjectBars)[n];
+ delete pObjectBars;
+
+ for (n=0; n<pObjectMenues->Count(); n++)
+ delete (*pObjectMenues)[n];
+ delete pObjectMenues;
+
+ for (n=0; n<pChildWindows->Count(); n++)
+ delete (*pChildWindows)[n];
+ delete pChildWindows;
+ }
+};
+
+//====================================================================
+
+class SfxIFConfig_Impl : public SfxConfigItem
+{
+friend class SfxInterface;
+ USHORT nCount;
+ SfxInterface* pIFace;
+ SfxObjectUIArr_Impl* pObjectBars;
+
+public:
+ SfxIFConfig_Impl(USHORT nClassId, SfxInterface *pIF);
+ virtual ~SfxIFConfig_Impl();
+ virtual int Load(SvStream&);
+ virtual BOOL Store(SvStream&);
+ virtual String GetName() const
+ { if (pIFace->HasName()) return pIFace->GetName();
+ else return String(); }
+ virtual void UseDefault();
+ void SaveDefaults(USHORT);
+};
+
+//-------------------------------------------------------------------------
+
+SfxIFConfig_Impl::SfxIFConfig_Impl(USHORT nClassId, SfxInterface *pIF) :
+ SfxConfigItem(SFX_ITEMTYPE_INTERFACE_START + nClassId),
+ nCount(0),
+ pObjectBars(0),
+ pIFace(pIF)
+{
+ SetInternal(TRUE);
+}
+
+//-------------------------------------------------------------------------
+
+void SfxIFConfig_Impl::SaveDefaults(USHORT nClassId)
+{
+ if ( pObjectBars )
+ return;
+
+ pObjectBars = new SfxObjectUIArr_Impl;
+
+ for (nCount=0; nCount < pIFace->pImpData->pObjectBars->Count(); nCount++)
+ {
+ SfxObjectUI_Impl* pUI = new SfxObjectUI_Impl(
+ pIFace->GetObjectBarPos(nCount),
+ pIFace->GetObjectBarResId(nCount),
+ pIFace->IsObjectBarVisible(nCount),
+ pIFace->GetObjectBarFeature(nCount),
+ nClassId);
+
+ pObjectBars->Append(pUI);
+ pUI->pName = new String(*pIFace->GetObjectBarName(nCount));
+ }
+}
+
+//-------------------------------------------------------------------------
+
+SfxIFConfig_Impl::~SfxIFConfig_Impl()
+{
+ if( pObjectBars )
+ {
+ for (USHORT n=0; n<pObjectBars->Count(); n++)
+ delete (*pObjectBars)[n];
+ delete pObjectBars;
+ }
+}
+
+//-------------------------------------------------------------------------
+
+int SfxIFConfig_Impl::Load(SvStream& rStream)
+{
+ for ( ;pIFace->pImpData->pObjectBars->Count(); )
+ pIFace->ReleaseObjectBar(pIFace->GetObjectBarResId(0).GetId());
+
+ USHORT n;
+ rStream >> n;
+
+ if ( n != nVersion)
+ return SfxConfigItem::WARNING_VERSION;
+
+ rStream >> n;
+ for (USHORT i=0; i<n; i++)
+ {
+ pIFace->LoadObjectBar(i, rStream);
+ }
+
+ return SfxConfigItem::ERR_OK;
+}
+
+//-------------------------------------------------------------------------
+
+BOOL SfxIFConfig_Impl::Store(SvStream& rStream)
+{
+ rStream << nVersion;
+
+ rStream << pIFace->pImpData->pObjectBars->Count();
+ USHORT nIFaceId = GetType() - SFX_ITEMTYPE_INTERFACE_START;
+
+ for (USHORT i=0; i<pIFace->pImpData->pObjectBars->Count(); i++)
+ {
+ pIFace->StoreObjectBar(i, rStream);
+ }
+
+ return TRUE;
+}
+
+//-------------------------------------------------------------------------
+
+void SfxIFConfig_Impl::UseDefault()
+{
+ pIFace->UseDefault();
+}
+
+//====================================================================
+// ctor, registeres a new unit
+
+SfxInterface::SfxInterface( SfxModule *pMod,
+ const char *pClassName,
+ const ResId& rNameResId,
+ USHORT nId,
+ const SfxInterface* pParent,
+ const SfxTypeLibImpl* pLibInfo ):
+ pName(pClassName),
+ nClassId(nId),
+ aNameResId(rNameResId.GetId()),
+ pGenoType(pParent),
+ pTypeLibInfo(pLibInfo),
+ pConfig(NULL),
+ pImpData(0),
+ nCount(0)
+{
+ aNameResId.SetResMgr(rNameResId.GetResMgr());
+ Init( );
+ pImpData->pModule = pMod;
+}
+
+SfxInterface::SfxInterface( SfxModule *pMod,
+ const char *pClassName,
+ const ResId& rNameResId,
+ USHORT nId,
+ const SfxInterface* pParent,
+ const SfxTypeLibImpl* pLibInfo,
+ SfxSlot &rSlotMap, USHORT nSlotCount ):
+ pName(pClassName),
+ nClassId(nId),
+ aNameResId(rNameResId.GetId()),
+ pGenoType(pParent),
+ pTypeLibInfo(pLibInfo),
+ pConfig(NULL),
+ pImpData(0)
+{
+ aNameResId.SetResMgr(rNameResId.GetResMgr());
+ Init();
+ pImpData->pModule = pMod;
+ SetSlotMap( rSlotMap, nSlotCount );
+ // register the functions at the SfxMessagePool
+ if ( pMod )
+ pMod->GetSlotPool()->RegisterInterface(*this);
+ else
+ SFX_APP()->GetAppSlotPool_Impl().RegisterInterface(*this);
+}
+
+void SfxInterface::Init()
+{
+ DBG_MEMTEST();
+ DBG_CTOR(SfxInterface, 0);
+// DBG_ASSERT(nCount, "Anzahl der Slot == NULL");
+
+ if ( nClassId )
+ pConfig = new SfxIFConfig_Impl(nClassId, this);
+ pImpData = new SfxInterface_Impl;
+}
+
+
+void SfxInterface::SetSlotMap( SfxSlot& rSlotMap, USHORT nSlotCount )
+{
+ pSlots = &rSlotMap;
+ nCount = nSlotCount;
+ SfxSlot* pIter = pSlots;
+ if ( 1 == nCount && !pIter->pNextSlot )
+ pIter->pNextSlot = pIter;
+
+ if ( !pIter->pNextSlot )
+ {
+ // sort the SfxSlots by id
+ qsort( pSlots, nCount, sizeof(SfxSlot), SfxCompareSlots_Impl );
+
+ // link masters and slaves
+ USHORT nIter = 1;
+ for ( pIter = pSlots; nIter <= nCount; ++pIter, ++nIter )
+ {
+ //! hier bitte sinnvoll pruefen
+ //! DBG_ASSERT(!(pIter->IsMode(SFX_SLOT_CACHABLE) &&
+ //! pIter->IsMode(SFX_SLOT_VOLATILE)),
+ //! "invalid Flags" );
+ DBG_ASSERT( nIter == nCount ||
+ pIter->GetSlotId() != (pIter+1)->GetSlotId(),
+ "doppelte SID" );
+
+ // jeder Master verweist auf seinen ersten Slave (ENUM), alle
+ // Slaves auf ihren Master.
+ // Slaves verweisen im Ring auf die anderen mit gleichem Master
+ if ( pIter->GetKind() == SFX_KIND_ENUM )
+ {
+ pIter->pLinkedSlot = GetSlot( pIter->nMasterSlotId );
+ DBG_ASSERT( pIter->pLinkedSlot, "slave without master" );
+ if ( !pIter->pLinkedSlot->pLinkedSlot )
+ ( (SfxSlot*) pIter->pLinkedSlot)->pLinkedSlot = pIter;
+
+ if ( 0 == pIter->GetNextSlot() )
+ {
+ SfxSlot *pLastSlot = pIter;
+ for ( USHORT n = nIter; n < Count(); ++n )
+ {
+ SfxSlot *pCurSlot = (pSlots+n);
+ if ( pCurSlot->nMasterSlotId == pIter->nMasterSlotId )
+ {
+ pLastSlot->pNextSlot = pCurSlot;
+ pLastSlot = pCurSlot;
+ }
+ }
+ pLastSlot->pNextSlot = pIter;
+ }
+ }
+ else if ( 0 == pIter->GetNextSlot() )
+ {
+ // Slots verweisen im Ring auf den n"achten mit derselben Statusmethode
+ SfxSlot *pLastSlot = pIter;
+ for ( USHORT n = nIter; n < Count(); ++n )
+ {
+ SfxSlot *pCurSlot = (pSlots+n);
+ if ( pCurSlot->GetStateFnc() == pIter->GetStateFnc() )
+ {
+ pLastSlot->pNextSlot = pCurSlot;
+ pLastSlot = pCurSlot;
+ }
+ }
+ pLastSlot->pNextSlot = pIter;
+ }
+ }
+ }
+#ifdef DBG_UTIL
+ else
+ {
+ USHORT nIter = 1;
+ for ( SfxSlot *pNext = pIter+1; nIter < nCount; ++pNext, ++nIter )
+ {
+
+ if ( pNext->GetSlotId() <= pIter->GetSlotId() )
+ DBG_ERROR ("Falsche Reihenfolge!");
+
+ if ( pIter->GetKind() == SFX_KIND_ENUM )
+ {
+ const SfxSlot *pMasterSlot = GetSlot(pIter->nMasterSlotId);
+ const SfxSlot *pFirstSlave = pMasterSlot->pLinkedSlot;
+ const SfxSlot *pSlave = pFirstSlave;
+ do
+ {
+ if ( pSlave->pLinkedSlot != pMasterSlot )
+ {
+ ByteString aStr("Falsche Master/Slave-Verkettung : ");
+ aStr += ByteString::CreateFromInt32(pMasterSlot->GetSlotId());
+ aStr += " , ";
+ aStr += ByteString::CreateFromInt32(pSlave->GetSlotId());
+ DBG_ERROR(aStr.GetBuffer());
+ }
+
+ if ( pSlave->nMasterSlotId != pMasterSlot->GetSlotId() )
+ {
+ ByteString aStr("Falsche Master/Slave-Ids : ");
+ aStr += ByteString::CreateFromInt32(pMasterSlot->GetSlotId());
+ aStr += " , ";
+ aStr += ByteString::CreateFromInt32(pSlave->GetSlotId());
+ DBG_ERROR(aStr.GetBuffer());
+ }
+
+ pSlave = pSlave->pNextSlot;
+ }
+ while ( pSlave != pFirstSlave );
+ }
+ else
+ {
+ if ( pIter->pLinkedSlot )
+ {
+ if ( pIter->pLinkedSlot->GetKind() != SFX_KIND_ENUM )
+ {
+ ByteString aStr("Slave ist kein enum : ");
+ aStr += ByteString::CreateFromInt32(pIter->GetSlotId());
+ aStr += " , ";
+ aStr += ByteString::CreateFromInt32(pIter->pLinkedSlot->GetSlotId());
+ DBG_ERROR(aStr.GetBuffer());
+ }
+ }
+
+ const SfxSlot *pLastSlot = pIter;
+ const SfxSlot *pCurSlot = pIter;
+ do
+ {
+ pCurSlot = pCurSlot->pNextSlot;
+ if ( pCurSlot->GetStateFnc() != pIter->GetStateFnc() )
+ {
+ ByteString aStr("Verkettete Slots mit verschiedenen StateMethods : ");
+ aStr += ByteString::CreateFromInt32(pCurSlot->GetSlotId());
+ aStr += " , ";
+ aStr += ByteString::CreateFromInt32(pIter->GetSlotId());
+ DBG_ERROR(aStr.GetBuffer());
+ }
+ }
+ while ( pCurSlot != pIter );
+ }
+
+ pIter = pNext;
+ }
+ }
+#endif
+}
+
+
+//--------------------------------------------------------------------
+
+
+
+SfxInterface::~SfxInterface()
+{
+ if (pConfig)
+ delete pConfig;
+
+ SfxModule *pMod = pImpData->pModule;
+ delete pImpData;
+ if ( nClassId )
+ {
+ if ( pMod )
+ pMod->GetSlotPool()->ReleaseInterface(*this);
+ else
+ SFX_APP()->GetAppSlotPool_Impl().ReleaseInterface(*this);
+ }
+}
+
+//--------------------------------------------------------------------
+
+// searches for the specified func
+
+
+const SfxSlot* SfxInterface::GetSlot( USHORT nFuncId ) const
+{
+ DBG_MEMTEST();
+ DBG_CHKTHIS(SfxInterface, 0);
+ DBG_ASSERT( this && pSlots && nCount, "" );
+
+ // find the id using binary search
+ void* p = bsearch( &nFuncId, pSlots, nCount, sizeof(SfxSlot),
+ SfxCompareSlots_Impl );
+ if ( !p && pGenoType )
+ return pGenoType->GetSlot( nFuncId );
+
+ return p ? (const SfxSlot*)p : 0;
+}
+
+const SfxSlot* SfxInterface::GetSlot( const String& rCommand ) const
+{
+ SfxSlotPool& rPool = SFX_SLOTPOOL();
+ for ( USHORT n=0; n<nCount; n++ )
+ {
+ USHORT nId = (pSlots+n)->GetSlotId();
+ if ( rCommand.CompareIgnoreCaseToAscii( rPool.GetSlotName_Impl( nId ) ) == COMPARE_EQUAL )
+ return pSlots+n;
+ }
+
+ return pGenoType ? pGenoType->GetSlot( rCommand ) : NULL;
+}
+
+//--------------------------------------------------------------------
+
+
+const SfxSlot* SfxInterface::GetRealSlot( const SfxSlot *pSlot ) const
+{
+ DBG_MEMTEST();
+ DBG_CHKTHIS(SfxInterface, 0);
+ DBG_ASSERT( this && pSlots && nCount, "" );
+
+ if ( !ContainsSlot_Impl(pSlot) )
+ {
+ if(pGenoType)
+ return pGenoType->GetRealSlot(pSlot);
+ DBG_ERROR("fremder Slot");
+ return 0;
+ }
+
+ return pSlot->pLinkedSlot;
+}
+
+//--------------------------------------------------------------------
+
+
+const SfxSlot* SfxInterface::GetRealSlot( USHORT nSlotId ) const
+{
+ DBG_MEMTEST();
+ DBG_CHKTHIS(SfxInterface, 0);
+ DBG_ASSERT( this && pSlots && nCount, "" );
+
+ const SfxSlot *pSlot = GetSlot(nSlotId);
+ if ( !pSlot )
+ {
+ if(pGenoType)
+ return pGenoType->GetRealSlot(nSlotId);
+ DBG_ERROR("fremder Slot");
+ return 0;
+ }
+
+ return pSlot->pLinkedSlot;
+}
+
+//--------------------------------------------------------------------
+
+
+void SfxInterface::RegisterPopupMenu( const ResId& rResId )
+{
+ DBG_CHKTHIS(SfxInterface, 0);
+ pImpData->aPopupRes = rResId;
+}
+
+//--------------------------------------------------------------------
+
+
+void SfxInterface::LoadConfig()
+{
+ if ( pConfig )
+ {
+ pConfig->SaveDefaults(nClassId);
+
+ // Wenn die Application schon l"auft, wurde das Interface nachtr"aglich
+ // erzeugt und mu\s daher explizit initialisiert werden.
+ if ( Application::IsInExecute() )
+ pConfig->Initialize();
+ }
+}
+
+
+BOOL SfxInterface::IsDefault()
+{
+ if (pConfig)
+ return pConfig->IsDefault();
+ else
+ return TRUE;
+}
+
+
+void SfxInterface::UseDefault()
+{
+ if ( !pConfig )
+ {
+ for (USHORT n=0; n<pImpData->pObjectBars->Count(); n++)
+ delete (*pImpData->pObjectBars)[n];
+ pImpData->pObjectBars->Remove(0, pImpData->pObjectBars->Count());
+ return;
+ }
+ else if ( !pConfig->IsDefault() )
+ {
+ USHORT n;
+ for (n=0; n<pImpData->pObjectBars->Count(); n++)
+ delete (*pImpData->pObjectBars)[n];
+ pImpData->pObjectBars->Remove(0, pImpData->pObjectBars->Count());
+
+ for (n=0; n<pConfig->nCount; n++)
+ {
+ SfxObjectUI_Impl* pUI = new SfxObjectUI_Impl(
+ (*pConfig->pObjectBars)[n]->nPos,
+ (*pConfig->pObjectBars)[n]->aResId,
+ (*pConfig->pObjectBars)[n]->bVisible,
+ (*pConfig->pObjectBars)[n]->nFeature,
+ nClassId);
+
+ pImpData->pObjectBars->Append(pUI);
+ pUI->pName = new String(*((*pConfig->pObjectBars)[n]->pName));
+ }
+ }
+}
+
+//--------------------------------------------------------------------
+
+
+void SfxInterface::SetObjectBarName(const String& rName, USHORT nId)
+{
+ // Objectbar im eigenen Array suchen
+ USHORT nCount = pImpData->pObjectBars->Count();
+ USHORT n;
+ for ( n=0; n<nCount; n++ )
+ if ((*pImpData->pObjectBars)[n]->aResId.GetId() == nId) break;
+
+ if ( n >= nCount )
+ {
+ // Nicht gefunden, in der Superklasse versuchen
+ BOOL bGenoType = ( pGenoType != 0 && !pGenoType->HasName() );
+ if (bGenoType)
+ ((SfxInterface*)pGenoType)->SetObjectBarName ( rName, nId );
+ else
+ DBG_ERROR("Objectbar ist unbekannt!");
+ }
+ else
+ {
+ SfxObjectUI_Impl *pUI = (*pImpData->pObjectBars)[n];
+ delete pUI->pName;
+ pUI->pName = new String( rName );
+ if ( pConfig )
+ pConfig->SetDefault(FALSE);
+ }
+}
+
+
+void SfxInterface::SetObjectBarPos(USHORT nPos, USHORT nId)
+{
+ // Objectbar im eigenen Array suchen
+ USHORT nCount = pImpData->pObjectBars->Count();
+ USHORT n;
+ for ( n=0; n<nCount; n++ )
+ if ((*pImpData->pObjectBars)[n]->aResId.GetId() == nId) break;
+
+ if ( n >= nCount )
+ {
+ // Nicht gefunden, in der Superklasse versuchen
+ BOOL bGenoType = ( pGenoType != 0 && !pGenoType->HasName() );
+ if (bGenoType)
+ ((SfxInterface*)pGenoType)->SetObjectBarPos ( nPos, nId );
+ else
+ DBG_ERROR("Objectbar ist unbekannt!");
+ }
+ else
+ {
+ (*pImpData->pObjectBars)[n]->nPos = nPos;
+ if (pConfig)
+ pConfig->SetDefault(FALSE);
+ }
+}
+
+//-------------------------------------------------------------------------
+
+void SfxInterface::RegisterObjectBar( USHORT nPos, const ResId& rResId,
+ const String *pStr )
+{
+ RegisterObjectBar( nPos, rResId, 0UL, pStr );
+}
+
+
+void SfxInterface::RegisterObjectBar( USHORT nPos, const ResId& rResId,
+ ULONG nFeature, const String *pStr )
+{
+ if ((nPos & SFX_VISIBILITY_MASK) == 0)
+ {
+ if ((nPos & SFX_POSITION_MASK) == 0 )
+ nPos |= SFX_VISIBILITY_CLIENT | SFX_VISIBILITY_STANDARD;
+ else
+ nPos |= (SFX_VISIBILITY_STANDARD | SFX_VISIBILITY_SERVER);
+ }
+
+ // App-Leiste?
+ if ( SFX_OBJECTBAR_APPLICATION == ( nPos & SFX_POSITION_MASK ) )
+ // je nach Desktop oder Einzelapp nur die richtige registrieren
+ if ( !( SFX_VISIBILITY_DESKTOP == ( nPos & SFX_VISIBILITY_DESKTOP ) ) )
+ return;
+ nPos &= ~(USHORT)SFX_VISIBILITY_DESKTOP;
+
+ if( nPos & SFX_VISIBILITY_SERVER )
+ nPos |= SFX_VISIBILITY_PLUGSERVER;
+ if( nPos & SFX_VISIBILITY_CLIENT )
+ nPos |= SFX_VISIBILITY_PLUGCLIENT;
+
+ SfxObjectUI_Impl* pUI = new SfxObjectUI_Impl(nPos, rResId, TRUE, nFeature, nClassId);
+
+ pImpData->pObjectBars->Append(pUI);
+
+ if (pStr == 0)
+ {
+ ResId aResId(rResId);
+ aResId.SetRT(RSC_STRING);
+ aResId.SetResMgr(rResId.GetResMgr());
+ if ( !Resource::GetResManager()->IsAvailable(aResId) )
+ {
+ DBG_ERROR("Der Objectbar-Name fehlt in der Resource!");
+ pUI->pName = new String (DEFINE_CONST_UNICODE("NoName"));
+ }
+ else
+ pUI->pName = new String(aResId);
+ }
+ else
+ pUI->pName = new String(*pStr);
+}
+
+
+void SfxInterface::TransferObjectBar( USHORT nPos, USHORT nId, SfxInterface *pIFace,
+ const String *pStr)
+{
+ if ( !pIFace )
+ {
+ RegisterObjectBar( nPos, nId, pStr );
+ if (pConfig)
+ pConfig->SetDefault(FALSE);
+ return;
+ }
+
+ // Suche den ObjectBar im Quellen-Interface ( GenoType ?? )
+ USHORT n;
+ for (n=0; n<pIFace->pImpData->pObjectBars->Count(); n++)
+ if ((*pIFace->pImpData->pObjectBars)[n]->aResId.GetId() == nId) break;
+
+ DBG_ASSERT(n<pIFace->pImpData->pObjectBars->Count(),"Objectbar ist unbekannt!");
+
+ // Uebernimm ResId und Interface-Id
+ SfxObjectUI_Impl* pUI = new SfxObjectUI_Impl(nPos,
+ (*pIFace->pImpData->pObjectBars)[n]->aResId,
+ (*pIFace->pImpData->pObjectBars)[n]->bVisible,
+ (*pIFace->pImpData->pObjectBars)[n]->nFeature,
+ (*pIFace->pImpData->pObjectBars)[n]->nInterfaceId);
+ pImpData->pObjectBars->Append(pUI);
+
+ if (pStr == 0)
+ {
+ pUI->pName = new String( *(pIFace->GetObjectBarName(n)));
+ }
+ else
+ pUI->pName = new String(*pStr);
+
+ if (pConfig)
+ pConfig->SetDefault(FALSE);
+
+ pIFace->ReleaseObjectBar(nId);
+}
+
+
+
+void SfxInterface::ReleaseObjectBar( USHORT nId )
+{
+ // Objectbar im eigenen Array suchen
+ USHORT nCount = pImpData->pObjectBars->Count();
+ USHORT n;
+ for ( n=0; n<nCount; n++ )
+ if ((*pImpData->pObjectBars)[n]->aResId.GetId() == nId) break;
+
+ if ( n >= nCount )
+ {
+ // Nicht gefunden, in der Superklasse versuchen
+ BOOL bGenoType = ( pGenoType != 0 && !pGenoType->HasName() );
+ if (bGenoType)
+ ((SfxInterface*)pGenoType)->ReleaseObjectBar( nId );
+ else
+ DBG_ERROR("Objectbar ist unbekannt!");
+ }
+ else
+ {
+ delete (*pImpData->pObjectBars)[n];
+ pImpData->pObjectBars->Remove(n);
+ if (pConfig)
+ pConfig->SetDefault(FALSE);
+ }
+}
+
+//--------------------------------------------------------------------
+
+
+const ResId& SfxInterface::GetObjectBarResId( USHORT nNo ) const
+{
+ BOOL bGenoType = (pGenoType != 0 && !pGenoType->HasName());
+ if ( bGenoType )
+ {
+ // Gibt es Toolbars in der Superklasse ?
+ USHORT nBaseCount = pGenoType->GetObjectBarCount();
+ if ( nNo < nBaseCount )
+ // Die der Superklasse kommen zuerst
+ return pGenoType->GetObjectBarResId( nNo );
+ else
+ nNo -= nBaseCount;
+ }
+
+ USHORT nCount = pImpData->pObjectBars->Count();
+ DBG_ASSERT( nNo<nCount,"Objectbar ist unbekannt!" );
+ return (*pImpData->pObjectBars)[nNo]->aResId;
+}
+
+//--------------------------------------------------------------------
+
+
+USHORT SfxInterface::GetObjectBarPos( USHORT nNo ) const
+{
+ BOOL bGenoType = (pGenoType != 0 && !pGenoType->HasName());
+ if ( bGenoType )
+ {
+ // Gibt es Toolbars in der Superklasse ?
+ USHORT nBaseCount = pGenoType->GetObjectBarCount();
+ if ( nNo < nBaseCount )
+ // Die der Superklasse kommen zuerst
+ return pGenoType->GetObjectBarPos( nNo );
+ else
+ nNo -= nBaseCount;
+ }
+
+ USHORT nCount = pImpData->pObjectBars->Count();
+ DBG_ASSERT( nNo<nCount,"Objectbar ist unbekannt!" );
+ return (*pImpData->pObjectBars)[nNo]->nPos;
+}
+
+//--------------------------------------------------------------------
+
+
+USHORT SfxInterface::GetObjectBarCount() const
+{
+ if (pGenoType && ! pGenoType->HasName())
+ return pImpData->pObjectBars->Count() + pGenoType->GetObjectBarCount();
+ else
+ return pImpData->pObjectBars->Count();
+}
+
+//--------------------------------------------------------------------
+
+
+const ResId& SfxInterface::GetObjectMenuResId( USHORT nNo ) const
+{
+ DBG_ASSERT(nNo<pImpData->pObjectMenues->Count(),"ObjectMenue ist unbekannt!");
+ return (*pImpData->pObjectMenues)[nNo]->aResId;
+}
+
+//--------------------------------------------------------------------
+
+
+USHORT SfxInterface::GetObjectMenuPos( USHORT nNo ) const
+{
+ DBG_ASSERT(nNo<pImpData->pObjectMenues->Count(),"ObjectMenue ist unbekannt!");
+ return (*pImpData->pObjectMenues)[nNo]->nPos;
+}
+
+//--------------------------------------------------------------------
+
+
+USHORT SfxInterface::GetObjectMenuCount() const
+{
+ return pImpData->pObjectMenues->Count();
+}
+
+void SfxInterface::ClearObjectMenus()
+{
+ for (USHORT n = pImpData->pObjectMenues->Count(); n; )
+ {
+ delete pImpData->pObjectMenues->GetObject( --n );
+ pImpData->pObjectMenues->Remove( n );
+ }
+}
+
+void SfxInterface::RemoveObjectMenu( USHORT nPos )
+{
+ for (USHORT n = pImpData->pObjectMenues->Count(); n; )
+ if( pImpData->pObjectMenues->GetObject(--n)->nPos == nPos )
+ {
+ delete pImpData->pObjectMenues->GetObject( n );
+ pImpData->pObjectMenues->Remove( n );
+ }
+}
+//--------------------------------------------------------------------
+
+
+void SfxInterface::RegisterObjectMenu( USHORT nPos, const ResId& rResId )
+{
+ SfxObjectUI_Impl* pUI = new SfxObjectUI_Impl(nPos, rResId, TRUE, 0, nClassId);
+ pImpData->pObjectMenues->Append(pUI);
+}
+
+//--------------------------------------------------------------------
+
+
+BOOL SfxInterface::StoreObjectBar(USHORT n, SvStream& rStream)
+{
+ rStream << ((*pImpData->pObjectBars)[n]->nPos)
+ << (*pImpData->pObjectBars)[n]->aResId.GetId()
+ << (*pImpData->pObjectBars)[n]->nInterfaceId
+ << (USHORT) (*pImpData->pObjectBars)[n]->bVisible;
+ rStream.WriteByteString(*(*pImpData->pObjectBars)[n]->pName);
+ rStream << (*pImpData->pObjectBars)[n]->nFeature;
+ return TRUE;
+}
+
+//--------------------------------------------------------------------
+
+
+int SfxInterface::LoadObjectBar(USHORT n, SvStream& rStream)
+{
+ DBG_ASSERT( pConfig, "LoadObjectBar ohne Config!" );
+
+ USHORT nId, nPos, nIFaceId, nVisible;
+ ULONG nFeature;
+ String aName;
+
+ rStream >> nPos >> nId >> nIFaceId >> nVisible;
+ rStream.ReadByteString(aName);
+
+ if ( nVersion > 4 )
+ rStream >> nFeature;
+
+ ResId aResId(nId);
+ RegisterObjectBar(nPos, aResId, nFeature, &aName );
+ (*pImpData->pObjectBars)[n]->nInterfaceId = nIFaceId;
+ (*pImpData->pObjectBars)[n]->bVisible = (BOOL) nVisible;
+
+ SfxIFConfig_Impl *pCfg = pConfig;
+
+ if (nIFaceId != nClassId) // pConfig von anderem Interface holen
+ {
+ SfxInterface *pIFace =
+ SFX_APP()->GetInterfaceByIdImpl(SfxInterfaceId(nIFaceId));
+ if (pIFace)
+ pCfg = pIFace->pConfig;
+ }
+
+ ResMgr *pResMgr=0; // falls selbstdefiniert!
+ if (pCfg->pObjectBars->Count())
+ pResMgr = (*pCfg->pObjectBars)[0]->aResId.GetResMgr();
+
+ (*pImpData->pObjectBars)[n]->aResId.SetResMgr(pResMgr);
+
+ return SfxConfigItem::ERR_OK;
+}
+
+
+void SfxInterface::RegisterChildWindow(USHORT nId, BOOL bContext, const String* pName)
+{
+ RegisterChildWindow( nId, bContext, 0UL, pName );
+}
+
+void SfxInterface::RegisterChildWindow(USHORT nId, BOOL bContext, ULONG nFeature, const String*)
+{
+ SfxObjectUI_Impl* pUI = new SfxObjectUI_Impl(0, nId, TRUE, nFeature, 0);
+ pUI->bContext = bContext;
+ pImpData->pChildWindows->Append(pUI);
+}
+
+void SfxInterface::ReleaseChildWindow( USHORT nId )
+{
+ USHORT nCount = pImpData->pChildWindows->Count();
+ USHORT n;
+ for ( n=0; n<nCount; n++ )
+ if ((*pImpData->pChildWindows)[n]->aResId.GetId() == nId) break;
+
+ if ( n >= nCount )
+ {
+ // Nicht gefunden, in der Superklasse versuchen
+ BOOL bGenoType = ( pGenoType != 0 && !pGenoType->HasName() );
+ if (bGenoType)
+ ((SfxInterface*)pGenoType)->ReleaseChildWindow( nId );
+ else
+ DBG_ERROR("ChildWindow ist unbekannt!");
+ }
+ else
+ {
+ delete (*pImpData->pChildWindows)[n];
+ pImpData->pChildWindows->Remove(n);
+ if (pConfig)
+ pConfig->SetDefault(FALSE);
+ }
+}
+
+void SfxInterface::RegisterStatusBar(const ResId& rResId)
+{
+ pImpData->aStatBarRes = rResId;
+}
+
+
+ULONG SfxInterface::GetChildWindowId (USHORT nNo) const
+{
+ if ( pGenoType )
+ {
+ // Gibt es ChildWindows in der Superklasse ?
+ USHORT nBaseCount = pGenoType->GetChildWindowCount();
+ if ( nNo < nBaseCount )
+ // Die der Superklasse kommen zuerst
+ return pGenoType->GetChildWindowId( nNo );
+ else
+ nNo -= nBaseCount;
+ }
+
+ USHORT nCount = pImpData->pChildWindows->Count();
+ DBG_ASSERT( nNo<nCount,"ChildWindow ist unbekannt!" );
+ ULONG nRet = (ULONG) (*pImpData->pChildWindows)[nNo]->aResId.GetId();
+ if ( (*pImpData->pChildWindows)[nNo]->bContext )
+ nRet += ( (ULONG) nClassId ) << 16;
+ return nRet;
+}
+
+ULONG SfxInterface::GetChildWindowFeature (USHORT nNo) const
+{
+ if ( pGenoType )
+ {
+ // Gibt es ChildWindows in der Superklasse ?
+ USHORT nBaseCount = pGenoType->GetChildWindowCount();
+ if ( nNo < nBaseCount )
+ // Die der Superklasse kommen zuerst
+ return pGenoType->GetChildWindowFeature( nNo );
+ else
+ nNo -= nBaseCount;
+ }
+
+ USHORT nCount = pImpData->pChildWindows->Count();
+ DBG_ASSERT( nNo<nCount,"ChildWindow ist unbekannt!" );
+ ULONG nRet = (ULONG) (*pImpData->pChildWindows)[nNo]->nFeature;
+ return nRet;
+}
+
+//--------------------------------------------------------------------
+
+
+USHORT SfxInterface::GetChildWindowCount() const
+{
+ if (pGenoType)
+ return pImpData->pChildWindows->Count() + pGenoType->GetChildWindowCount();
+ else
+ return pImpData->pChildWindows->Count();
+}
+
+
+const ResId& SfxInterface::GetPopupMenuResId() const
+{
+ return pImpData->aPopupRes;
+}
+
+
+const ResId& SfxInterface::GetStatusBarResId() const
+{
+ if (pImpData->aStatBarRes.GetId() == 0 && pGenoType)
+ return pGenoType->GetStatusBarResId();
+ else
+ return pImpData->aStatBarRes;
+}
+
+
+
+const String* SfxInterface::GetObjectBarName ( USHORT nNo ) const
+{
+ BOOL bGenoType = (pGenoType != 0 && !pGenoType->HasName());
+ if ( bGenoType )
+ {
+ // Gibt es Toolbars in der Superklasse ?
+ USHORT nBaseCount = pGenoType->GetObjectBarCount();
+ if ( nNo < nBaseCount )
+ // Die der Superklasse kommen zuerst
+ return pGenoType->GetObjectBarName( nNo );
+ else
+ nNo -= nBaseCount;
+ }
+
+ USHORT nCount = pImpData->pObjectBars->Count();
+ DBG_ASSERT( nNo<nCount,"Objectbar ist unbekannt!" );
+ return (*pImpData->pObjectBars)[nNo]->pName;
+}
+
+ULONG SfxInterface::GetObjectBarFeature ( USHORT nNo ) const
+{
+ BOOL bGenoType = (pGenoType != 0 && !pGenoType->HasName());
+ if ( bGenoType )
+ {
+ // Gibt es Toolbars in der Superklasse ?
+ USHORT nBaseCount = pGenoType->GetObjectBarCount();
+ if ( nNo < nBaseCount )
+ // Die der Superklasse kommen zuerst
+ return pGenoType->GetObjectBarFeature( nNo );
+ else
+ nNo -= nBaseCount;
+ }
+
+ USHORT nCount = pImpData->pObjectBars->Count();
+ DBG_ASSERT( nNo<nCount,"Objectbar ist unbekannt!" );
+ return (*pImpData->pObjectBars)[nNo]->nFeature;
+}
+
+
+BOOL SfxInterface::IsObjectBarVisible(USHORT nNo) const
+{
+ BOOL bGenoType = (pGenoType != 0 && !pGenoType->HasName());
+ if ( bGenoType )
+ {
+ // Gibt es Toolbars in der Superklasse ?
+ USHORT nBaseCount = pGenoType->GetObjectBarCount();
+ if ( nNo < nBaseCount )
+ // Die der Superklasse kommen zuerst
+ return pGenoType->IsObjectBarVisible( nNo );
+ else
+ nNo -= nBaseCount;
+ }
+
+ USHORT nCount = pImpData->pObjectBars->Count();
+ DBG_ASSERT( nNo<nCount,"Objectbar ist unbekannt!" );
+ return (*pImpData->pObjectBars)[nNo]->bVisible;
+}
+
+
+void SfxInterface::SetObjectBarVisible(BOOL bVis, USHORT nId)
+{
+ // Objectbar im eigenen Array suchen
+ USHORT nCount = pImpData->pObjectBars->Count();
+ USHORT n;
+ for ( n=0; n<nCount; n++ )
+ if ( (*pImpData->pObjectBars)[n]->aResId.GetId() == nId ) break;
+
+ if ( n >= nCount )
+ {
+ // Nicht gefunden, in der Superklasse versuchen
+ BOOL bGenoType = (pGenoType != 0 && !pGenoType->HasName());
+ if (bGenoType)
+ ((SfxInterface*)pGenoType)->SetObjectBarVisible(bVis,nId);
+ else
+ DBG_ERROR("Objectbar ist unbekannt!");
+ }
+ else
+ {
+ (*pImpData->pObjectBars)[n]->bVisible = bVis;
+ if (pConfig)
+ pConfig->SetDefault(FALSE);
+ }
+}
+
+
+void SfxInterface::ReInitialize(SfxConfigManager *pCfgMgr)
+{
+ DBG_ASSERT( pConfig, "ReInitialize ohne Config!" );
+
+ SfxConfigManager *pOld = pConfig->GetConfigManager_Impl();
+ if (pCfgMgr == pOld)
+ return;
+ pConfig->ReInitialize(pCfgMgr);
+
+ pCfgMgr->RemoveConfigItem(pConfig);
+ pOld->AddConfigItem(pConfig);
+
+ pConfig->SetDefault(FALSE);
+
+ for (USHORT n=0; n<pImpData->pObjectBars->Count(); n++)
+ {
+ USHORT nId = (*pImpData->pObjectBars)[n]->aResId.GetId();
+ if ( SfxToolBoxManager::IsUserDefToolBox_Impl(nId))
+ {
+ if (!pOld->HasConfigItem(nId))
+ pOld->InsertConfigItem(nId);
+ }
+ }
+}
+
+
+void SfxInterface::SaveConfig()
+{
+ if ( pConfig )
+ pConfig->StoreConfig();
+}
+
+
+USHORT SfxInterface::GetConfigId() const
+{
+ return SFX_ITEMTYPE_INTERFACE_START + nClassId;
+}
+
+
+SfxObjectUIArr_Impl* SfxInterface::GetObjectBarArr_Impl() const
+{
+ return pImpData->pObjectBars;
+}
+
+
+USHORT SfxInterface::RegisterUserDefToolBox(USHORT nId, const String *pName,
+ SfxConfigManager *pCfgMgr)
+{
+ // Zuerst "uber den Namen die ToolBox suchen
+ SfxInterface *pIFace;
+ for (pIFace = SFX_SLOTPOOL().FirstInterface(); pIFace != 0;
+ pIFace = SFX_SLOTPOOL().NextInterface())
+ {
+ // Nur Interfaces mit Namen d"urfen welche bekommen
+ if (pIFace->HasName())
+ {
+ // Zugriff auf ObjectBars
+ SfxObjectUIArr_Impl *pArr = pIFace->GetObjectBarArr_Impl();
+ for (USHORT nNo=0; nNo<pArr->Count(); nNo++)
+ {
+ if ( *pName == *(*pArr)[nNo]->pName)
+ return (*pArr)[nNo]->aResId.GetId();
+ }
+ }
+ }
+
+ // Ansonsten n"achste freie Id besorgen
+ USHORT nFreeId = SfxToolBoxManager::GetUserDefToolBoxId_Impl();
+ BOOL bFound = FALSE;
+
+ // Alle Interfaces durchprobieren, ob sie noch eine UserDefToolBox
+ // aufnehmen k"onnen
+ USHORT nPos;
+ for (pIFace = SFX_SLOTPOOL().FirstInterface(); pIFace != 0;
+ pIFace = SFX_SLOTPOOL().NextInterface())
+ {
+ BOOL bFound = FALSE;
+
+ // Nur Interfaces mit Namen d"urfen welche bekommen
+ if (pIFace->HasName())
+ {
+ // Zugriff auf ObjectBars
+ SfxObjectUIArr_Impl *pArr = pIFace->GetObjectBarArr_Impl();
+
+ for ( nPos=SFX_OBJECTBAR_USERDEF1; nPos<=SFX_OBJECTBAR_USERDEF3; nPos++ )
+ {
+ // Nach freier Position suchen
+ bFound = TRUE;
+ for (USHORT nNo=0; nNo<pArr->Count(); nNo++)
+ {
+ if ( nPos == (*pArr)[nNo]->nPos)
+ {
+ // Diese Position ist schon besetzt, n"achste versuchen
+ bFound = FALSE;
+ break;
+ }
+ }
+
+ // Wurde eine noch freie Position gefunden ?
+ if ( bFound )
+ break;
+ }
+ }
+
+ // Wurde am Interface etwas gefunden ?
+ if ( bFound )
+ break;
+ }
+
+ if ( pIFace )
+ {
+ // Am gefundenen Interface mu\s die Konfiguration ver"andert werden
+ SfxConfigItem *pCfgItem = pIFace->GetConfig_Impl();
+ SfxConfigManager *pOldCfgMgr = pCfgItem->GetConfigManager_Impl();
+
+ if ( pOldCfgMgr != pCfgMgr )
+ {
+ // Wenn das Interface bisher von einem anderen ConfigManager
+ // bedient wird, wird dessen Config gesichert
+ pCfgItem->StoreConfig();
+
+ // Der Ziel-Configmanager mu\s die Konfiguration aufnehmen k"onnen
+ if ( !pCfgMgr->HasConfigItem(pIFace->GetConfigId()) )
+ pCfgMgr->InsertConfigItem(pIFace->GetConfigId());
+
+ // Verbindung mit dem ConfigItem herstellen und Config "ubernehmen
+ pCfgMgr->AddConfigItem(pCfgItem);
+ pCfgItem->Initialize();
+ }
+
+ // Jetzt wird das Interface umkonfiguriert
+ pIFace->RegisterObjectBar(nPos, nFreeId, pName);
+ pIFace->SetObjectBarVisible(TRUE, nFreeId);
+
+ // Konfiguration sichern und aktuellen Stand der Config restaurieren
+ if ( pCfgMgr != pOldCfgMgr && pCfgMgr != SFX_CFGMANAGER() )
+ {
+ pCfgItem->StoreConfig();
+ pCfgMgr->RemoveConfigItem(pCfgItem);
+ pCfgItem->Connect(pOldCfgMgr);
+ pCfgItem->Initialize();
+ }
+ }
+
+ return nFreeId;
+}
+
+
+void SfxInterface::ReleaseUserDefToolBox(USHORT nId, SfxConfigManager *pCfgMgr)
+
+{
+ BOOL bDone = FALSE;
+
+ // Alle Interfaces durchprobieren, ob sie diese UserDefToolBox haben
+ for (SfxInterface *pIFace = SFX_SLOTPOOL().FirstInterface(); pIFace != 0;
+ pIFace = SFX_SLOTPOOL().NextInterface())
+ {
+ // Nur Interfaces mit Namen k"onnen welche haben
+ if (pIFace->HasName())
+ {
+ // Die Konfiguration vom "ubergebenen Manager interessiert
+ SfxConfigItem *pCfgItem = pIFace->GetConfig_Impl();
+ SfxConfigManager *pOldCfgMgr = pCfgItem->GetConfigManager_Impl();
+
+ if ( pOldCfgMgr != pCfgMgr )
+ {
+ // Wenn das Interface bisher von einem anderen ConfigManager
+ // bedient wird, wird dessen Config gesichert
+ pCfgItem->StoreConfig();
+
+ // Verbindung mit dem ConfigItem herstellen und Config "ubernehmen
+ pCfgMgr->AddConfigItem(pCfgItem);
+ pCfgItem->Initialize();
+ }
+
+ if ( pIFace->HasObjectBar(nId) )
+ {
+ pIFace->ReleaseObjectBar(nId);
+ BOOL bDone = TRUE;
+ }
+
+ // Konfiguration sichern und aktuellen Stand der Config restaurieren
+ if ( pCfgMgr != pOldCfgMgr )
+ {
+ pCfgItem->StoreConfig();
+ pCfgMgr->RemoveConfigItem(pCfgItem);
+ pCfgItem->Connect(pOldCfgMgr);
+ pCfgItem->Initialize();
+ }
+ }
+
+ if ( bDone )
+ {
+ break;
+ }
+ }
+}
+
+
+BOOL SfxInterface::HasObjectBar( USHORT nId ) const
+{
+ for (USHORT n=0; n<pImpData->pObjectBars->Count(); n++)
+ if ((*pImpData->pObjectBars)[n]->aResId.GetId() == nId) return TRUE;
+ return FALSE;
+}
+
+SfxModule* SfxInterface::GetModule() const
+{
+ return pImpData->pModule;
+}
+
+const SfxInterface* SfxInterface::GetRealInterfaceForSlot( const SfxSlot *pRealSlot ) const
+{
+ const SfxInterface* pInterface = this;
+
+ // Der Slot k"onnte auch aus dem Interface einer Shell-Basisklasse stammen
+ do
+ {
+ const SfxSlot *pLastSlot = (*pInterface)[pInterface->Count()-1];
+ const SfxSlot *pFirstSlot = (*pInterface)[0];
+
+ // Ist pInterface der Owner von pRealSlot ?
+ if ( pFirstSlot <= pRealSlot && pRealSlot <= pLastSlot )
+ break;
+
+ // Sonst Interface der Superklasse probieren
+ pInterface = pInterface->pGenoType;
+ }
+ while ( pInterface );
+
+ return pInterface;
+}
+
+
diff --git a/sfx2/source/control/request.cxx b/sfx2/source/control/request.cxx
new file mode 100644
index 000000000000..f03edd48cc6d
--- /dev/null
+++ b/sfx2/source/control/request.cxx
@@ -0,0 +1,576 @@
+/*************************************************************************
+ *
+ * $RCSfile: request.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 16:52:29 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _SFXITEMITER_HXX //autogen
+#include <svtools/itemiter.hxx>
+#endif
+
+#ifndef _ARGS_HXX //autogen
+#include <svtools/args.hxx>
+#endif
+
+#ifndef _SVTOOLS_ITEMDEL_HXX
+#include <svtools/itemdel.hxx>
+#endif
+
+#include <svtools/itempool.hxx>
+
+#pragma hdrstop
+
+#include "request.hxx"
+#include "dispatch.hxx"
+#include "sfxtypes.hxx"
+#include "msg.hxx"
+#include "objsh.hxx"
+#include "saveopt.hxx"
+#include "viewfrm.hxx"
+#include "viewsh.hxx"
+#include "app.hxx"
+#include "objface.hxx"
+
+//===================================================================
+
+struct SfxRequest_Impl: public SfxListener
+
+/* [Beschreibung]
+
+ Implementations-Struktur der Klasse <SfxRequest>.
+*/
+
+{
+ SfxRequest* pAnti; // Owner wegen sterbendem Pool
+ SfxItemPool* pPool; // ItemSet mit diesem Pool bauen
+ SfxPoolItem* pRetVal; // R"uckgabewert geh"ort sich selbst
+ const SfxShell* pShell; // ausgef"uhrt an dieser Shell
+ const SfxSlot* pSlot; // ausgef"uhrter Slot
+ USHORT nModifier; // welche Modifier waren gedrueckt?
+ BOOL bDone; // "uberhaupt ausgef"uhrt
+ BOOL bIgnored; // vom User abgebrochen
+ BOOL bCancelled; // nicht mehr zustellen
+ USHORT nCallMode; // Synch/Asynch/API/Record
+ SfxAllItemSet* pInternalArgs;
+
+ SfxRequest_Impl( SfxRequest *pOwner )
+ : pAnti( pOwner), bCancelled(FALSE),
+ nCallMode( SFX_CALLMODE_SYNCHRON ), nModifier(0),
+ pPool(0), pInternalArgs( 0 )
+ {}
+ ~SfxRequest_Impl() { delete pInternalArgs; }
+
+
+ void SetPool( SfxItemPool *pNewPool );
+ virtual void Notify( SfxBroadcaster &rBC, const SfxHint &rHint );
+};
+
+
+//====================================================================
+
+void SfxRequest_Impl::Notify( SfxBroadcaster &rBC, const SfxHint &rHint )
+{
+ SfxSimpleHint *pSimpleHint = PTR_CAST(SfxSimpleHint, &rHint);
+ if ( pSimpleHint && pSimpleHint->GetId() == SFX_HINT_DYING )
+ pAnti->Cancel();
+}
+
+//====================================================================
+
+void SfxRequest_Impl::SetPool( SfxItemPool *pNewPool )
+{
+ if ( pNewPool != pPool )
+ {
+ if ( pPool )
+ EndListening( pPool->BC() );
+ pPool = pNewPool;
+ if ( pNewPool )
+ StartListening( pNewPool->BC() );
+ }
+}
+
+//====================================================================
+
+
+SfxRequest::~SfxRequest()
+{
+ DBG_MEMTEST();
+ // nicht mit Done() marktierte Requests mit 'rem' rausschreiben
+
+ // Objekt abr"aumen
+ delete pArgs;
+ if ( pImp->pRetVal )
+ DeleteItemOnIdle(pImp->pRetVal);
+ delete pImp;
+}
+//--------------------------------------------------------------------
+
+
+SfxRequest::SfxRequest
+(
+ const SfxRequest& rOrig
+)
+: nSlot(rOrig.nSlot),
+ pArgs(rOrig.pArgs? new SfxAllItemSet(*rOrig.pArgs): 0),
+ pImp( new SfxRequest_Impl(this) )
+{
+ DBG_MEMTEST();
+
+ pImp->bDone = FALSE;
+ pImp->bIgnored = FALSE;
+ pImp->pRetVal = 0;
+ pImp->pShell = 0;
+ pImp->pSlot = 0;
+ pImp->nCallMode = rOrig.pImp->nCallMode;
+ pImp->nModifier = rOrig.pImp->nModifier;
+
+ if ( pArgs )
+ pImp->SetPool( pArgs->GetPool() );
+ else
+ pImp->SetPool( rOrig.pImp->pPool );
+}
+
+SfxRequest::SfxRequest
+(
+ USHORT nSlotId, // auszuf"uhrende <Slot-Id>
+ SfxCallMode nMode, // Synch/API/...
+ SfxItemPool& rPool // ggf. f"ur das SfxItemSet f"ur Parameter
+)
+
+// creates a SfxRequest without arguments
+
+: nSlot(nSlotId),
+ pArgs(0),
+ pImp( new SfxRequest_Impl(this) )
+{
+ DBG_MEMTEST();
+
+ pImp->bDone = FALSE;
+ pImp->bIgnored = FALSE;
+ pImp->SetPool( &rPool );
+ pImp->pRetVal = 0;
+ pImp->pShell = 0;
+ pImp->pSlot = 0;
+ pImp->nCallMode = nMode;
+}
+
+//-----------------------------------------------------------------------
+
+SfxRequest::SfxRequest
+(
+ USHORT nSlotId,
+ USHORT nMode,
+ const SfxAllItemSet& rSfxArgs
+)
+
+// creates a SfxRequest with arguments
+
+: nSlot(nSlotId),
+ pArgs(new SfxAllItemSet(rSfxArgs)),
+ pImp( new SfxRequest_Impl(this) )
+{
+ DBG_MEMTEST();
+
+ pImp->bDone = FALSE;
+ pImp->bIgnored = FALSE;
+ pImp->SetPool( rSfxArgs.GetPool() );
+ pImp->pRetVal = 0;
+ pImp->pShell = 0;
+ pImp->pSlot = 0;
+ pImp->nCallMode = nMode;
+}
+//--------------------------------------------------------------------
+
+USHORT SfxRequest::GetCallMode() const
+{
+ return pImp->nCallMode;
+}
+
+//--------------------------------------------------------------------
+
+BOOL SfxRequest::IsSynchronCall() const
+{
+ return SFX_CALLMODE_SYNCHRON == ( SFX_CALLMODE_SYNCHRON & pImp->nCallMode );
+}
+
+//--------------------------------------------------------------------
+
+void SfxRequest::SetSynchronCall( BOOL bSynchron )
+{
+ if ( bSynchron )
+ pImp->nCallMode |= SFX_CALLMODE_SYNCHRON;
+ else
+ pImp->nCallMode &= ~(USHORT) SFX_CALLMODE_SYNCHRON;
+}
+
+void SfxRequest::SetInternalArgs_Impl( const SfxAllItemSet& rArgs )
+{
+ delete pImp->pInternalArgs;
+ pImp->pInternalArgs = new SfxAllItemSet( rArgs );
+}
+
+const SfxItemSet* SfxRequest::GetInternalArgs_Impl() const
+{
+ return pImp->pInternalArgs;
+}
+
+//--------------------------------------------------------------------
+
+void SfxRequest::SetArgs( const SfxAllItemSet& rArgs )
+{
+ delete pArgs;
+ pArgs = new SfxAllItemSet(rArgs);
+ pImp->SetPool( pArgs->GetPool() );
+}
+
+//--------------------------------------------------------------------
+
+void SfxRequest::AppendItem(const SfxPoolItem &rItem)
+{
+ if(!pArgs)
+ pArgs = new SfxAllItemSet(*pImp->pPool);
+ pArgs->Put(rItem, rItem.Which());
+}
+
+//--------------------------------------------------------------------
+
+void SfxRequest::RemoveItem( USHORT nID )
+{
+ if (pArgs)
+ {
+ pArgs->ClearItem(nID);
+ if ( !pArgs->Count() )
+ DELETEZ(pArgs);
+ }
+}
+
+//--------------------------------------------------------------------
+
+const SfxPoolItem* SfxRequest::GetArg
+(
+ USHORT nSlotId, // Slot-Id oder Which-Id des Parameters
+ FASTBOOL bDeep, // FALSE: nicht in Parent-ItemSets suchen
+ TypeId aType // != 0: RTTI Pruefung mit Assertion
+) const
+{
+ return GetItem( pArgs, nSlotId, bDeep, aType );
+}
+
+
+//--------------------------------------------------------------------
+const SfxPoolItem* SfxRequest::GetItem
+(
+ const SfxItemSet* pArgs,
+ USHORT nSlotId, // Slot-Id oder Which-Id des Parameters
+ FASTBOOL bDeep, // FALSE: nicht in Parent-ItemSets suchen
+ TypeId aType // != 0: RTTI Pruefung mit Assertion
+)
+
+/* [Beschreibung]
+
+ Mit dieser Methode wird der Zugriff auf einzelne Parameter im
+ SfxRequest wesentlich vereinfacht. Insbesondere wird die Typpr"ufung
+ (per Assertion) durchgef"uhrt, wodurch die Applikations-Sourcen
+ wesentlich "ubersichtlicher werden. In der PRODUCT-Version wird
+ eine 0 zur"uckgegeben, wenn das gefundene Item nicht von der
+ angegebenen Klasse ist.
+
+
+ [Beispiel]
+
+ void MyShell::Execute( SfxRequest &rReq )
+ {
+ switch ( rReq.GetSlot() )
+ {
+ case SID_MY:
+ {
+ ...
+ // ein Beispiel ohne Verwendung des Makros
+ const SfxInt32Item *pPosItem = (const SfxUInt32Item*)
+ rReq.GetArg( SID_POS, FALSE, TYPE(SfxInt32Item) );
+ USHORT nPos = pPosItem ? pPosItem->GetValue() : 0;
+
+ // ein Beispiel mit Verwendung des Makros
+ SFX_REQUEST_ARG(rReq, pSizeItem, SfxInt32Item, SID_SIZE, FALSE);
+ USHORT nSize = pSizeItem ? pPosItem->GetValue() : 0;
+
+ ...
+ }
+
+ ...
+ }
+ }
+*/
+
+{
+ if ( pArgs )
+ {
+ // ggf. in Which-Id umrechnen
+ USHORT nWhich = pArgs->GetPool()->GetWhich(nSlotId);
+
+ // ist das Item gesetzt oder bei bDeep==TRUE verf"ugbar?
+ const SfxPoolItem *pItem = 0;
+ if ( ( bDeep ? SFX_ITEM_AVAILABLE : SFX_ITEM_SET )
+ <= pArgs->GetItemState( nWhich, bDeep, &pItem ) )
+ {
+ // stimmt der Typ "uberein?
+ if ( !pItem || pItem->IsA(aType) )
+ return pItem;
+
+ // Item da aber falsch => Programmierfehler
+ DBG_ERROR( "invalid argument type" );
+ }
+ }
+
+ // keine Parameter, nicht gefunden oder falschen Typ gefunden
+ return 0;
+}
+
+//--------------------------------------------------------------------
+
+void SfxRequest::SetReturnValue(const SfxPoolItem &rItem)
+{
+ DBG_ASSERT(!pImp->pRetVal, "Returnwert mehrfach setzen?");
+ if(pImp->pRetVal)
+ delete pImp->pRetVal;
+ pImp->pRetVal = rItem.Clone();
+}
+
+//--------------------------------------------------------------------
+
+const SfxPoolItem* SfxRequest::GetReturnValue() const
+{
+ return pImp->pRetVal;
+}
+
+//--------------------------------------------------------------------
+
+void SfxRequest::Done
+(
+ const SfxItemSet& rSet, /* von der Applikation mitgeteilte Parameter,
+ die z.B. in einem Dialog vom Benuter
+ erfragt wurden, ggf. 0 falls keine
+ Parameter gesetzt wurden */
+
+ FASTBOOL bKeep /* TRUE (default)
+ 'rSet' wird gepeichert und ist "uber
+ GetArgs() abfragbar
+
+ FALSE
+ 'rSet' wird nicht kopiert (schneller) */
+)
+
+/* [Beschreibung]
+
+ Diese Methode mu\s in der <Execute-Methode> des <SfxSlot>s gerufen
+ werden, der den SfxRequest ausgef"uhrt hat, wenn die Ausf"uhrung
+ tats"achlich stattgefunden hat. Wird 'Done()' nicht gerufen, gilt
+ der SfxRequest als abgebrochen.
+
+ Etwaige Returnwerte werden nur durchgereicht, wenn 'Done()' gerufen
+ wurde. Ebenso werden beim Aufzeichnen von Makros nur echte
+ Statements erzeugt, wenn 'Done()' gerufen wurde; f"ur SfxRequests,
+ die nicht derart gekennzeichnet wurden, wird anstelle dessen eine
+ auf die abgebrochene Funktion hinweisende Bemerkung ('rem') eingf"ugt.
+
+
+ [Anmerkung]
+
+ 'Done()' wird z.B. nicht gerufen, wenn ein durch die Funktion gestarteter
+ Dialog vom Benutzer abgebrochen wurde oder das Ausf"uhren aufgrund
+ eines falschen Kontextes (ohne Verwendung separater <SfxShell>s)
+ nicht durchgef"uhrt werden konnte. 'Done()' mu\s sehr wohl gerufen
+ werden, wenn das Ausf"uhren der Funktion zu einem regul"aren Fehler
+ f"uhrte (z.B. Datei konnte nicht ge"offnet werden).
+*/
+
+{
+ pImp->bDone = TRUE;
+
+ // ggf. Items merken, damit StarDraw sie abfragen kann
+ if ( bKeep )
+ {
+ if ( !pArgs )
+ {
+ pArgs = new SfxAllItemSet( rSet );
+ pImp->SetPool( pArgs->GetPool() );
+ }
+ else
+ {
+ SfxItemIter aIter(rSet);
+ const SfxPoolItem* pItem = aIter.FirstItem();
+ while(pItem)
+ {
+ if(!IsInvalidItem(pItem))
+ pArgs->Put(*pItem,pItem->Which());
+ pItem = aIter.NextItem();
+ }
+ }
+ }
+}
+
+//--------------------------------------------------------------------
+
+
+void SfxRequest::Done( BOOL bRelease )
+// [<SfxRequest::Done(SfxItemSet&)>]
+{
+ pImp->bDone = TRUE;
+ if( bRelease )
+ DELETEZ( pArgs );
+}
+
+//--------------------------------------------------------------------
+
+BOOL SfxRequest::IsCancelled() const
+{
+ return pImp->bCancelled;
+}
+
+//--------------------------------------------------------------------
+
+void SfxRequest::Cancel()
+
+/* [Beschreibung]
+
+ Markiert diesen Request als nicht mehr auszufuehren. Wird z.B. gerufen,
+ wenn das Ziel (genauer dessen Pool) stirbt.
+*/
+
+{
+ pImp->bCancelled = TRUE;
+ pImp->SetPool( 0 );
+ DELETEZ( pArgs );
+}
+
+//--------------------------------------------------------------------
+
+
+void SfxRequest::Ignore()
+
+/* [Beschreibung]
+
+ Wird diese Methode anstelle von <SfxRequest::Done()> gerufen, dann
+ wird dieser Request nicht recorded.
+
+
+ [Bespiel]
+
+ Das Selektieren von Tools im StarDraw soll nicht aufgezeichnet werden,
+ dieselben Slots sollen aber zum erzeugen der von den Tools zu
+ erzeugenden Objekte verwendet werde. Also kann nicht NoRecord
+ angegeben werden, dennoch soll u.U. nicht aufgezeichnet werden.
+*/
+
+{
+ // als tats"achlich ausgef"uhrt markieren
+ pImp->bIgnored = TRUE;
+}
+
+//--------------------------------------------------------------------
+
+BOOL SfxRequest::IsDone() const
+
+/* [Beschreibung]
+
+ Mit dieser Methode kann abgefragt werden, ob der SfxRequest tats"achlich
+ ausgef"uhrt wurde oder nicht. Wurde ein SfxRequest nicht ausgef"uhrt,
+ liegt dies z.B. daran, da\s der Benutzer abgebrochen hat oder
+ der Kontext f"ur diesen Request falsch war, dieses aber nicht "uber
+ eine separate <SfxShell> realisiert wurde.
+
+ SfxRequest-Instanzen, die hier FALSE liefern, werden nicht recorded.
+
+
+ [Querverweise]
+
+ <SfxRequest::Done(const SfxItemSet&)>
+ <SfxRequest::Done()>
+*/
+
+{
+ return pImp->bDone;
+}
+
+//--------------------------------------------------------------------
+
+BOOL SfxRequest::IsAPI() const
+
+/* [Beschreibung]
+
+ Liefert TRUE, wenn dieser SfxRequest von einer API (z.B. BASIC)
+ erzeugt wurde, sonst FALSE.
+*/
+
+{
+ return SFX_CALLMODE_API == ( SFX_CALLMODE_API & pImp->nCallMode );
+}
+
+//--------------------------------------------------------------------
+void SfxRequest::SetModifier( USHORT nModi )
+{
+ pImp->nModifier = nModi;
+}
+
+//--------------------------------------------------------------------
+USHORT SfxRequest::GetModifier() const
+{
+ return pImp->nModifier;
+}
+
+
diff --git a/sfx2/source/control/shell.cxx b/sfx2/source/control/shell.cxx
new file mode 100644
index 000000000000..b73b804f5a45
--- /dev/null
+++ b/sfx2/source/control/shell.cxx
@@ -0,0 +1,1524 @@
+/*************************************************************************
+ *
+ * $RCSfile: shell.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 16:52:29 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _SB_SBSTAR_HXX //autogen
+#include <basic/sbstar.hxx>
+#endif
+#ifndef _PSEUDO_HXX //autogen
+#include <so3/pseudo.hxx>
+#endif
+#ifndef _SFXITEMPOOL_HXX //autogen
+#include <svtools/itempool.hxx>
+#endif
+#ifndef _UNDO_HXX //autogen
+#include <svtools/undo.hxx>
+#endif
+#ifndef _SVTOOLS_ITEMDEL_HXX
+#include <svtools/itemdel.hxx>
+#endif
+
+#ifndef _SBXCLASS_HXX //autogen
+#include <svtools/sbx.hxx>
+#endif
+
+#pragma hdrstop
+
+#include "shell.hxx"
+#include "bindings.hxx"
+#include "dispatch.hxx"
+#include "viewfrm.hxx"
+#include "sfxbasic.hxx"
+#include "objface.hxx"
+#include "objsh.hxx"
+#include "viewsh.hxx"
+#include "dispatch.hxx"
+#include "sfxtypes.hxx"
+#include "request.hxx"
+#include "mnumgr.hxx"
+#include "saveopt.hxx"
+#include "statcach.hxx"
+
+//====================================================================
+
+DBG_NAME(SfxShell);
+
+//====================================================================
+
+TYPEINIT0(SfxShell);
+
+//====================================================================
+typedef SfxSlot* SfxSlotPtr;
+SV_DECL_PTRARR_DEL( SfxVerbSlotArr_Impl, SfxSlotPtr, 4, 4);
+SV_IMPL_PTRARR( SfxVerbSlotArr_Impl, SfxSlotPtr);
+
+struct SfxVerbList
+{
+ SfxVerbSlotArr_Impl aSlotArr;
+ SvVerbList aVerbList;
+};
+
+struct SfxShell_Impl: public SfxBroadcaster
+{
+ String aObjectName;// Name des Sbx-Objects
+ SfxItemArray_Impl aItems; // Datenaustausch auf Item-Basis
+ SfxViewShell* pViewSh; // SfxViewShell falls Shell ViewFrame/ViewShell/SubShell ist
+ SfxViewFrame* pFrame; // Frame, falls <UI-aktiv>
+ SfxVerbList* pVerbs;
+ SfxRepeatTarget* pRepeatTarget;
+// SbxObjectRef xParent;
+ BOOL bInAppBASIC;
+ BOOL bActive;
+ ULONG nDisableFlags;
+ ULONG nHelpId;
+ AsynchronLink* pExecuter;
+ AsynchronLink* pUpdater;
+ SfxShell_Impl() : pExecuter( 0 ), pUpdater( 0 ) {}
+ ~SfxShell_Impl() { delete pExecuter; delete pUpdater;}
+};
+
+//====================================================================
+#ifdef DBG_UTIL
+
+String SfxShellIdent_Impl( const SfxShell *pSh )
+
+/* [Beschreibung]
+
+ Interne Hilfesfunktion. Liefert einen die SfxShell 'pSh' beschreibenden
+ String zur"uck. Z.B.: SfxApplication[StarWriter]
+*/
+
+{
+ String aIdent( pSh->ISA(SfxApplication) ? DEFINE_CONST_UNICODE("SfxApplication") :
+ pSh->ISA(SfxViewFrame) ? DEFINE_CONST_UNICODE("SfxViewFrame") :
+ pSh->ISA(SfxViewShell) ? DEFINE_CONST_UNICODE("SfxViewShell") :
+ pSh->ISA(SfxObjectShell) ? DEFINE_CONST_UNICODE("SfxObjectShell") : DEFINE_CONST_UNICODE("SfxShell") );
+ aIdent += 0x005B; // '[' = 5Bh
+ aIdent += pSh->GetName();
+ aIdent += 0x005D; // ']' = 5Dh
+ return aIdent;
+}
+
+#endif
+//====================================================================
+
+void __EXPORT SfxShell::EmptyExecStub(SfxShell *, SfxRequest &)
+{
+}
+
+void __EXPORT SfxShell::EmptyStateStub(SfxShell *, SfxItemSet &)
+{
+}
+
+SfxShell::SfxShell()
+
+/* [Beschreibung]
+
+ Der Konstruktor der Klasse SfxShell initialisierung nur einfache
+ Typen, das dazugeh"orige SbxObject wird erst on-demand erzeugt.
+ Daher ist das Anlegen einer SfxShell Instanz sehr billig.
+*/
+
+: pPool(0),
+ pUndoMgr(0),
+ pImp(0)
+{
+ DBG_CTOR(SfxShell, 0);
+ pImp = new SfxShell_Impl;
+ pImp->pViewSh = 0;
+ pImp->pFrame = 0;
+ pImp->pVerbs = 0;
+ pImp->pRepeatTarget = 0;
+ pImp->bInAppBASIC = FALSE;
+ pImp->nHelpId = 0L;
+ pImp->bActive = FALSE;
+ pImp->nDisableFlags = 0;
+}
+
+//-------------------------------------------------------------------------
+
+SfxShell::SfxShell( SfxViewShell *pViewSh )
+
+/* [Beschreibung]
+
+ Der Konstruktor der Klasse SfxShell initialisierung nur einfache
+ Typen, das dazugeh"orige SbxObject wird erst on-demand erzeugt.
+ Daher ist das Anlegen einer SfxShell Instanz sehr billig.
+*/
+
+: pPool(0),
+ pUndoMgr(0),
+ pImp(0)
+{
+ DBG_CTOR(SfxShell, 0);
+ pImp = new SfxShell_Impl;
+ pImp->pViewSh = pViewSh;
+ pImp->pFrame = 0;
+ pImp->pVerbs = 0;
+ pImp->pRepeatTarget = 0;
+ pImp->bInAppBASIC = FALSE;
+ pImp->nHelpId = 0L;
+ pImp->bActive = FALSE;
+}
+
+//--------------------------------------------------------------------
+
+SfxShell::~SfxShell()
+
+/* [Beschreibung]
+
+ Die Verbindungs zu einem ggf. zugeh"origen SbxObject wird gel"ost.
+ Das SbxObject existiert ggf. weiter, kann aber keine Funktionen
+ mehr ausf"uhren und keine Properties mehr bereitstellen.
+*/
+
+{
+ DBG_DTOR(SfxShell, 0);
+ delete pImp->pVerbs;
+ delete pImp;
+}
+
+//--------------------------------------------------------------------
+
+void SfxShell::SetName( const String &rName )
+
+/* [Beschreibung]
+
+ Setzt den Namen des Shell-Objekts. Mit diesem Namen kann die
+ SfxShell-Instanz vom BASIC aus angesprochen werden.
+*/
+
+{
+ pImp->aObjectName = rName;
+}
+
+//--------------------------------------------------------------------
+
+const String& SfxShell::GetName() const
+
+/* [Beschreibung]
+
+ Liefert den Namen des Shell-Objekts. Mit diesem Namen kann die
+ SfxShell-Instanz vom BASIC aus angesprochen werden.
+*/
+
+{
+ return pImp->aObjectName;
+}
+
+//--------------------------------------------------------------------
+
+SvGlobalName SfxShell::GetGlobalName() const
+
+/* [Beschreibung]
+
+ Liefert den Global Unique Identifier des Shell-Objekts. Mit diesem
+ Namen kann die SfxShell-Instanz z.B. via OLE Automation angesprochen
+ werden, bzw. in der Registration-Database gefunden werden.
+*/
+
+{
+ return SvGlobalName();
+}
+
+//--------------------------------------------------------------------
+
+SfxDispatcher* SfxShell::GetDispatcher() const
+
+/* [Beschreibung]
+
+ Diese Methode liefert einen Pointer auf den <SfxDispatcher>, in
+ dem die SfxShell gerade <UI-aktiv> ist bzw. einen 0-Pointer, wenn
+ sie gerade nicht UI-aktiv ist.
+
+ Der zur"uckgegebene Pointer ist nur im unmittelbaren Kontext des
+ Methodenaufrufs g"ultig.
+*/
+
+{
+ return pImp->pFrame ? pImp->pFrame->GetDispatcher() : 0;
+}
+
+//--------------------------------------------------------------------
+
+SfxViewShell* SfxShell::GetViewShell() const
+
+/* [Beschreibung]
+
+ Liefert bei SubShells die SfxViewShell, in der sie liegen. Sonst und
+ falls nicht vom App-Entwickler angegeben liefert diese Methode 0.
+*/
+
+{
+ return pImp->pViewSh;
+}
+
+//--------------------------------------------------------------------
+
+SfxViewFrame* SfxShell::GetFrame() const
+
+/* [Beschreibung]
+
+ Diese Methode liefert einen Pointer auf den <SfxViewFrame>, dem diese
+ SfxShell-Instanz zugeordnet ist oder in dem sie zur Zeit <UI-aktiv> ist.
+ Ein 0-Pointer wird geliefert, wenn diese SfxShell-OInstanz gerade nicht
+ UI-aktiv ist und auch keinem SfxViewFrame fest zugeordnet ist.
+
+ Der zur"uckgegebene Pointer ist nur im unmittelbaren Kontext des
+ Methodenaufrufs g"ultig.
+
+
+ [Anmerkung]
+
+ Nur Instanzen von Subklasse von SfxApplication und SfxObjectShell sollten
+ hier einen 0-Pointer liefern. Ansonsten liegt ein Fehler im Anwendungs-
+ programm vor (falscher Ctor von SfxShell gerufen).
+
+
+ [Querverweise]
+
+ <SfxViewShell::GetViewFrame()const>
+*/
+
+{
+ if ( pImp->pFrame )
+ return pImp->pFrame;
+ if ( pImp->pViewSh )
+ return pImp->pViewSh->GetViewFrame();
+ return 0;
+}
+
+//--------------------------------------------------------------------
+
+const SfxPoolItem* SfxShell::GetItem
+(
+ USHORT nSlotId // Slot-Id des zu erfragenden <SfxPoolItem>s
+) const
+
+/* [Beschreibung]
+
+ Mit dieser Methode kann auf beliebige Objekte von Subklassen von
+ <SfxPoolItem> zugegriffen werden. Diese Austauschtechnik wird ben"otigt,
+ wenn z.B. spezielle <SfxToolBoxControl> Subklassen Zugriff auf
+ bestimmte Daten z.B. der <SfxObjectShell> ben"otigen.
+
+ Die zur"uckgelieferte Instanz geh"ort der jeweilige SfxShell und
+ darf nur im unmittelbaren Kontext des Methodenaufrufs verwendet werden.
+
+
+ [Querverweise]
+
+ <SfxShell::PutItem(const SfxPoolItem&)>
+ <SfxShell::RemoveItem(USHORT)>
+*/
+
+{
+ for ( USHORT nPos = 0; nPos < pImp->aItems.Count(); ++nPos )
+ if ( pImp->aItems.GetObject(nPos)->Which() == nSlotId )
+ return pImp->aItems.GetObject(nPos);
+ return 0;
+}
+
+//--------------------------------------------------------------------
+
+void SfxShell::RemoveItem
+(
+ USHORT nSlotId // Slot-Id des zu l"oschenden <SfxPoolItem>s
+)
+
+/* [Beschreibung]
+
+ Mit dieser Methode k"onnen die allgemein zur Verf"ugung gestellten
+ Instanzen von Subklassen von <SfxPoolItem> aus der SfxShell entfernt
+ werden.
+
+ Die gespeicherte Instanz wird gel"oscht.
+
+
+ [Querverweise]
+
+ <SfxShell::PutItem(const SfxPoolItem&)>
+ <SfxShell::GetItem(USHORT)>
+*/
+
+{
+ for ( USHORT nPos = 0; nPos < pImp->aItems.Count(); ++nPos )
+ if ( pImp->aItems.GetObject(nPos)->Which() == nSlotId )
+ {
+ // Item entfernen und l"oschen
+ SfxPoolItem *pItem = pImp->aItems.GetObject(nPos);
+ delete pItem;
+ pImp->aItems.Remove(nPos);
+
+ // falls aktiv Bindings benachrichtigen
+ SfxDispatcher *pDispat = GetDispatcher();
+ if ( pDispat )
+ {
+ SfxVoidItem aVoid( nSlotId );
+ pDispat->GetBindings()->Broadcast( SfxPoolItemHint( &aVoid ) );
+ }
+ }
+}
+
+//--------------------------------------------------------------------
+
+void SfxShell::PutItem
+(
+ const SfxPoolItem& rItem /* Instanz, von der eine Kopie erstellt wird,
+ die in der SfxShell in einer Liste
+ gespeichert wird. */
+)
+
+/* [Beschreibung]
+
+ Mit dieser Methode k"onnen beliebige Objekte von Subklassen von
+ <SfxPoolItem> zur Verf"ugung gestellt werden. Diese Austauschtechnik
+ wird ben"otigt, wenn z.B. spezielle <SfxToolBoxControl> Subklassen
+ Zugriff auf bestimmte Daten z.B. der <SfxObjectShell> ben"otigen.
+
+ Falls ein SfxPoolItem mit derselben Slot-Id exisitert, wird dieses
+ automatisch gel"oscht.
+
+
+ [Querverweise]
+
+ <SfxShell::RemoveItem(USHORT)>
+ <SfxShell::GetItem(USHORT)>
+*/
+
+{
+ DBG_ASSERT( !rItem.ISA(SfxSetItem), "SetItems aren't allowed here" );
+ DBG_ASSERT( SfxItemPool::IsSlot( rItem.Which() ),
+ "items with Which-Ids aren't allowed here" );
+
+ // MSC auf WNT/W95 machte hier Mist, Vorsicht bei Umstellungen
+ const SfxPoolItem *pItem = rItem.Clone();
+ SfxPoolItemHint aItemHint( (SfxPoolItem*) pItem );
+ const USHORT nWhich = rItem.Which();
+ SfxPoolItem **ppLoopItem = (SfxPoolItem**) pImp->aItems.GetData();
+ USHORT nPos;
+ for ( nPos = 0; nPos < pImp->aItems.Count(); ++nPos, ++ppLoopItem )
+ {
+ if ( (*ppLoopItem)->Which() == nWhich )
+ {
+ // Item austauschen
+ delete *ppLoopItem;
+ pImp->aItems.Remove(nPos);
+ pImp->aItems.Insert( (SfxPoolItemPtr) pItem, nPos );
+
+ // falls aktiv Bindings benachrichtigen
+ SfxDispatcher *pDispat = GetDispatcher();
+ if ( pDispat )
+ pDispat->GetBindings()->Broadcast( aItemHint );
+ return;
+ }
+ }
+
+ Broadcast( aItemHint );
+ pImp->aItems.Insert((SfxPoolItemPtr)pItem, nPos );
+}
+
+//--------------------------------------------------------------------
+
+SfxInterface* SfxShell::GetInterface() const
+
+/* [Beschreibung]
+
+ Mit dieser virtuellen Methode, die durch das Makro <SFX_DECL_INTERFACE>
+ von jeder Subclass mit eigenen Slots automatisch "uberladen wird, kann
+ auf die zu der Subklasse geh"orende <SfxInterface>-Instanz zugegriffen
+ werden.
+
+ Die Klasse SfxShell selbst hat noch kein eigenes SfxInterface
+ (keine Slots), daher wird ein 0-Pointer zur"uckgeliefert.
+*/
+
+{
+ return 0;
+}
+
+//--------------------------------------------------------------------
+
+SfxBroadcaster* SfxShell::GetBroadcaster()
+
+/* [Beschreibung]
+
+ Liefert einen SfxBroadcaster f"ur diese SfxShell-Instanz bis die
+ Klasse SfxShell von SfxBroadcaster abgeleitet ist.
+*/
+
+{
+ return pImp;
+}
+
+//--------------------------------------------------------------------
+
+SfxUndoManager* SfxShell::GetUndoManager()
+
+/* [Beschreibung]
+
+ Jede Subclass von SfxShell kann "uber einen <SfxUndoManager> verf"ugen.
+ Dieser kann in den abgeleiteten Klasse mit <SfxShell:SetUndoManager()>
+ gesetzt werden.
+
+ Die Klasse SfxShell selbst hat noch keinen SfxUndoManager, es wird
+ daher ein 0-Pointer zur"uckgeliefert.
+*/
+
+{
+ return pUndoMgr;
+}
+
+//--------------------------------------------------------------------
+
+void SfxShell::SetUndoManager( SfxUndoManager *pNewUndoMgr )
+
+/* [Beschreibung]
+
+ Setzt einen <SfxUndoManager> f"ur diese <SfxShell> Instanz. F"ur das
+ Undo wird immer nur der Undo-Manager an der jeweils oben auf dem
+ Stack des <SfxDispatcher> liegenden SfxShell verwendet.
+
+ Am "ubergebenen <SfxUndoManager> wird automatisch die aktuelle
+ Max-Undo-Action-Count Einstellung aus den Optionen gesetzt.
+
+ 'pNewUndoMgr' mu\s bis zum Dtor dieser SfxShell-Instanz oder bis
+ zum n"achsten 'SetUndoManager()' existieren.
+*/
+
+{
+ pUndoMgr = pNewUndoMgr;
+ if ( pUndoMgr )
+ pUndoMgr->SetMaxUndoActionCount( SFX_APP()->GetOptions().GetUndoCount() );
+}
+
+//--------------------------------------------------------------------
+
+SfxRepeatTarget* SfxShell::GetRepeatTarget() const
+
+/* [Beschreibung]
+
+ Liefert einen Pointer auf die <SfxRepeatTarget>-Instanz, die
+ als RepeatTarget bei SID_REPEAT verwendet wird, wenn der
+ von dieser SfxShell gelieferte <SfxUndoManager> angesprochen wird.
+ Der R"uckgabewert kann 0 sein.
+
+
+ [Anmerkung]
+
+ Eine Ableitung von <SfxShell> oder einer ihrer Subklassen von
+ <SfxRepeatTarget> ist nicht zu empfehlen, da Compiler-Fehler
+ provoziert werden (wegen Call-to-Pointer-to-Member-Function to
+ subclass).
+*/
+
+{
+ return pImp->pRepeatTarget;
+}
+
+//--------------------------------------------------------------------
+
+void SfxShell::SetRepeatTarget( SfxRepeatTarget *pTarget )
+
+/* [Beschreibung]
+
+ Setzt den die <SfxRepeatTarget>-Instanz, die bei SID_REPEAT als
+ RepeatTarget verwendet wird, wenn der von dieser SfxShell gelieferte
+ <SfxUndoManager> angesprochen wird. Durch 'pTarget==0' wird SID_REPEAT
+ f"ur diese SfxShell disabled. Die Instanz '*pTarget' mu\s so lange
+ leben, wie sie angemeldet ist.
+
+
+ [Anmerkung]
+
+ Eine Ableitung von <SfxShell> oder einer ihrer Subklassen von
+ <SfxRepeatTarget> ist nicht zu empfehlen, da Compiler-Fehler
+ provoziert werden (wegen Call-to-Pointer-to-Member-Function to
+ subclass).
+*/
+
+{
+ pImp->pRepeatTarget = pTarget;
+}
+
+//--------------------------------------------------------------------
+
+void SfxShell::Invalidate
+(
+ USHORT nId /* Zu invalidierende Slot-Id oder Which-Id.
+ Falls diese 0 ist (default), werden
+ alle z.Zt. von dieser Shell bedienten
+ Slot-Ids invalidiert. */
+)
+
+/* [Beschreibung]
+
+ Mit dieser Methode k"onnen Slots der Subclasses "uber die Slot-Id
+ oder alternativ "uber die Which-Id invalidiert werden. Slot-Ids,
+ die von der Subclass ererbt sind, werden ebenfalls invalidert.
+
+ [Querverweise]
+ <SfxBindings::Invalidate(USHORT)>
+ <SfxBindings::InvalidateAll(BOOL)>
+*/
+
+{
+ if ( !GetViewShell() )
+ {
+#if SUPD>603
+ DBG_ERROR( "wrong Invalidate method called!" );
+#endif
+ return;
+ }
+
+ Invalidate_Impl( GetViewShell()->GetViewFrame()->GetBindings(), nId );
+}
+
+void SfxShell::Invalidate_Impl( SfxBindings& rBindings, USHORT nId )
+{
+ if ( nId == 0 )
+ {
+ rBindings.InvalidateShell( *this, FALSE );
+ }
+ else
+ {
+ const SfxInterface *pIF = GetInterface();
+ do
+ {
+ const SfxSlot *pSlot = pIF->GetSlot(nId);
+ if ( pSlot )
+ {
+ // bei Enum-Slots ist der Master-Slot zu invalidieren
+ if ( SFX_KIND_ENUM == pSlot->GetKind() )
+ pSlot = pSlot->GetLinkedSlot();
+
+ // den Slot selbst und ggf. auch alle Slave-Slots invalidieren
+ rBindings.Invalidate( pSlot->GetSlotId() );
+ for ( const SfxSlot *pSlave = pSlot->GetLinkedSlot();
+ pSlave && pIF->ContainsSlot_Impl( pSlave ) &&
+ pSlave->GetLinkedSlot() == pSlot;
+ ++pSlave )
+ rBindings.Invalidate( pSlave->GetSlotId() );
+
+ return;
+ }
+
+ pIF = pIF->GetGenoType();
+ }
+
+ while ( pIF );
+
+ DBG_WARNING( "W3: invalidating slot-id unknown in shell" );
+ }
+}
+
+//--------------------------------------------------------------------
+
+void SfxShell::DoActivate( SfxViewFrame *pFrame, BOOL bMDI )
+
+/* [Beschreibung]
+
+ Diese Methode steuert die Aktivierung der SfxShell-Instanz. Zun"achst
+ wird durch Aufruf der virtuellen Methode <SfxShell::Activate(BOOL)>
+ der Subclass die M"oglichkeit gegeben, auf das Event zu reagieren.
+
+ Bei bMDI == TRUE wird das zugeh"orige SbxObject 'scharfgeschaltet',
+ so da\s Methoden des Objekts unqualifiziert (ohne den Namen des Objekts)
+ vom BASIC gefunden werden.
+*/
+
+{
+#ifndef PRODUCT
+ const SfxInterface *p_IF = GetInterface();
+ if ( !p_IF )
+ return;
+#endif
+#ifdef DBG_UTIL_VB
+ String aMsg("SfxShell::DoActivate() ");
+ aMsg += (long)this;
+ aMsg += " ";
+ aMsg += GetInterface()->GetName();
+ aMsg += " bMDI ";
+ if ( bMDI ) aMsg += "MDI";
+ DbgTrace( aMsg.GetBuffer() );
+#endif
+
+ if ( bMDI )
+ {
+ // Frame merken, in dem aktiviert wird
+ pImp->pFrame = pFrame;
+ pImp->bActive = TRUE;
+ }
+
+ // Subklasse benachrichtigen
+ Activate(bMDI);
+}
+
+//--------------------------------------------------------------------
+
+void SfxShell::DoDeactivate( SfxViewFrame *pFrame, BOOL bMDI )
+
+/* [Beschreibung]
+
+ Diese Methode steuert die Deaktivierung der SfxShell-Instanz. Bei
+ bMDI == TRUE wird zun"achst das SbxObject in einen Status versetzt,
+ so da\s Methoden vom BASIC aus nur noch qualifiziert gerufen werden
+ k"onnen.
+
+ Dann erh"alt in jedem Fall die Subclass durch Aufruf der virtuellen
+ Methode <SfxShell::Deactivate(BOOL)> die M"oglichkeit auf das Event
+ zu reagieren.
+*/
+
+{
+#ifndef PRODUCT
+ const SfxInterface *p_IF = GetInterface();
+ if ( !p_IF )
+ return;
+#endif
+#ifdef DBG_UTIL_VB
+ String aMsg("SfxShell::DoDeactivate()");
+ aMsg += (long)this;
+ aMsg += " ";
+ aMsg += GetInterface()->GetName();
+ aMsg += " bMDI ";
+ if ( bMDI ) aMsg += "MDI";
+ DbgTrace( aMsg.GetBuffer() );
+#endif
+
+ // nur wenn er vom Frame kommt (nicht z.B. pop der BASIC-IDE vom AppDisp)
+ if ( bMDI && pImp->pFrame == pFrame )
+ {
+ // austragen
+ pImp->pFrame = 0;
+ pImp->bActive = FALSE;
+ }
+
+ // Subklasse benachrichtigen
+ Deactivate(bMDI);
+}
+
+//--------------------------------------------------------------------
+
+BOOL SfxShell::IsActive() const
+{
+ return pImp->bActive;
+}
+
+//--------------------------------------------------------------------
+
+void SfxShell::Activate
+(
+ BOOL bMDI /* TRUE
+ der <SfxDispatcher>, auf dem die SfxShell sich
+ befindet, ist aktiv geworden oder die SfxShell
+ Instanz wurde auf einen aktiven SfxDispatcher
+ gepusht. (vergl. SystemWindow::IsMDIActivate())
+
+ FALSE
+ das zum <SfxViewFrame>, auf dessen SfxDispatcher
+ sich die SfxShell Instanz befindet, wurde
+ aktiviert.
+ (z.B. durch einen geschlossenen Dialog) */
+)
+
+/* [Beschreibung]
+
+ Virtuelle Methode, die beim Aktivieren der SfxShell Instanz gerufen
+ wird, um den Subclasses die Gelegenheit zu geben, auf das Aktivieren
+ zu reagieren.
+
+ Die Basisimplementation ist leer und braucht nicht gerufen zu werden.
+
+
+ [Querverweise]
+ StarView SystemWindow::Activate(BOOL)
+*/
+
+{
+}
+
+//--------------------------------------------------------------------
+
+void SfxShell::Deactivate
+(
+ BOOL bMDI /* TRUE
+ der <SfxDispatcher>, auf dem die SfxShell sich
+ befindet, ist inaktiv geworden oder die SfxShell
+ Instanz wurde auf einen aktiven SfxDispatcher
+ gepoppt. (vergl. SystemWindow::IsMDIActivate())
+
+ FALSE
+ das zum <SfxViewFrame>, auf dessen SfxDispatcher
+ sich die SfxShell Instanz befindet, wurde
+ deaktiviert. (z.B. durch einen Dialog) */
+
+)
+
+/* [Beschreibung]
+
+ Virtuelle Methode, die beim Deaktivieren der SfxShell Instanz gerufen
+ wird, um den Subclasses die Gelegenheit zu geben, auf das Deaktivieren
+ zu reagieren.
+
+ Die Basisimplementation ist leer und braucht nicht gerufen zu werden.
+
+
+ [Querverweise]
+ StarView SystemWindow::Dectivate(BOOL)
+*/
+
+{
+}
+
+void SfxShell::ParentActivate
+(
+)
+
+/* [Beschreibung]
+
+ Ein Parent des <SfxDispatcher>, auf dem die SfxShell sich befindet,
+ ist aktiv geworden, oder die SfxShell Instanz wurde auf einen
+ <SfxDispatcher> gepusht, dessen parent aktiv ist.
+
+ Die Basisimplementation ist leer und braucht nicht gerufen zu werden.
+
+ [Querverweise]
+ SfxShell::Activate()
+*/
+{
+}
+
+//--------------------------------------------------------------------
+
+void SfxShell::ParentDeactivate
+(
+)
+
+/* [Beschreibung]
+
+ Der aktive Parent des <SfxDispatcher>, auf dem die SfxShell sich befindet,
+ ist deaktiviert worden.
+
+ Die Basisimplementation ist leer und braucht nicht gerufen zu werden.
+
+ [Querverweise]
+ SfxShell::Deactivate()
+*/
+{
+}
+
+//--------------------------------------------------------------------
+#if 0
+// falls noch mal "pure virtual function called" auf dem MAC:
+// Bitte MAC nicht mehr unterstuetzen
+// der MPW-Linker will die immer haben, obwohl pure virtual
+
+#ifdef MAC
+extern "C"
+{
+ void debugstr( char *pMsg );
+}
+#endif
+
+SfxItemPool& SfxShell::GetPool()
+{
+ debugstr( "pure virtual function called: SfxShell::GetPool()" );
+ SfxItemPool aPool(0,0);
+ return aPool;
+}
+
+#endif
+
+//--------------------------------------------------------------------
+
+void SfxShell::FillStatusBar( StatusBar& )
+
+/* [Beschreibung]
+
+ Mit dieser Factory-Methode kann der Applikationsprogrammierer einer
+ SfxShell-Subklasse eine eigene Statusbar zuweisen. Der SFx bevorzugt
+ jeweils die Statusbar einer weiter oben auf den <SfxDispatcher>-Stack
+ liegenden SfxShell.
+
+ Die Basisimplementation ist leer und braucht nicht gerufen zu werden.
+
+*/
+
+{
+}
+
+//--------------------------------------------------------------------
+
+ResMgr* SfxShell::GetResMgr() const
+
+/* [Beschreibung]
+
+ Diese Methode liefert den ResMgr der <Resource-DLL>, die von der
+ SfxShell-Instanz verwendet wird. Ist dies ein 0-Pointer, so
+ ist der aktuelle Resource-Manager zu verwenden.
+*/
+
+{
+ return GetInterface()->GetResMgr();
+}
+
+//--------------------------------------------------------------------
+
+FASTBOOL SfxShell::CanExecuteSlot_Impl( const SfxSlot &rSlot )
+
+/* [Beschreibung]
+
+ Diese Methode stellt durch Aufruf der Statusfunktion fest,
+ ob 'rSlot' aktuell ausgef"uhrt werden kann.
+*/
+{
+ // Slot-Status holen
+ SfxItemPool &rPool = GetPool();
+ const USHORT nId = rSlot.GetWhich( rPool );
+ SfxItemSet aSet(rPool, nId, nId);
+ SfxStateFunc pFunc = rSlot.GetStateFnc();
+ CallState( pFunc, aSet );
+ return aSet.GetItemState(nId) != SFX_ITEM_DISABLED;
+}
+
+//--------------------------------------------------------------------
+#if 0
+ULONG SfxShell::ExecuteSlot
+(
+ USHORT nSlot, // In: auszuf"uhrender Slot
+ USHORT nMemberId, // In: MemberId f"ur strukturierte Items
+ SbxVariable& rRet, // Out: Returnwert
+ SbxBase* pArgs // In: 0, einzelner Parameter/Parameterliste
+)
+
+/* [Beschreibung]
+
+ Methode zum Ausf"uhren eines <SfxSlot>s von einem SfxShellObject
+ (BASIC oder andere API).
+
+ Aufrufe von APIs werden nicht recorded (ist ja auch kein <SfxDispatcher>).
+
+
+ [R"uckgabewert]
+
+ ULONG ErrorCode
+*/
+
+{
+ // Slot suchen
+ const SfxSlot *pSlot = GetInterface()->GetSlot(nSlot);
+ if ( !pSlot )
+ return SbxERR_PROC_UNDEFINED;
+
+ // ggf. disabled
+ if ( !pSlot->IsMode(SFX_SLOT_FASTCALL) && !CanExecuteSlot_Impl(*pSlot) )
+ return SbERR_METHOD_FAILED;
+
+ // "ofters ben"otigte Werte
+ SfxItemPool &rPool = GetPool();
+ SfxMapUnit eUserMetric = SFX_APP()->GetOptions().GetUserMetric();
+
+ // Returnwert zum sp"ateren Aufbereiten als SbxVariable merken
+ BOOL bDone = FALSE; // Return nur auswerten, wenn nicht abgebrochen wurde
+ const SfxPoolItem *pRetItem = 0;
+ SbxObject *pOwnObject = GetSbxObject(); // Hack fuer #22783
+
+ // aktuelle Parameter oder Property (impliziter Parameter)?
+ if ( pArgs || pSlot->IsMode(SFX_SLOT_PROPSET) )
+ {
+ // aktuelle Parameter in diesem ItemSet sammeln
+ SfxAllItemSet aSet( rPool );
+
+ // mehrere Parameter?
+ if ( pSlot->IsMode(SFX_SLOT_METHOD) )
+ {
+ // das kann nur ein Methoden-Slot sein
+ DBG_ASSERT( !pArgs || pArgs->ISA(SbxArray), "not an SbxArray as arguments" );
+
+ // "uber die formalen Parameter iterieren
+ USHORT nFormalArgs = pSlot->GetFormalArgumentCount();
+ USHORT nActualArgs = pArgs ? ((SbxArray*)pArgs)->Count() - 1 : 0;
+ USHORT nBasicArg = 0;
+ for ( USHORT nArg = 0;
+ nArg < nFormalArgs && nBasicArg < nActualArgs;
+ ++nArg )
+ {
+ // formale Paramterbeschreibung besorgen
+ const SfxFormalArgument &rArg = pSlot->GetFormalArgument(nArg);
+
+ // Item per Factory erzeugen
+ SfxPoolItem *pItem = rArg.CreateItem();
+ DBG_ASSERT( pItem, "item without factory" );
+ pItem->SetWhich( rPool.GetWhich(rArg.nSlotId) );
+
+ // Konvertieren / ggf. strukturierte Items zusammensetzen
+ ULONG eErr = 0;
+ USHORT nSubCount = rArg.pType->nAttribs;
+ if ( !nSubCount )
+ {
+ // einfaches Item
+ SbxVariable *pSubArg = ((SbxArray*)pArgs)->Get(++nBasicArg);
+ eErr = rPool.SetVariable( *pItem, *pSubArg, eUserMetric );
+ }
+ else
+ {
+ // strukturiertes Item
+ for ( USHORT n = 1; n <= nSubCount && !eErr; ++n )
+ {
+ SbxVariable *pSubArg = ((SbxArray*)pArgs)->Get(++nBasicArg);
+ pSubArg->SetUserData(
+ long(rArg.pType->aAttrib[n-1].nAID) << 20 );
+ eErr = rPool.SetVariable( *pItem, *pSubArg, eUserMetric );
+ }
+ }
+
+ // falls Item erzeugt werden konnte, an Request anh"angen
+ if ( 0 == eErr )
+ aSet.Put( *pItem,pItem->Which() );
+ delete pItem; //! Optimieren (Put mit direkter Uebernahme)
+ if ( 0 != eErr )
+ return eErr;
+ }
+
+ // nicht alle Parameter abger"aumt (zuviele)?
+ if ( nBasicArg < nActualArgs )
+ return SbxERR_WRONG_ARGS;
+ }
+ else
+ {
+ // Instanz von SfxPoolItem-Subklasse besorgen/erzeugen
+ SfxPoolItem *pItem = 0;
+
+ // Teil eines strukturiertes Items?
+ if ( nMemberId )
+ {
+ // => Status-Item besorgen
+ const SfxPoolItem *pState = GetSlotState(nSlot);
+ if ( pState && !pState->ISA(SfxVoidItem) )
+ pItem = pState->Clone();
+ }
+
+ // kein StatusItem oder einfaches/komplexes Item
+ if ( !pItem )
+ {
+ // per Factory erzeugen
+ pItem = pSlot->GetType()->CreateItem();
+ DBG_ASSERT( pItem, "item without factory" );
+ pItem->SetWhich( rPool.GetWhich(nSlot) );
+ }
+
+ // Daten aus Variable in das Item "ubertragen
+ ULONG eErr = rPool.SetVariable( *pItem, rRet, eUserMetric );
+ if ( 0 == eErr )
+ aSet.Put( *pItem,pItem->Which() );
+ delete pItem; //! Optimieren (Put mit direkter Uebernahme)
+ if ( 0 != eErr )
+ return eErr;
+ }
+
+ // via Request mit 'normaler' Execute-Methode ausf"uhren
+ SfxRequest aReq( nSlot, SFX_CALLMODE_API, aSet );
+ aSet.ClearItem(); // pPool k"onnte in _Execute sterben
+ SfxExecFunc pFunc = pSlot->GetExecFnc();
+ CallExec( pFunc, aReq );
+ bDone = aReq.IsDone();
+ pRetItem = aReq.GetReturnValue();
+ }
+ else
+ {
+ // ohne Parameter direkt ausf"uhren
+ SfxRequest aReq( nSlot, SFX_CALLMODE_API, GetPool() );
+// SfxRequest aReq( nSlot, GetPool(), TRUE );
+ SfxExecFunc pFunc = pSlot->GetExecFnc();
+ CallExec( pFunc, aReq );
+ bDone = aReq.IsDone();
+ pRetItem = aReq.GetReturnValue();
+ }
+
+ // in IDL ein Return-Wert angegeben?
+ if ( pSlot->IsMode(SFX_SLOT_METHOD) && rRet.GetType() != SbxVOID )
+ {
+ // ist aber kein Returnwert gesetzt worden?
+ if ( !pRetItem || pRetItem->ISA(SfxVoidItem) )
+ {
+ // Ignore ohne Parameter ist erlaubt und auch normal
+ if ( !bDone )
+ return 0;
+
+ // sonst mu\s einer gesetzt worden sein
+ DBG_ERROR( "IDL hat Return-Wert, Execute-Methode setzt aber keinen!" );
+ return SbxERR_CONVERSION;
+ }
+
+ // Returnwert in SbxVariable packen
+ HACK( #22783 - lebt *this noch? )
+ if ( ((SfxShellObject*)pOwnObject)->GetShell() )
+ GetPool().FillVariable( *pRetItem, rRet, eUserMetric );
+ else
+ pRetItem->FillVariable( rRet, eUserMetric, eUserMetric );
+ }
+
+ return 0;
+}
+#endif
+
+long ShellCall_Impl( void* pObj, void* pArg )
+{
+ ((SfxShell* )pObj)->ExecuteSlot( *(SfxRequest*)pArg, (SfxInterface*)0L );
+ return 0;
+}
+
+/* [Beschreibung]
+ Asynchrones ExecuteSlot fuer das RELOAD
+ */
+
+//--------------------------------------------------------------------
+const SfxPoolItem* SfxShell::ExecuteSlot( SfxRequest& rReq, BOOL bAsync )
+{
+ if( !bAsync )
+ return ExecuteSlot( rReq, (SfxInterface*)0L );
+ else
+ {
+ if( !pImp->pExecuter )
+ pImp->pExecuter = new AsynchronLink(
+ Link( this, ShellCall_Impl ) );
+ pImp->pExecuter->Call( new SfxRequest( rReq ) );
+ return 0;
+ }
+}
+
+const SfxPoolItem* SfxShell::ExecuteSlot
+(
+ SfxRequest &rReq, // der weiterzuleitende <SfxRequest>
+ const SfxInterface* pIF // default = 0 bedeutet virtuell besorgen
+)
+
+/* [Beschreibung]
+
+ Diese Methode erm"oglicht das Weiterleiten eines <SfxRequest> an
+ die angegebene Basis-<SfxShell>.
+
+
+ [Beispiel]
+
+ In einer von SfxViewShell abgeleiteten Klasse soll SID_PRINTDOCDIRECT
+ abgefangen werden. Unter bestimmten Umst"anden soll vor dem Drucken
+ eine Abfrage erscheinen, und der Request soll ggf. abgebrochen werden.
+
+ Dazu ist in der IDL dieser Subklasse der o.g. Slot einzutragen. Die
+ Execute-Methode enth"alt dann skizziert:
+
+ void SubViewShell::Exec( SfxRequest &rReq )
+ {
+ if ( rReq.GetSlot() == SID_PRINTDOCDIRECT )
+ {
+ 'dialog'
+ if ( 'condition' )
+ ExecuteSlot( rReq, SfxViewShell::GetInterface() );
+ }
+ }
+
+ Es braucht i.d.R. kein rReq.Done() gerufen zu werden, da das bereits
+ die Implementierung der SfxViewShell erledigt bzw. abgebrochen wurde.
+
+
+ [Querverweise]
+
+ <SfxShell::GetSlotState(USHORT,const SfxInterface*,SfxItemSet*)>
+*/
+
+{
+ if ( !pIF )
+ pIF = GetInterface();
+ const SfxSlot *pSlot = pIF->GetSlot(rReq.GetSlot());
+ DBG_ASSERT( pSlot, "slot not supported" );
+
+ SfxExecFunc pFunc = pSlot->GetExecFnc();
+ CallExec( pFunc, rReq );
+
+ return rReq.GetReturnValue();
+}
+
+//--------------------------------------------------------------------
+
+const SfxPoolItem* SfxShell::GetSlotState
+(
+ USHORT nSlotId, // Slot-Id des zu befragenden Slots
+ const SfxInterface* pIF, // default = 0 bedeutet virtuell besorgen
+ SfxItemSet* pStateSet // SfxItemSet der Slot-State-Methode
+)
+
+/* [Beschreibung]
+
+ Diese Methode liefert den Status des Slots mit der angegebenen Slot-Id
+ "uber das angegebene Interface.
+
+ Ist der Slot disabled oder in dieser SfxShell (und deren Parent-Shells)
+ nicht bekannt, wird ein 0-Pointer zur"uckgeliefert.
+
+ Hat der Slot keinen Status, wird ein SfxVoidItem zur"uckgeliefert.
+
+ Der Status wird bei pStateSet != 0 gleich in diesem Set gesetzt, so
+ da\s <SfxShell>-Subklassen Slots-"uberladen und auch bei der
+ Status-Methode die Basis-Implementierung rufen k"onnen.
+
+
+ [Beispiel]
+
+ In einer von SfxViewShell abgeleiteten Klasse soll SID_PRINTDOCDIRECT
+ abgefangen werden. Unter bestimmten Umst"anden soll vor dem Drucken
+ eine Abfrage erscheinen, und der Request soll ggf. abgebrochen werden.
+
+ Dazu ist in der IDL dieser Subklasse der o.g. Slot einzutragen. Die
+ Status-Methode enth"alt dann skizziert:
+
+ void SubViewShell::PrintState( SfxItemSet &rState )
+ {
+ if ( rState.GetItemState( SID_PRINTDOCDIRECT ) != SFX_ITEM_UNKNOWN )
+ GetSlotState( SID_PRINTDOCDIRECT, SfxViewShell::GetInterface(),
+ &rState );
+ ...
+ }
+
+
+ [Querverweise]
+
+ <SfxShell::ExecuteSlot(SfxRequest&)>
+*/
+
+{
+ // Slot am angegebenen Interface besorgen
+ if ( !pIF )
+ pIF = GetInterface();
+ SfxItemState eState;
+ SfxItemPool &rPool = GetPool();
+ const SfxSlot *pSlot = pIF->GetSlot(nSlotId);
+ if ( pSlot )
+ // ggf. auf Which-Id mappen
+ nSlotId = pSlot->GetWhich( rPool );
+
+ // Item und Item-Status besorgen
+ const SfxPoolItem *pItem;
+ SfxItemSet aSet( rPool, nSlotId, nSlotId ); // pItem stirbt sonst zu fr"uh
+ if ( pSlot )
+ {
+ // Status-Methode rufen
+ SfxStateFunc pFunc = pSlot->GetStateFnc();
+ CallState( pFunc, aSet );
+ eState = aSet.GetItemState( nSlotId, TRUE, &pItem );
+
+ // ggf. Default-Item besorgen
+ if ( eState == SFX_ITEM_DEFAULT )
+ {
+ if ( SfxItemPool::IsWhich(nSlotId) )
+ pItem = &rPool.GetDefaultItem(nSlotId);
+ else
+ eState = SFX_ITEM_DONTCARE;
+ }
+ }
+ else
+ eState = SFX_ITEM_UNKNOWN;
+
+ // Item und Item-Status auswerten und ggf. in pStateSet mitpflegen
+ SfxPoolItem *pRetItem = 0;
+ if ( eState <= SFX_ITEM_DISABLED )
+ {
+ if ( pStateSet )
+ pStateSet->DisableItem(nSlotId);
+ return 0;
+ }
+ else if ( eState == SFX_ITEM_DONTCARE )
+ {
+ if ( pStateSet )
+ pStateSet->ClearItem(nSlotId);
+ pRetItem = new SfxVoidItem(0);
+ }
+ else
+ {
+ if ( pStateSet && pStateSet->Put( *pItem ) )
+ return &pStateSet->Get( pItem->Which() );
+ pRetItem = pItem->Clone();
+ }
+ DeleteItemOnIdle(pRetItem);
+
+ return pRetItem;
+}
+
+//--------------------------------------------------------------------
+
+SFX_EXEC_STUB(SfxShell, VerbExec)
+SFX_STATE_STUB(SfxShell, VerbState)
+
+
+void SfxShell::SetVerbs(const SvVerbList* pVerbs)
+{
+ SfxViewShell *pViewSh = PTR_CAST ( SfxViewShell, this);
+
+ DBG_ASSERT(pViewSh, "SetVerbs nur an der ViewShell aufrufen!");
+
+ if (pImp->pVerbs)
+ {
+ // Zun"achst alle Statecaches dirty machen, damit keiner mehr versucht,
+ // die Slots zu benutzen
+
+ SfxBindings *pBindings =
+ pViewSh->GetViewFrame()->GetDispatcher()->GetBindings();
+ USHORT nCount = pImp->pVerbs->aSlotArr.Count();
+ for (USHORT n=0; n<nCount ; n++)
+ {
+ USHORT nId = SID_VERB_START + n;
+ pBindings->Invalidate(nId, FALSE, TRUE);
+ }
+
+ DELETEZ (pImp->pVerbs);
+ }
+
+ if (pVerbs)
+ pImp->pVerbs = new SfxVerbList();
+
+ if (pVerbs)
+ {
+ USHORT nr=0;
+ for (USHORT n=0; n<pVerbs->Count(); n++)
+ {
+ SfxSlot *pNewSlot = new SfxSlot;
+ USHORT nSlotId = SID_VERB_START + nr++;
+ DBG_ASSERT(nSlotId <= SID_VERB_END, "Zuviele Verben!");
+ if (nSlotId > SID_VERB_END)
+ break;
+
+ pNewSlot->nSlotId = nSlotId;
+ pNewSlot->nGroupId = 0;
+
+ // Verb-Slots m"ussen asynchron ausgef"uhrt werden, da sie w"ahrend
+ // des Ausf"uhrens zerst"ort werden k"onnten
+ pNewSlot->nFlags = SFX_SLOT_ASYNCHRON;
+ pNewSlot->nMasterSlotId = 0;
+ pNewSlot->nValue = 0;
+ pNewSlot->fnExec = SFX_STUB_PTR(SfxShell,VerbExec);
+ pNewSlot->fnState = SFX_STUB_PTR(SfxShell,VerbState);
+ pNewSlot->pType = 0; HACK(SFX_TYPE(SfxVoidItem))
+ pNewSlot->pName = U2S((*pVerbs)[n].GetName()).getStr();
+ pNewSlot->pLinkedSlot = 0;
+ pNewSlot->nArgDefCount = 0;
+ pNewSlot->pFirstArgDef = 0;
+ pNewSlot->pUnoName = 0;
+
+ if (pImp->pVerbs->aSlotArr.Count())
+ {
+ SfxSlot *pSlot = (pImp->pVerbs->aSlotArr)[0];
+ pNewSlot->pNextSlot = pSlot->pNextSlot;
+ pSlot->pNextSlot = pNewSlot;
+ }
+ else
+ pNewSlot->pNextSlot = pNewSlot;
+
+ pImp->pVerbs->aSlotArr.Insert(pNewSlot, n);
+ pImp->pVerbs->aVerbList.Insert((*pVerbs)[n], n);
+ }
+ }
+
+ if (pViewSh)
+ {
+ // Der Status von SID_OBJECT wird im Controller direkt an der Shell
+ // abgeholt, es reicht also, ein neues StatusUpdate anzuregen
+ SfxBindings *pBindings = pViewSh->GetViewFrame()->GetDispatcher()->
+ GetBindings();
+ pBindings->Invalidate( SID_OBJECT, TRUE, TRUE );
+ }
+}
+
+//--------------------------------------------------------------------
+
+const SvVerbList* SfxShell::GetVerbs() const
+{
+ return pImp->pVerbs ? &pImp->pVerbs->aVerbList : 0;
+}
+
+//--------------------------------------------------------------------
+
+void SfxShell::VerbExec(SfxRequest& rReq)
+{
+ USHORT nId = rReq.GetSlot();
+ SfxViewShell *pViewShell = SfxViewShell::Current();
+ const SvVerbList* pList = pViewShell->GetVerbs();
+
+ for (USHORT n=0; n<pList->Count(); n++)
+ {
+ if (nId == SID_VERB_START + n)
+ {
+ pViewShell->DoVerb((*pList)[n].GetId());
+ rReq.Done();
+ return;
+ }
+ }
+}
+
+//--------------------------------------------------------------------
+
+void SfxShell::VerbState(SfxItemSet &rSet)
+{
+}
+
+//--------------------------------------------------------------------
+
+const SfxSlot* SfxShell::GetVerbSlot_Impl(USHORT nId) const
+{
+// DBG_ASSERT(pImp->pVerbs, "Keine Verben bekannt!");
+ if (!pImp->pVerbs)
+ return 0;
+
+ const SvVerbList& rList = pImp->pVerbs->aVerbList;
+
+ DBG_ASSERT(nId >= SID_VERB_START && nId <= SID_VERB_END,"Falsche VerbId!");
+ USHORT nIndex = nId - SID_VERB_START;
+ DBG_ASSERT(nIndex < rList.Count(),"Falsche VerbId!");
+
+ if (nIndex < rList.Count())
+ return pImp->pVerbs->aSlotArr[nIndex];
+ else
+ return 0;
+}
+
+//--------------------------------------------------------------------
+
+void SfxShell::SetHelpId(ULONG nId)
+{
+ pImp->nHelpId = nId;
+}
+
+//--------------------------------------------------------------------
+
+ULONG SfxShell::GetHelpId() const
+{
+ return pImp->nHelpId;
+}
+
+//--------------------------------------------------------------------
+
+SfxObjectShell* SfxShell::GetObjectShell()
+{
+ if ( GetViewShell() )
+ return GetViewShell()->GetViewFrame()->GetObjectShell();
+ else
+ return NULL;
+}
+
+//--------------------------------------------------------------------
+
+SfxSlotPool& SfxShell::GetSlotPool_Impl() const
+{
+ return SFX_APP()->GetSlotPool( GetFrame() );
+}
+
+BOOL SfxShell::HasUIFeature( ULONG )
+{
+ return FALSE;
+}
+
+long DispatcherUpdate_Impl( void* pObj, void* pArg )
+{
+ ((SfxDispatcher*) pArg)->Update_Impl( TRUE );
+ return 0;
+}
+
+void SfxShell::UIFeatureChanged()
+{
+ SfxViewFrame *pFrame = GetFrame();
+ if ( pFrame && pFrame->IsVisible() )
+ {
+ // Auch dann Update erzwingen, wenn Dispatcher schon geupdated ist,
+ // sonst bleibt evtl. irgendwas in den gebunkerten Tools stecken.
+ // Asynchron aufrufen, um Rekursionen zu vermeiden
+ if ( !pImp->pUpdater )
+ pImp->pUpdater = new AsynchronLink( Link( this, DispatcherUpdate_Impl ) );
+
+ // Mehrfachaufrufe gestattet
+ pImp->pUpdater->Call( pFrame->GetDispatcher(), TRUE );
+ }
+}
+
+void SfxShell::SetDisableFlags( ULONG nFlags )
+{
+ pImp->nDisableFlags = nFlags;
+}
+
+ULONG SfxShell::GetDisableFlags() const
+{
+ return pImp->nDisableFlags;
+}
+
+SfxItemSet* SfxShell::CreateItemSet( USHORT nId )
+{
+ return NULL;
+}
+
+void SfxShell::ApplyItemSet( USHORT nId, const SfxItemSet& rSet )
+{
+}
+
+void SfxShell::SetViewShell_Impl( SfxViewShell* pView )
+{
+ pImp->pViewSh = pView;
+}
+
+
+
diff --git a/sfx2/source/control/srchitem.cxx b/sfx2/source/control/srchitem.cxx
new file mode 100644
index 000000000000..b9ce85cd593a
--- /dev/null
+++ b/sfx2/source/control/srchitem.cxx
@@ -0,0 +1,306 @@
+/*************************************************************************
+ *
+ * $RCSfile: srchitem.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 16:52:29 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+// include ---------------------------------------------------------------
+
+#ifndef __SBX_SBXVARIABLE_HXX
+#include <svtools/sbxvar.hxx>
+#endif
+
+#ifndef _COM_SUN_STAR_UTIL_XREPLACEABLE_HPP_
+#include <com/sun/star/util/XReplaceable.hpp>
+#endif
+#ifndef _COM_SUN_STAR_UTIL_XSEARCHABLE_HPP_
+#include <com/sun/star/util/XSearchable.hpp>
+#endif
+#ifndef _COM_SUN_STAR_UTIL_XSEARCHDESCRIPTOR_HPP_
+#include <com/sun/star/util/XSearchDescriptor.hpp>
+#endif
+#ifndef _COM_SUN_STAR_UTIL_XPROPERTYREPLACE_HPP_
+#include <com/sun/star/util/XPropertyReplace.hpp>
+#endif
+#ifndef _COM_SUN_STAR_UTIL_XREPLACEDESCRIPTOR_HPP_
+#include <com/sun/star/util/XReplaceDescriptor.hpp>
+#endif
+#include <svtools/memberid.hrc>
+//ASDBG #include <usr/uno.hxx>
+
+#pragma hdrstop
+
+#define _SVX_SRCHITEM_CXX
+
+#include "sfxsids.hrc"
+#define ITEMID_SEARCH SID_SEARCH_ITEM
+#include "srchitem.hxx"
+
+#include <sfxuno.hxx>
+
+// STATIC DATA -----------------------------------------------------------
+
+TYPEINIT1_AUTOFACTORY(SvxSearchItem, SfxPoolItem);
+
+// -----------------------------------------------------------------------
+
+SvxSearchItem::SvxSearchItem( const sal_uInt16 nId ) :
+
+ SfxPoolItem( nId ),
+
+ nCommand ( 0 ),
+ aSearchString () ,
+ aReplaceString (),
+ bWordOnly ( sal_False ),
+ bExact ( sal_False ),
+ bBackward ( sal_False ),
+ bSelection ( sal_False ),
+ bRegExp ( sal_False ),
+ bPattern ( sal_False ),
+ bContent ( sal_False ),
+ eFamily ( SFX_STYLE_FAMILY_PARA ),
+ bRowDirection ( sal_True ),
+ bAllTables ( sal_False ),
+ nCellType ( SVX_SEARCHIN_FORMULA ),
+ nAppFlag ( SVX_SEARCHAPP_WRITER ),
+ bLevenshtein ( sal_False ),
+ bLEVRelaxed ( sal_True ),
+ nLEVOther ( 2 ),
+ nLEVShorter ( 2 ),
+ nLEVLonger ( 2 )
+{
+}
+
+// -----------------------------------------------------------------------
+
+SvxSearchItem::SvxSearchItem( const SvxSearchItem& rItem ) :
+
+ SfxPoolItem ( rItem ),
+
+ nCommand ( rItem.nCommand ),
+ aSearchString ( rItem.aSearchString ),
+ aReplaceString ( rItem.aReplaceString ),
+ bWordOnly ( rItem.bWordOnly ),
+ bExact ( rItem.bExact ),
+ bBackward ( rItem.bBackward ),
+ bSelection ( rItem.bSelection ),
+ bRegExp ( rItem.bRegExp ),
+ bPattern ( rItem.bPattern ),
+ bContent ( rItem.bContent ),
+ eFamily ( rItem.eFamily ),
+ bRowDirection ( rItem.bRowDirection ),
+ bAllTables ( rItem.bAllTables ),
+ nCellType ( rItem.nCellType ),
+ nAppFlag ( rItem.nAppFlag ),
+ bLevenshtein ( rItem.bLevenshtein ),
+ bLEVRelaxed ( rItem.bLEVRelaxed ),
+ nLEVOther ( rItem.nLEVOther ),
+ nLEVShorter ( rItem.nLEVShorter ),
+ nLEVLonger ( rItem.nLEVLonger )
+{
+}
+
+// -----------------------------------------------------------------------
+
+int SvxSearchItem::operator==( const SfxPoolItem& rItem ) const
+{
+ DBG_ASSERT( SfxPoolItem::operator==( rItem ), "unequal which or type" );
+
+ return ( nCommand == ( (SvxSearchItem&)rItem ).nCommand ) &&
+ ( aSearchString == ( (SvxSearchItem&)rItem ).aSearchString ) &&
+ ( aReplaceString == ( (SvxSearchItem&)rItem ).aReplaceString ) &&
+ ( bWordOnly == ( (SvxSearchItem&)rItem ).bWordOnly ) &&
+ ( bExact == ( (SvxSearchItem&)rItem ).bExact ) &&
+ ( bBackward == ( (SvxSearchItem&)rItem ).bBackward ) &&
+ ( bSelection == ( (SvxSearchItem&)rItem ).bSelection ) &&
+ ( bRegExp == ( (SvxSearchItem&)rItem ).bRegExp ) &&
+ ( bPattern == ( (SvxSearchItem&)rItem ).bPattern ) &&
+ ( bContent == ( (SvxSearchItem&)rItem ).bContent ) &&
+ ( eFamily == ( (SvxSearchItem&)rItem ).eFamily ) &&
+ ( bRowDirection == ( (SvxSearchItem&)rItem ).bRowDirection ) &&
+ ( bAllTables == ( (SvxSearchItem&)rItem ).bAllTables ) &&
+ ( nCellType == ( (SvxSearchItem&)rItem ).nCellType ) &&
+ ( nAppFlag == ( (SvxSearchItem&)rItem ).nAppFlag ) &&
+ ( bLevenshtein == ( (SvxSearchItem&)rItem ).bLevenshtein ) &&
+ ( bLEVRelaxed == ( (SvxSearchItem&)rItem ).bLEVRelaxed ) &&
+ ( nLEVOther == ( (SvxSearchItem&)rItem ).nLEVOther ) &&
+ ( nLEVShorter == ( (SvxSearchItem&)rItem ).nLEVShorter ) &&
+ ( nLEVLonger == ( (SvxSearchItem&)rItem ).nLEVLonger );
+}
+
+
+//------------------------------------------------------------------------
+
+SfxItemPresentation SvxSearchItem::GetPresentation
+(
+ SfxItemPresentation ePres,
+ SfxMapUnit eCoreUnit,
+ SfxMapUnit ePresUnit,
+ XubString& rText,
+ const International *
+) const
+{
+/*
+ switch ( ePres )
+ {
+ case SFX_ITEM_PRESENTATION_NONE:
+ rText.Erase();
+ return SFX_ITEM_PRESENTATION_NONE;
+ case SFX_ITEM_PRESENTATION_NAMELESS:
+ case SFX_ITEM_PRESENTATION_COMPLETE:
+ {
+ rText = SVX_RESSTR(RID_SVXITEMS_SEARCHCMD_BEGIN + nCommand);
+ rText += cpDelim;
+ rText += aSearchString;
+ rText += cpDelim;
+ rText += aReplaceString;
+ rText += cpDelim;
+ rText += ::GetBoolString( bWordOnly );
+ rText += cpDelim;
+ rText += ::GetBoolString( bExact );
+ rText += cpDelim;
+ rText += ::GetBoolString( bBackward );
+ rText += cpDelim;
+ rText += ::GetBoolString( bSelection );
+ rText += cpDelim;
+ rText += ::GetBoolString( bRegExp );
+ rText += cpDelim;
+ rText += ::GetBoolString( bPattern );
+ rText += cpDelim;
+ rText += ::GetBoolString( bContent );
+ rText += cpDelim;
+ rText += SVX_RESSTR(RID_SVXITEMS_SEARCHSTYLE_BEGIN + (sal_uInt16)eFamily );
+ rText += cpDelim;
+ rText += ::GetBoolString( bRowDirection );
+ rText += cpDelim;
+ rText += ::GetBoolString( bAllTables );
+ rText += cpDelim;
+ rText += SVX_RESSTR(RID_SVXITEMS_SEARCHIN_BEGIN + nCellType);
+ rText += cpDelim;
+ rText += SVX_RESSTR(RID_SVXITEMS_SEARCHAPP_BEGIN + nAppFlag);
+ return ePres;
+ }
+ }
+ */
+ return SFX_ITEM_PRESENTATION_NONE;
+}
+
+void SvxSearchItem::GetFromDescriptor( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XSearchDescriptor >& rDescr )
+{
+ SetSearchString( rDescr->getSearchString() );
+ ::com::sun::star::uno::Any aAny = rDescr->getPropertyValue( DEFINE_CONST_UNICODE("SearchWords") );
+ sal_Bool bTemp ;
+ aAny >>= bTemp ;
+ SetWordOnly( bTemp );
+ aAny = rDescr->getPropertyValue( DEFINE_CONST_UNICODE("SearchCaseSensitive") );
+ aAny >>= bTemp ;
+ SetExact( bTemp );
+ aAny = rDescr->getPropertyValue( DEFINE_CONST_UNICODE("SearchBackwards") );
+ aAny >>= bTemp ;
+ SetBackward( bTemp );
+ aAny = rDescr->getPropertyValue( DEFINE_CONST_UNICODE("SearchInSelection") );
+ aAny >>= bTemp ;
+ SetSelection( bTemp );
+ aAny = rDescr->getPropertyValue( DEFINE_CONST_UNICODE("SearchRegularExpression") );
+ aAny >>= bTemp ;
+ SetRegExp( bTemp );
+ aAny = rDescr->getPropertyValue( DEFINE_CONST_UNICODE("SearchSimilarity") );
+ aAny >>= bTemp ;
+ SetLevenshtein( bTemp );
+ aAny = rDescr->getPropertyValue( DEFINE_CONST_UNICODE("SearchSimilarityRelax") );
+ aAny >>= bTemp ;
+ SetLEVRelaxed( bTemp );
+ aAny = rDescr->getPropertyValue( DEFINE_CONST_UNICODE("SearchSimilarityExchange") );
+ sal_Int16 nTemp ;
+ aAny >>= nTemp ;
+ SetLEVOther( nTemp );
+ aAny = rDescr->getPropertyValue( DEFINE_CONST_UNICODE("SearchSimilarityRemove") );
+ aAny >>= nTemp ;
+ SetLEVShorter( nTemp );
+ aAny = rDescr->getPropertyValue( DEFINE_CONST_UNICODE("SearchSimilarityAdd") );
+ aAny >>= nTemp ;
+ SetLEVLonger( nTemp );
+}
+
+void SvxSearchItem::SetToDescriptor( ::com::sun::star::uno::Reference< ::com::sun::star::util::XSearchDescriptor > & rDescr )
+{
+ rDescr->setSearchString( GetSearchString() );
+ ::com::sun::star::uno::Any aAny;
+ aAny <<= GetWordOnly() ;
+ rDescr->setPropertyValue( DEFINE_CONST_UNICODE("SearchWords"), aAny );
+ aAny <<= GetExact() ;
+ rDescr->setPropertyValue( DEFINE_CONST_UNICODE("SearchCaseSensitive"), aAny );
+ aAny <<= GetBackward() ;
+ rDescr->setPropertyValue( DEFINE_CONST_UNICODE("SearchBackwards"), aAny );
+ aAny <<= GetSelection() ;
+ rDescr->setPropertyValue( DEFINE_CONST_UNICODE("SearchInSelection"), aAny );
+ aAny <<= GetRegExp() ;
+ rDescr->setPropertyValue( DEFINE_CONST_UNICODE("SearchRegularExpression"), aAny );
+ aAny <<= IsLevenshtein() ;
+ rDescr->setPropertyValue( DEFINE_CONST_UNICODE("SearchSimilarity"), aAny );
+ aAny <<= IsLEVRelaxed() ;
+ rDescr->setPropertyValue( DEFINE_CONST_UNICODE("SearchSimilarityRelax"), aAny );
+ aAny <<= GetLEVOther() ;
+ rDescr->setPropertyValue( DEFINE_CONST_UNICODE("SearchSimilarityExchange"), aAny );
+ aAny <<= GetLEVShorter() ;
+ rDescr->setPropertyValue( DEFINE_CONST_UNICODE("SearchSimilarityRemove"), aAny );
+ aAny <<= GetLEVLonger() ;
+ rDescr->setPropertyValue( DEFINE_CONST_UNICODE("SearchSimilarityAdd"), aAny );
+}
+
+
diff --git a/sfx2/source/control/statcach.cxx b/sfx2/source/control/statcach.cxx
new file mode 100644
index 000000000000..d563da2d0005
--- /dev/null
+++ b/sfx2/source/control/statcach.cxx
@@ -0,0 +1,577 @@
+/*************************************************************************
+ *
+ * $RCSfile: statcach.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 16:52:29 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <string> // HACK: prevent conflict between STLPORT and Workshop headers
+
+#ifndef _COM_SUN_STAR_UTIL_XURLTRANSFORMER_HPP_
+#include <com/sun/star/util/XURLTransformer.hpp>
+#endif
+#ifndef _COM_SUN_STAR_FRAME_XCONTROLLER_HPP_
+#include <com/sun/star/frame/XController.hpp>
+#endif
+#ifndef _COM_SUN_STAR_FRAME_XFRAMEACTIONLISTENER_HPP_
+#include <com/sun/star/frame/XFrameActionListener.hpp>
+#endif
+#ifndef _COM_SUN_STAR_FRAME_XCOMPONENTLOADER_HPP_
+#include <com/sun/star/frame/XComponentLoader.hpp>
+#endif
+#ifndef _COM_SUN_STAR_FRAME_XFRAME_HPP_
+#include <com/sun/star/frame/XFrame.hpp>
+#endif
+#ifndef _COM_SUN_STAR_FRAME_FRAMEACTIONEVENT_HPP_
+#include <com/sun/star/frame/FrameActionEvent.hpp>
+#endif
+#ifndef _COM_SUN_STAR_FRAME_FRAMEACTION_HPP_
+#include <com/sun/star/frame/FrameAction.hpp>
+#endif
+#ifndef _CPPUHELPER_WEAK_HXX_
+#include <cppuhelper/weak.hxx>
+#endif
+#include <svtools/eitem.hxx>
+#include <svtools/intitem.hxx>
+#include <svtools/stritem.hxx>
+#include <unotools/processfactory.hxx>
+
+#pragma hdrstop
+
+#include "statcach.hxx"
+#include "msg.hxx"
+#include "ctrlitem.hxx"
+#include "dispatch.hxx"
+#include "sfxtypes.hxx"
+#include "sfxuno.hxx"
+#include "unoctitm.hxx"
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::util;
+
+//====================================================================
+
+DBG_NAME(SfxStateCache);
+DBG_NAME(SfxStateCacheSetState);
+
+SFX_IMPL_XINTERFACE_2( BindDispatch_Impl, OWeakObject, ::com::sun::star::frame::XStatusListener, ::com::sun::star::lang::XEventListener )
+SFX_IMPL_XTYPEPROVIDER_2( BindDispatch_Impl, ::com::sun::star::frame::XStatusListener, ::com::sun::star::lang::XEventListener )
+
+//-----------------------------------------------------------------------------
+BindDispatch_Impl::BindDispatch_Impl( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > & rDisp, const ::com::sun::star::util::URL& rURL, SfxStateCache *pStateCache )
+ : xDisp( rDisp )
+ , aURL( rURL )
+ , pCache( pStateCache )
+{
+ aStatus.IsEnabled = sal_True;
+}
+
+void SAL_CALL BindDispatch_Impl::disposing( const ::com::sun::star::lang::EventObject& rEvent ) throw( ::com::sun::star::uno::RuntimeException )
+{
+ if ( xDisp.is() )
+ {
+ xDisp->removeStatusListener( (::com::sun::star::frame::XStatusListener*) this, ::com::sun::star::util::URL() );
+ xDisp = ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > ();
+ }
+}
+
+void SAL_CALL BindDispatch_Impl::statusChanged( const ::com::sun::star::frame::FeatureStateEvent& rEvent ) throw( ::com::sun::star::uno::RuntimeException )
+{
+ aStatus = rEvent;
+ if ( !pCache )
+ return;
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > xRef( (::cppu::OWeakObject*)this, ::com::sun::star::uno::UNO_QUERY );
+ if ( aStatus.Requery )
+ pCache->Invalidate( sal_True );
+ else
+ {
+ pCache->Invalidate( sal_False );
+ if ( !aStatus.IsEnabled )
+ pCache->SetState_Impl( SFX_ITEM_DISABLED, NULL );
+ else
+ {
+ sal_uInt16 nId = pCache->GetId();
+ SfxItemState eState = SFX_ITEM_AVAILABLE;
+ SfxPoolItem *pItem=NULL;
+ ::com::sun::star::uno::Any aAny = aStatus.State;
+ ::com::sun::star::uno::Type pType = aAny.getValueType();
+
+ if ( pType == ::getBooleanCppuType() )
+ {
+ sal_Bool bTemp ;
+ aAny >>= bTemp ;
+ pItem = new SfxBoolItem( nId, bTemp );
+ }
+ else if ( pType == ::getCppuType((const sal_uInt16*)0) )
+ {
+ sal_uInt16 nTemp ;
+ aAny >>= nTemp ;
+ pItem = new SfxUInt16Item( nId, nTemp );
+ }
+ else if ( pType == ::getCppuType((const sal_uInt32*)0) )
+ {
+ sal_uInt32 nTemp ;
+ aAny >>= nTemp ;
+ pItem = new SfxUInt32Item( nId, nTemp );
+ }
+ else if ( pType == ::getCppuType((const ::rtl::OUString*)0) )
+ {
+ ::rtl::OUString sTemp ;
+ aAny >>= sTemp ;
+ pItem = new SfxStringItem( nId, sTemp );
+ }
+ else
+ pItem = new SfxVoidItem( nId );
+ pCache->SetState_Impl( eState, pItem );
+ delete pItem;
+ }
+ }
+}
+
+void BindDispatch_Impl::Release()
+{
+ if ( xDisp.is() )
+ {
+ xDisp->removeStatusListener( (::com::sun::star::frame::XStatusListener*) this, ::com::sun::star::util::URL() );
+ xDisp = ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > ();
+ }
+
+ pCache = NULL;
+ release();
+}
+
+const ::com::sun::star::frame::FeatureStateEvent& BindDispatch_Impl::GetStatus() const
+{
+ return aStatus;
+}
+
+void BindDispatch_Impl::Dispatch( sal_Bool bForceSynchron )
+{
+ if ( xDisp.is() && aStatus.IsEnabled )
+ if ( bForceSynchron )
+ {
+ ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue > aProps(1);
+ aProps.getArray()[0].Name = DEFINE_CONST_UNICODE("SynchronMode");
+ aProps.getArray()[0].Value <<= sal_True ;
+ xDisp->dispatch( aURL, aProps );
+ }
+ else
+ xDisp->dispatch( aURL, ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >() );
+}
+
+//--------------------------------------------------------------------
+
+/* Dieser Konstruktor fuer einen ungueltigen Cache, der sich also
+ bei der ersten Anfrage zun"achst updated.
+ */
+
+SfxStateCache::SfxStateCache( sal_uInt16 nFuncId ):
+ nId(nFuncId),
+ pController(0),
+ pLastItem( 0 ),
+ eLastState( 0 ),
+ pDispatch( 0 )
+{
+ DBG_MEMTEST();
+ DBG_CTOR(SfxStateCache, 0);
+ bCtrlDirty = sal_True;
+ bSlotDirty = sal_True;
+ bItemDirty = sal_True;
+}
+
+//--------------------------------------------------------------------
+
+/* Der Destruktor pr"uft per Assertion, ob noch Controller angemeldet
+ sind.
+ */
+
+SfxStateCache::~SfxStateCache()
+{
+ DBG_MEMTEST();
+ DBG_DTOR(SfxStateCache, 0);
+ DBG_ASSERT( pController == 0, "es sind noch Controller angemeldet" );
+ if ( !IsInvalidItem(pLastItem) )
+ delete pLastItem;
+ if ( pDispatch )
+ {
+ pDispatch->Release();
+ pDispatch = NULL;
+ }
+}
+
+//--------------------------------------------------------------------
+// invalidates the cache (next request will force update)
+void SfxStateCache::Invalidate( sal_Bool bWithMsg )
+{
+ bCtrlDirty = sal_True;
+ if ( bWithMsg )
+ {
+ bSlotDirty = sal_True;
+ aSlotServ.SetSlot( 0 );
+ if ( pDispatch )
+ {
+ pDispatch->Release();
+ pDispatch = NULL;
+ }
+ }
+}
+
+//--------------------------------------------------------------------
+
+// gets the corresponding function from the dispatcher or the cache
+
+const SfxSlotServer* SfxStateCache::GetSlotServer( SfxDispatcher &rDispat , const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > & xProv )
+{
+ DBG_MEMTEST();
+ DBG_CHKTHIS(SfxStateCache, 0);
+
+ if ( bSlotDirty )
+ {
+ if ( xProv.is() )
+ {
+ DBG_ASSERT( !pDispatch, "Altes Dispatch nicht entfernt!" );
+
+//(mba)/compview
+ const SfxSlot* pSlot = 0;//SfxComponentViewShell::GetUnoSlot( nId );
+ ::com::sun::star::util::URL aURL;
+ String aName( pSlot ? String::CreateFromAscii(pSlot->GetUnoName()) : String() );
+ String aCmd;
+ if ( aName.Len() )
+ {
+ aCmd = DEFINE_CONST_UNICODE(".uno:");
+ aCmd += aName;
+ }
+ else
+ {
+ aCmd = DEFINE_CONST_UNICODE("slot:");
+ aCmd += String::CreateFromInt32( nId );
+ }
+
+ aURL.Complete = aCmd;
+ Reference < XURLTransformer > xTrans( ::utl::getProcessServiceFactory()->createInstance( rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer" )), UNO_QUERY );
+ xTrans->parseStrict( aURL );
+ ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > xDisp = xProv->queryDispatch( aURL, ::rtl::OUString(), 0 );
+ if ( xDisp.is() )
+ {
+ ::com::sun::star::uno::Reference< ::com::sun::star::lang::XUnoTunnel > xTunnel( xDisp, ::com::sun::star::uno::UNO_QUERY );
+ SfxOfficeDispatch* pDisp = NULL;
+ if ( xTunnel.is() )
+ {
+ sal_Int64 nImplementation = xTunnel->getSomething(SfxOfficeDispatch::impl_getStaticIdentifier());
+ pDisp = (SfxOfficeDispatch*)(nImplementation);
+ }
+
+ if ( pDisp )
+ {
+ // The intercepting object is a SFX component
+ // Get the shell that is the slotserver of this component
+ SfxDispatcher *pDispatcher = pDisp->GetDispatcher_Impl();
+ pDispatcher->_FindServer( nId, aSlotServ, sal_False );
+ SfxShell* pShell = pDispatcher->GetShell( aSlotServ.GetShellLevel() );
+
+ // Check if this shell is active on the active dispatcher
+ sal_uInt16 nLevel = rDispat.GetShellLevel( *pShell );
+ if ( nLevel != USHRT_MAX )
+ {
+ // so we can use this shell direct without StarONE connection
+ aSlotServ.SetShellLevel( nLevel );
+ bSlotDirty = sal_False;
+ bCtrlDirty = sal_True;
+
+ //MI: wozu das? bItemDirty = sal_True;
+ return aSlotServ.GetSlot()? &aSlotServ: 0;
+ }
+ else
+ {
+ pDispatch = new BindDispatch_Impl( xDisp, aURL, this );
+ pDispatch->acquire();
+
+ // flags must be set before adding StatusListener because the dispatch object will set the state
+ bSlotDirty = sal_False;
+ bCtrlDirty = sal_True;
+ xDisp->addStatusListener( pDispatch, aURL );
+ aSlotServ.SetSlot(0);
+ return NULL;
+ }
+ }
+ else
+ {
+ pDispatch = new BindDispatch_Impl( xDisp, aURL, this );
+ pDispatch->acquire();
+
+ // flags must be set before adding StatusListener because the dispatch object will set the state
+ bSlotDirty = sal_False;
+ bCtrlDirty = sal_True;
+ xDisp->addStatusListener( pDispatch, aURL );
+ aSlotServ.SetSlot(0);
+ return NULL;
+ }
+ }
+ }
+
+// if ( !rDispat._TryIntercept_Impl( nId, aSlotServ, sal_False ) )
+ rDispat._FindServer(nId, aSlotServ, sal_False);
+ bSlotDirty = sal_False;
+ bCtrlDirty = sal_True;
+ //MI: wozu das? bItemDirty = sal_True;
+ }
+
+ return aSlotServ.GetSlot()? &aSlotServ: 0;
+}
+
+
+//--------------------------------------------------------------------
+
+// Status setzen in allen Controllern
+
+void SfxStateCache::SetState
+(
+ SfxItemState eState, // <SfxItemState> von 'pState'
+ const SfxPoolItem* pState // Status des Slots, ggf. 0 oder -1
+)
+
+/* [Beschreibung]
+
+ Diese Methode verteilt die Status auf alle an dieser SID gebundenen
+ <SfxControllerItem>s. Ist der Wert derselbe wie zuvor und wurde in-
+ zwischen weder ein Controller angemeldet, noch ein Controller invalidiert,
+ dann wird kein Wert weitergeleitet. Dadurch wird z.B. Flackern in
+ ListBoxen vermieden.
+*/
+
+{
+ if ( pDispatch )
+ return;
+ SetState_Impl( eState, pState );
+}
+
+
+void SfxStateCache::SetState_Impl
+(
+ SfxItemState eState, // <SfxItemState> von 'pState'
+ const SfxPoolItem* pState // Status des Slots, ggf. 0 oder -1
+)
+{
+ DBG_MEMTEST();
+ DBG_CHKTHIS(SfxStateCache, 0);
+
+ // wenn zwischen Enter- und LeaveRegistrations ein hartes Update kommt
+ // k"onnen zwischenzeitlich auch Cached ohne Controller exisitieren
+ if ( !pController )
+ return;
+
+ DBG_ASSERT( pController->GetId()==nId, "Cache mit falschem ControllerItem" );
+ DBG_ASSERT( !bSlotDirty, "setting state of dirty message" );
+ DBG_ASSERT( bCtrlDirty ||
+ ( aSlotServ.GetSlot() && aSlotServ.GetSlot()->IsMode(SFX_SLOT_VOLATILE) ),
+ "setting state of non dirty controller" );
+ DBG_ASSERT( SfxControllerItem::GetItemState(pState) == eState,
+ "invalid SfxItemState" );
+ DBG_PROFSTART(SfxStateCacheSetState);
+
+ // m"ussen die Controller "uberhaupt benachrichtigt werden?
+ FASTBOOL bNotify = bItemDirty;
+ if ( !bItemDirty )
+ {
+ FASTBOOL bBothAvailable = pLastItem && pState &&
+ !IsInvalidItem(pState) && !IsInvalidItem(pLastItem);
+ DBG_ASSERT( !bBothAvailable || pState != pLastItem, "setting state with own item" );
+ if ( bBothAvailable )
+ bNotify = pState->Type() != pLastItem->Type() ||
+ *pState != *pLastItem;
+ else
+ bNotify = ( pState != pLastItem ) || ( eState != eLastState );
+ }
+
+ if ( bNotify )
+ {
+ // Controller updaten
+ for ( SfxControllerItem *pCtrl = pController;
+ pCtrl;
+ pCtrl = pCtrl->GetItemLink() )
+ pCtrl->StateChanged( nId, eState, pState );
+
+ // neuen Wert merken
+ if ( !IsInvalidItem(pLastItem) )
+ DELETEZ(pLastItem);
+ if ( pState && !IsInvalidItem(pState) )
+ pLastItem = pState->Clone();
+ else
+ pLastItem = 0;
+ eLastState = eState;
+ bItemDirty = sal_False;
+ }
+
+ bCtrlDirty = sal_False;
+ DBG_PROFSTOP(SfxStateCacheSetState);
+}
+
+
+//--------------------------------------------------------------------
+
+// alten Status in allen Controllern nochmal setzen
+
+void SfxStateCache::SetCachedState()
+{
+ DBG_MEMTEST();
+ DBG_CHKTHIS(SfxStateCache, 0);
+ DBG_ASSERT( pController, "Cache ohne ControllerItem" );
+ DBG_ASSERT( pController->GetId()==nId, "Cache mit falschem ControllerItem" );
+ DBG_PROFSTART(SfxStateCacheSetState);
+
+ // nur updaten wenn cached item vorhanden und auch verarbeitbar
+ // (Wenn der State gesendet wird, mu\s sichergestellt sein, da\s ein
+ // Slotserver vorhanden ist, s. SfxControllerItem::GetCoreMetric() )
+ if ( !bItemDirty && !bSlotDirty )
+ {
+ // Controller updaten
+ for ( SfxControllerItem *pCtrl = pController;
+ pCtrl;
+ pCtrl = pCtrl->GetItemLink() )
+ pCtrl->StateChanged( nId, eLastState, pLastItem );
+
+ // Controller sind jetzt ok
+ bCtrlDirty = sal_True;
+ }
+
+ DBG_PROFSTOP(SfxStateCacheSetState);
+}
+
+
+//--------------------------------------------------------------------
+
+// FloatingWindows in allen Controls mit dieser Id zerstoeren
+
+void SfxStateCache::DeleteFloatingWindows()
+{
+ DBG_MEMTEST();
+ DBG_CHKTHIS(SfxStateCache, 0);
+
+ SfxControllerItem *pNextCtrl=0;
+ for ( SfxControllerItem *pCtrl=pController; pCtrl; pCtrl=pNextCtrl )
+ {
+ DBG_TRACE((ByteString("pCtrl: ").Append(ByteString::CreateFromInt32((sal_uInt32)pCtrl))).GetBuffer());
+ pNextCtrl = pCtrl->GetItemLink();
+ pCtrl->DeleteFloatingWindow();
+ }
+}
+
+sal_Bool SfxStateCache::UpdateDispatch( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > & xProv )
+{
+ if ( bSlotDirty && xProv.is() )
+ {
+ DBG_ASSERT( !pDispatch, "Altes Dispatch nicht entfernt!" );
+
+//(mba)/compview
+ const SfxSlot* pSlot = 0;//SfxComponentViewShell::GetUnoSlot( nId );
+ ::com::sun::star::util::URL aURL;
+ String aName( pSlot ? String::CreateFromAscii(pSlot->GetUnoName()) : String() );
+ String aCmd;
+ if ( aName.Len() )
+ {
+ aCmd = DEFINE_CONST_UNICODE(".uno:");
+ aCmd += aName;
+ }
+ else
+ {
+ aCmd = DEFINE_CONST_UNICODE("slot:");
+ aCmd += String::CreateFromInt32( nId );
+ }
+
+ aURL.Complete = aCmd;
+ Reference < XURLTransformer > xTrans( ::utl::getProcessServiceFactory()->createInstance( rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer" )), UNO_QUERY );
+ xTrans->parseStrict( aURL );
+ ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > xDisp = xProv->queryDispatch( aURL, ::rtl::OUString(), 0 );
+ if ( xDisp.is() )
+ {
+ ::com::sun::star::uno::Reference< ::com::sun::star::lang::XUnoTunnel > xTunnel( xDisp, ::com::sun::star::uno::UNO_QUERY );
+ SfxOfficeDispatch* pDisp = NULL;
+ if ( xTunnel.is() )
+ {
+ sal_Int64 nImplementation = xTunnel->getSomething(SfxOfficeDispatch::impl_getStaticIdentifier());
+ pDisp = (SfxOfficeDispatch*)(nImplementation);
+ }
+
+ if ( pDisp && !pDisp->IsInterceptDispatch() )
+ return sal_False;
+ pDispatch = new BindDispatch_Impl( xDisp, aURL, this );
+ pDispatch->acquire();
+ bSlotDirty = sal_False;
+ bCtrlDirty = sal_True;
+ xDisp->addStatusListener( pDispatch, aURL );
+ aSlotServ.SetSlot(0);
+ }
+ }
+
+ return ( pDispatch != NULL );
+}
+
+::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > SfxStateCache::GetDispatch() const
+{
+ if ( pDispatch )
+ return pDispatch->xDisp;
+ return ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > ();
+}
+
+void SfxStateCache::Dispatch( sal_Bool bForceSynchron )
+{
+ if ( pDispatch )
+ pDispatch->Dispatch( bForceSynchron );
+}
+
+
diff --git a/sfx2/source/control/unoctitm.cxx b/sfx2/source/control/unoctitm.cxx
new file mode 100644
index 000000000000..ff821be8732f
--- /dev/null
+++ b/sfx2/source/control/unoctitm.cxx
@@ -0,0 +1,560 @@
+/*************************************************************************
+ *
+ * $RCSfile: unoctitm.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 16:52:29 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <tools/debug.hxx>
+
+#ifndef _SFXENUMITEM_HXX //autogen
+#include <svtools/eitem.hxx>
+#endif
+#ifndef _SFXSTRITEM_HXX //autogen
+#include <svtools/stritem.hxx>
+#endif
+#include <svtools/intitem.hxx>
+#include <svtools/itemset.hxx>
+
+#ifndef _COM_SUN_STAR_UTIL_XURLTRANSFORMER_HPP_
+#include <com/sun/star/util/XURLTransformer.hpp>
+#endif
+#ifndef _COM_SUN_STAR_FRAME_XCONTROLLER_HPP_
+#include <com/sun/star/frame/XController.hpp>
+#endif
+#ifndef _COM_SUN_STAR_FRAME_XFRAMEACTIONLISTENER_HPP_
+#include <com/sun/star/frame/XFrameActionListener.hpp>
+#endif
+#ifndef _COM_SUN_STAR_FRAME_XCOMPONENTLOADER_HPP_
+#include <com/sun/star/frame/XComponentLoader.hpp>
+#endif
+#ifndef _COM_SUN_STAR_FRAME_XFRAME_HPP_
+#include <com/sun/star/frame/XFrame.hpp>
+#endif
+#ifndef _COM_SUN_STAR_FRAME_FRAMEACTIONEVENT_HPP_
+#include <com/sun/star/frame/FrameActionEvent.hpp>
+#endif
+#ifndef _COM_SUN_STAR_FRAME_FRAMEACTION_HPP_
+#include <com/sun/star/frame/FrameAction.hpp>
+#endif
+#include <unotools/processfactory.hxx>
+
+#include "unoctitm.hxx"
+#include "viewfrm.hxx"
+#include "frame.hxx"
+#include "ctrlitem.hxx"
+#include "sfxuno.hxx"
+#include "bindings.hxx"
+#include "dispatch.hxx"
+#include "sfxsids.hrc"
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::util;
+//long nOfficeDispatchCount = 0;
+
+SFX_IMPL_XINTERFACE_2( SfxUnoControllerItem, OWeakObject, ::com::sun::star::frame::XStatusListener, ::com::sun::star::lang::XEventListener )
+SFX_IMPL_XTYPEPROVIDER_2( SfxUnoControllerItem, ::com::sun::star::frame::XStatusListener, ::com::sun::star::lang::XEventListener )
+
+SfxUnoControllerItem::SfxUnoControllerItem( SfxControllerItem *pItem, SfxBindings& rBind, const String& rCmd )
+ : pCtrlItem( pItem )
+ , pBindings( &rBind )
+{
+ DBG_ASSERT( !pCtrlItem || !pCtrlItem->IsBound(), "ControllerItem fehlerhaft!" );
+
+ aCommand.Complete = rCmd;
+ Reference < XURLTransformer > xTrans( ::utl::getProcessServiceFactory()->createInstance( rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer" )), UNO_QUERY );
+ xTrans->parseStrict( aCommand );
+ pBindings->RegisterUnoController_Impl( this );
+}
+
+SfxUnoControllerItem::~SfxUnoControllerItem()
+{
+ // tell bindings to forget this controller ( if still connected )
+ if ( pBindings )
+ pBindings->ReleaseUnoController_Impl( this );
+}
+
+void SfxUnoControllerItem::UnBind()
+{
+ // connection to SfxControllerItem is lost
+ pCtrlItem = NULL;
+ ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > aRef( (::cppu::OWeakObject*)this, ::com::sun::star::uno::UNO_QUERY );
+ ReleaseDispatch();
+}
+
+void SAL_CALL SfxUnoControllerItem::statusChanged(const ::com::sun::star::frame::FeatureStateEvent& rEvent) throw ( ::com::sun::star::uno::RuntimeException )
+{
+ DBG_ASSERT( pCtrlItem, "Dispatch hat den StatusListener nicht entfern!" );
+
+ if ( rEvent.Requery )
+ {
+ // Fehler kann nur passieren, wenn das alte Dispatch fehlerhaft implementiert
+ // ist, also removeStatusListener nicht gefunzt hat. Aber sowas soll
+ // ja vorkommen ...
+ // Also besser vor ReleaseDispatch gegen Abflug sch"utzen!
+ ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > aRef( (::cppu::OWeakObject*)this, ::com::sun::star::uno::UNO_QUERY );
+ ReleaseDispatch();
+ if ( pCtrlItem )
+ GetNewDispatch(); // asynchron ??
+ }
+ else if ( pCtrlItem )
+ {
+ // pass new status to the SfxControllerItem
+ SfxItemState eState = SFX_ITEM_DISABLED;
+ SfxPoolItem* pItem = NULL;
+ if ( rEvent.IsEnabled )
+ {
+ eState = SFX_ITEM_AVAILABLE;
+ ::com::sun::star::uno::Type pType = rEvent.State.getValueType();
+
+ if ( pType == ::getBooleanCppuType() )
+ {
+ sal_Bool bTemp ;
+ rEvent.State >>= bTemp ;
+ pItem = new SfxBoolItem( pCtrlItem->GetId(), bTemp );
+ }
+ else if ( pType == ::getCppuType((const sal_uInt16*)0) )
+ {
+ sal_uInt16 nTemp ;
+ rEvent.State >>= nTemp ;
+ pItem = new SfxUInt16Item( pCtrlItem->GetId(), nTemp );
+ }
+ else if ( pType == ::getCppuType((const sal_uInt32*)0) )
+ {
+ sal_uInt32 nTemp ;
+ rEvent.State >>= nTemp ;
+ pItem = new SfxUInt32Item( pCtrlItem->GetId(), nTemp );
+ }
+ else if ( pType == ::getCppuType((const ::rtl::OUString*)0) )
+ {
+ ::rtl::OUString sTemp ;
+ rEvent.State >>= sTemp ;
+ pItem = new SfxStringItem( pCtrlItem->GetId(), sTemp );
+ }
+ else
+ pItem = new SfxVoidItem( pCtrlItem->GetId() );
+ }
+
+ pCtrlItem->StateChanged( pCtrlItem->GetId(), eState, pItem );
+ delete pItem;
+ }
+}
+
+void SAL_CALL SfxUnoControllerItem::disposing( const ::com::sun::star::lang::EventObject& rEvent ) throw ( ::com::sun::star::uno::RuntimeException )
+{
+ ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > aRef( (::cppu::OWeakObject*)this, ::com::sun::star::uno::UNO_QUERY );
+ ReleaseDispatch();
+}
+
+void SfxUnoControllerItem::ReleaseDispatch()
+{
+ if ( xDispatch.is() )
+ {
+ xDispatch->removeStatusListener( (::com::sun::star::frame::XStatusListener*) this, aCommand );
+ xDispatch = ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > ();
+ }
+}
+
+void SfxUnoControllerItem::GetNewDispatch()
+{
+ if ( !pBindings )
+ {
+ // Bindings released
+ DBG_ERROR( "Tried to get dispatch, but no Bindings!" );
+ return;
+ }
+
+ // forget old dispatch
+ xDispatch = ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > ();
+
+ // no arms, no cookies !
+ if ( !pBindings->GetDispatcher_Impl() || !pBindings->GetDispatcher_Impl()->GetFrame() )
+ return;
+
+ SfxFrame *pFrame = pBindings->GetDispatcher_Impl()->GetFrame()->GetFrame();
+ SfxFrame *pParent = pFrame->GetParentFrame();
+ if ( pParent )
+ // parent may intercept
+ xDispatch = TryGetDispatch( pParent );
+
+ if ( !xDispatch.is() )
+ {
+ // no interception
+ ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xFrame = pFrame->GetFrameInterface();
+ ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > xProv( xFrame, ::com::sun::star::uno::UNO_QUERY );
+ if ( xProv.is() )
+ xDispatch = xProv->queryDispatch( aCommand, ::rtl::OUString(), 0 );
+ }
+
+ if ( xDispatch.is() )
+ xDispatch->addStatusListener( (::com::sun::star::frame::XStatusListener*) this, aCommand );
+ else if ( pCtrlItem )
+ pCtrlItem->StateChanged( pCtrlItem->GetId(), SFX_ITEM_DISABLED, NULL );
+}
+
+::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > SfxUnoControllerItem::TryGetDispatch( SfxFrame *pFrame )
+{
+ ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatch > xDisp;
+ SfxFrame *pParent = pFrame->GetParentFrame();
+ if ( pParent )
+ // parent may intercept
+ xDisp = TryGetDispatch( pParent );
+
+ // only components may intercept
+ if ( !xDisp.is() && pFrame->HasComponent() )
+ {
+ // no interception
+ ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xFrame = pFrame->GetFrameInterface();
+ ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > xProv( xFrame, ::com::sun::star::uno::UNO_QUERY );
+ if ( xProv.is() )
+ xDisp = xProv->queryDispatch( aCommand, ::rtl::OUString(), 0 );
+ }
+
+ return xDisp;
+}
+
+void SfxUnoControllerItem::Execute()
+{
+ // dispatch the resource
+ if ( xDispatch.is() )
+ xDispatch->dispatch( aCommand, ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >() );
+}
+
+void SfxUnoControllerItem::ReleaseBindings()
+{
+ // connection to binding is lost; so forget the binding and the dispatch
+ ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > aRef( (::cppu::OWeakObject*)this, ::com::sun::star::uno::UNO_QUERY );
+ ReleaseDispatch();
+ if ( pBindings )
+ pBindings->ReleaseUnoController_Impl( this );
+ pBindings = NULL;
+}
+
+void SfxStatusDispatcher::ReleaseAll()
+{
+ ::com::sun::star::lang::EventObject aObject;
+ aObject.Source = (::cppu::OWeakObject*) this;
+ aListeners.disposeAndClear( aObject );
+}
+
+void SAL_CALL SfxStatusDispatcher::dispatch( const ::com::sun::star::util::URL&, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& ) throw ( ::com::sun::star::uno::RuntimeException )
+{
+}
+
+SFX_IMPL_XINTERFACE_1( SfxStatusDispatcher, OWeakObject, ::com::sun::star::frame::XDispatch )
+SFX_IMPL_XTYPEPROVIDER_1( SfxStatusDispatcher, ::com::sun::star::frame::XDispatch )
+//IMPLNAME "com.sun.star.comp.sfx2.StatusDispatcher",
+
+SfxStatusDispatcher::SfxStatusDispatcher()
+ : aListeners( aMutex )
+{
+}
+
+void SAL_CALL SfxStatusDispatcher::addStatusListener(const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > & aListener, const ::com::sun::star::util::URL& aURL) throw ( ::com::sun::star::uno::RuntimeException )
+{
+ aListeners.addInterface( aURL.Complete, aListener );
+ if ( aURL.Complete.compareToAscii(".uno:LifeTime")==0 )
+ {
+ ::com::sun::star::frame::FeatureStateEvent aEvent;
+ aEvent.FeatureURL = aURL;
+ aEvent.Source = (::com::sun::star::frame::XDispatch*) this;
+ aEvent.IsEnabled = sal_True;
+ aEvent.Requery = sal_False;
+ aListener->statusChanged( aEvent );
+ }
+}
+
+void SAL_CALL SfxStatusDispatcher::removeStatusListener( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > & aListener, const ::com::sun::star::util::URL& aURL ) throw ( ::com::sun::star::uno::RuntimeException )
+{
+ aListeners.removeInterface( aURL.Complete, aListener );
+}
+
+SFX_IMPL_XINTERFACE_1( SfxOfficeDispatch, SfxStatusDispatcher, ::com::sun::star::lang::XUnoTunnel )
+SFX_IMPL_XTYPEPROVIDER_2( SfxOfficeDispatch, ::com::sun::star::frame::XDispatch, ::com::sun::star::lang::XUnoTunnel )
+
+
+//-------------------------------------------------------------------------
+// XUnoTunnel
+sal_Int64 SAL_CALL SfxOfficeDispatch::getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier ) throw(::com::sun::star::uno::RuntimeException)
+{
+ if ( aIdentifier == impl_getStaticIdentifier() )
+ return (sal_Int64)this;
+ else
+ return 0;
+}
+
+/* ASDBG
+void* SfxOfficeDispatch::getImplementation(Reflection *p)
+{
+ if( p == ::getCppuType((const SfxOfficeDispatch*)0) )
+ return this;
+ else
+ return ::cppu::OWeakObject::getImplementation(p);
+
+}
+
+Reflection* ::getCppuType((const SfxOfficeDispatch*)0)
+{
+ static StandardClassReflection aRefl(
+ 0,
+ createStandardClass(
+ "SfxOfficeDispatch", ::cppu::OWeakObject::get::cppu::OWeakObjectIdlClass(),
+ 1,
+ ::getCppuType((const ::com::sun::star::frame::XDispatch*)0) ) );
+ return &aRefl;
+}
+*/
+
+SfxOfficeDispatch::SfxOfficeDispatch( SfxBindings& rBindings, SfxDispatcher* pDispat, sal_uInt16 nSlotId, const ::com::sun::star::util::URL& rURL, sal_Bool bInter )
+ : bIntercept( bInter )
+{
+// nOfficeDispatchCount++;
+
+ // this object is an adapter that shows a ::com::sun::star::frame::XDispatch-Interface to the outside and uses a SfxControllerItem to monitor a state
+ pControllerItem = new SfxDispatchController_Impl( this, rBindings, pDispat, nSlotId, rURL, bInter );
+}
+
+SfxOfficeDispatch::~SfxOfficeDispatch()
+{
+// --nOfficeDispatchCount;
+
+ if ( pControllerItem )
+ {
+ // when dispatch object is released, destroy its connection to this object and destroy it
+ pControllerItem->UnBindController();
+ delete pControllerItem;
+ }
+}
+
+void SAL_CALL SfxOfficeDispatch::dispatch( const ::com::sun::star::util::URL& aURL, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aArgs ) throw ( ::com::sun::star::uno::RuntimeException )
+{
+ // ControllerItem is the Impl class
+ if ( pControllerItem )
+ pControllerItem->dispatch( aURL, aArgs );
+}
+
+void SAL_CALL SfxOfficeDispatch::addStatusListener(const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > & aListener, const ::com::sun::star::util::URL& aURL) throw ( ::com::sun::star::uno::RuntimeException )
+{
+ GetListeners().addInterface( aURL.Complete, aListener );
+ if ( pControllerItem )
+ {
+ // ControllerItem is the Impl class
+ pControllerItem->addStatusListener( aListener, aURL );
+ }
+}
+
+SfxDispatcher* SfxOfficeDispatch::GetDispatcher_Impl()
+{
+ return pControllerItem->GetDispatcher();
+}
+
+SfxDispatchController_Impl::SfxDispatchController_Impl( SfxOfficeDispatch* pDisp, SfxBindings& rBindings, SfxDispatcher* pDispat, sal_uInt16 nSlotId, const ::com::sun::star::util::URL& rURL, sal_Bool bInter )
+ : pDispatch( pDisp )
+ , aDispatchURL( rURL )
+ , pBindings( &rBindings )
+ , pDispatcher( pDispat )
+ , pLastState( 0 )
+ , nSlot( nSlotId )
+{
+}
+
+SfxDispatchController_Impl::~SfxDispatchController_Impl()
+{
+ if ( pLastState && !IsInvalidItem( pLastState ) )
+ delete pLastState;
+
+ if ( pDispatch )
+ {
+ // disconnect
+ pDispatch->pControllerItem = NULL;
+
+ // force all listeners to release the dispatch object
+ ::com::sun::star::lang::EventObject aObject;
+ aObject.Source = (::cppu::OWeakObject*) pDispatch;
+ pDispatch->GetListeners().disposeAndClear( aObject );
+ }
+}
+
+void SfxDispatchController_Impl::UnBindController()
+{
+ pDispatch = NULL;
+ if ( IsBound() )
+ {
+ GetBindings().ENTERREGISTRATIONS();
+ SfxControllerItem::UnBind();
+ GetBindings().LEAVEREGISTRATIONS();
+ }
+}
+
+void SAL_CALL SfxDispatchController_Impl::dispatch( const ::com::sun::star::util::URL& aURL, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aArgs ) throw ( ::com::sun::star::uno::RuntimeException )
+{
+ if ( pDispatch && aURL == aDispatchURL )
+ {
+ if ( !GetId() )
+ {
+ pBindings->ENTERREGISTRATIONS();
+ Bind( nSlot, pBindings );
+ pBindings->LEAVEREGISTRATIONS();
+ }
+
+ SfxAllItemSet aSet( SFX_APP()->GetPool() );
+ TransformParameters( GetId(), aArgs, aSet );
+ aSet.Put( SfxBoolItem( SID_INTERCEPTOR, sal_False ) );
+ if ( !pDispatcher )
+ pDispatcher = GetBindings().GetDispatcher_Impl();
+
+ SfxCallMode nCall = SFX_CALLMODE_SLOT;
+ sal_uInt16 nCount = aArgs.getLength();
+ const ::com::sun::star::beans::PropertyValue* pPropsVal = aArgs.getConstArray();
+ for ( sal_uInt16 n=0; n<nCount; n++ )
+ {
+ const ::com::sun::star::beans::PropertyValue& rProp = pPropsVal[n];
+ String aName = rProp.Name;
+ sal_Bool bTemp ;
+ if ( aName.EqualsAscii("SynchronMode") && (rProp.Value >>= bTemp) )
+ {
+ nCall = SFX_CALLMODE_SYNCHRON;
+ break;
+ }
+ }
+ pDispatcher->Execute( GetId(), nCall, aSet );
+ }
+}
+
+SfxDispatcher* SfxDispatchController_Impl::GetDispatcher()
+{
+ if ( !pDispatcher )
+ pDispatcher = GetBindings().GetDispatcher_Impl();
+ return pDispatcher;
+}
+
+void SAL_CALL SfxDispatchController_Impl::addStatusListener(const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XStatusListener > & aListener, const ::com::sun::star::util::URL& aURL) throw ( ::com::sun::star::uno::RuntimeException )
+{
+ if ( !pDispatch )
+ return;
+
+ if ( !GetId() )
+ {
+ pBindings->ENTERREGISTRATIONS();
+ Bind( nSlot, pBindings );
+ pBindings->LEAVEREGISTRATIONS();
+ }
+
+ const SfxPoolItem *pItem = 0;
+ if ( !pDispatcher )
+ pDispatcher = GetBindings().GetDispatcher_Impl();
+ SfxItemState eState = pDispatcher->QueryState( GetId(), pItem );
+ ::com::sun::star::uno::Any aState;
+ if ( pItem )
+ pItem->QueryValue( aState );
+
+ ::com::sun::star::frame::FeatureStateEvent aEvent;
+ aEvent.FeatureURL = aURL;
+ aEvent.Source = (::com::sun::star::frame::XDispatch*) pDispatch;
+ aEvent.IsEnabled = eState != SFX_ITEM_DISABLED;
+ aEvent.Requery = sal_False;
+ aEvent.State = aState;
+
+ aListener->statusChanged( aEvent );
+}
+
+void SfxDispatchController_Impl::StateChanged( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState )
+{
+ if ( !pDispatch )
+ return;
+
+ if ( pDispatch->IsInterceptDispatch() )
+ {
+ // If this Controller is made for an interception, the state can't be set from outside
+ // because this would be the state of the interceptor itself!
+ if ( !pDispatcher )
+ pDispatcher = GetBindings().GetDispatcher_Impl();
+ eState = pDispatcher->QueryState( GetId(), pState );
+ }
+
+ // Bindings instance notifies controller about a state change, listeners must be notified also
+ sal_Bool bNotify = sal_True;
+ sal_Bool bBothAvailable = pLastState && pState && !IsInvalidItem(pLastState) && !IsInvalidItem(pState);
+ if ( bBothAvailable )
+ bNotify = pState->Type() != pLastState->Type() || *pState != *pLastState;
+ else
+ bNotify = ( pLastState != pState );
+ if ( pLastState && !IsInvalidItem( pLastState ) )
+ delete pLastState;
+ pLastState = ( pState && !IsInvalidItem(pState) ) ? pState->Clone() : pState;
+
+ ::cppu::OInterfaceContainerHelper* pContnr = pDispatch->GetListeners().getContainer ( aDispatchURL.Complete );
+ if ( bNotify && pContnr )
+ {
+ ::com::sun::star::uno::Any aState;
+ if ( pState )
+ pState->QueryValue( aState );
+
+ ::com::sun::star::frame::FeatureStateEvent aEvent;
+ aEvent.FeatureURL = aDispatchURL;
+ aEvent.Source = (::com::sun::star::frame::XDispatch*) pDispatch;
+ aEvent.IsEnabled = eState != SFX_ITEM_DISABLED;
+ aEvent.Requery = sal_False;
+ aEvent.State = aState;
+
+ ::cppu::OInterfaceIteratorHelper aIt( *pContnr );
+ while( aIt.hasMoreElements() )
+ ((::com::sun::star::frame::XStatusListener *)aIt.next())->statusChanged( aEvent );
+ }
+}
+
+