/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: sfx2_bindings.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: rt $ $Date: 2006/10/27 19:08:39 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

#ifndef _SFXITEMPOOL_HXX //autogen
#include <svtools/itempool.hxx>
#endif
#ifndef _AEITEM_HXX //autogen
#include <svtools/aeitem.hxx>
#endif

#include <svtools/itemdel.hxx>

#pragma hdrstop

#include "interno.hxx"

#ifndef _COM_SUN_STAR_LANG_XTYPEPROVIDER_HPP_
#include <com/sun/star/lang/XTypeProvider.hpp>
#endif

#include "statcach.hxx"
#include "appdata.hxx"
#include "dispatch.hxx"
#include "request.hxx"
#include "workwin.hxx"
#include "macrconf.hxx"
#include "unoctitm.hxx"
#include "sfx.hrc"
#include "topfrm.hxx"
#include "cfgmgr.hxx"

namespace binfilter {

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::util;

/*N*/ DBG_NAME(SfxBindingsMsgPos)
/*N*/ DBG_NAME(SfxBindingsUpdateServers)
/*N*/ DBG_NAME(SfxBindingsCreateSet)
/*N*/ DBG_NAME(SfxBindingsUpdateCtrl1)
/*N*/ DBG_NAME(SfxBindingsUpdateCtrl2)
/*N*/ DBG_NAME(SfxBindingsNextJob_Impl0)
/*N*/ DBG_NAME(SfxBindingsNextJob_Impl)
/*N*/ DBG_NAME(SfxBindingsUpdate_Impl)
/*N*/ 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;

//====================================================================

DECL_PTRARRAY(SfxStateCacheArr_Impl, SfxStateCache*, 32, 16)//STRIP008 ;

//====================================================================



/*?*/ 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::XDispatchRecorder > xRecorder;
/*?*/ 	::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > 	xProv;
/*?*/ 	SfxUnoControllerArr_Impl*
/*?*/ 							pUnoCtrlArr;
/*?*/ 	SfxWorkWindow*			pWorkWin;
/*?*/ 	SfxBindings*			pSubBindings;
/*?*/ 	SfxBindings*			pSuperBindings;
/*?*/ 	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                    bContextChanged;
/*?*/ 	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_uInt16					nOwnRegLevel;	// z"ahlt die echten Locks, ohne die der SuperBindings
/*?*/ };

//--------------------------------------------------------------------

/*N*/ 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.
*/

/*N*/ {
/*N*/ 	sal_uInt16          nSlotId;    // die Slot-Id
/*N*/ 	sal_uInt16          nWhichId;   // falls verf"ugbar die Which-Id, sonst nSlotId
/*N*/ 	const SfxSlot*  pSlot;      // Pointer auf den <Master-Slot>
/*N*/ 	SfxStateCache*  pCache;     // Pointer auf den StatusCache, ggf. 0
/*N*/ 
/*N*/ 	SfxFoundCache_Impl():
/*N*/ 		nSlotId(0),
/*N*/ 		nWhichId(0),
/*N*/ 		pSlot(0),
/*N*/ 		pCache(0)
/*N*/ 	{}
/*N*/ 
/*N*/ 	SfxFoundCache_Impl(SfxFoundCache_Impl&r):
/*N*/ 		nSlotId(r.nSlotId),
/*N*/ 		nWhichId(r.nWhichId),
/*N*/ 		pSlot(r.pSlot),
/*N*/ 		pCache(r.pCache)
/*N*/ 	{}
/*N*/ 
/*N*/ 	SfxFoundCache_Impl(sal_uInt16 nS, sal_uInt16 nW, const SfxSlot *pS, SfxStateCache *pC ):
/*N*/ 		nSlotId(nS),
/*N*/ 		nWhichId(nW),
/*N*/ 		pSlot(pS),
/*N*/ 		pCache(pC)
/*N*/ 	{}
/*N*/ 
/*N*/ 	int operator<( const SfxFoundCache_Impl &r ) const
/*N*/ 	{ return nWhichId < r.nWhichId; } const
/*N*/ 
/*N*/ 	int operator==( const SfxFoundCache_Impl &r )
/*N*/ 	{ return nWhichId== r.nWhichId; }
/*N*/ };

//--------------------------------------------------------------------------

/*N*/ SV_DECL_PTRARR_SORT_DEL(SfxFoundCacheArr_Impl, SfxFoundCache_Impl*, 16, 16 )//STRIP008 ;
/*N*/ SV_IMPL_OP_PTRARR_SORT(SfxFoundCacheArr_Impl, SfxFoundCache_Impl*);

//==========================================================================

/*N*/ 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.
*/

/*N*/ :   pImp(new SfxBindings_Impl),
/*N*/ 	pDispatcher(0),
/*N*/ 	nRegLevel(1)    // geht erst auf 0, wenn Dispatcher gesetzt
/*N*/ {
/*N*/ 	pImp->nMsgPos = 0;
/*N*/ 	pImp->bAllMsgDirty = sal_True;
/*N*/ 	pImp->bContextChanged = sal_False;
/*N*/ 	pImp->bMsgDirty = sal_True;
/*N*/ 	pImp->bAllDirty = sal_True;
/*N*/ 	pImp->ePopupAction = SFX_POPUP_DELETE;
/*N*/ 	pImp->nCachedFunc1 = 0;
/*N*/ 	pImp->nCachedFunc2 = 0;
/*N*/ 	pImp->bCtrlReleased = sal_False;
/*N*/ 	pImp->bFirstRound = sal_False;
/*N*/ 	pImp->bInNextJob = sal_False;
/*N*/ 	pImp->bInUpdate = sal_False;
/*N*/ 	pImp->pSubBindings = NULL;
/*N*/ 	pImp->pSuperBindings = NULL;
/*N*/ 	pImp->pWorkWin = NULL;
/*N*/ 	pImp->pUnoCtrlArr = NULL;
/*N*/ 	pImp->nOwnRegLevel = nRegLevel;
/*N*/ 
/*N*/ 	// all caches are valid (no pending invalidate-job)
/*N*/ 	// create the list of caches
/*N*/ 	pImp->pCaches = new SfxStateCacheArr_Impl;
/*N*/ 	pImp->aTimer.SetTimeoutHdl( LINK(this, SfxBindings, NextJob_Impl) );
/*N*/ }

//====================================================================

/*N*/ 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.
*/

/*N*/ {
/*N*/ 	// Die SubBindings sollen ja nicht gelocked werden !
/*N*/ 	pImp->pSubBindings = NULL;
/*N*/ 
/*N*/ 	ENTERREGISTRATIONS();
/*N*/ 
/*N*/ 	pImp->aTimer.Stop();
/*N*/ 	DeleteControllers_Impl();
/*N*/ 
/*N*/ 	// Caches selbst l"oschen
/*N*/ 	sal_uInt16 nCount = pImp->pCaches->Count();
/*N*/ 	for ( sal_uInt16 nCache = 0; nCache < nCount; ++nCache )
/*?*/ 		delete pImp->pCaches->GetObject(nCache);
/*N*/ 
/*N*/     DELETEZ( pImp->pWorkWin );
/*N*/ 
/*N*/ 	delete pImp->pCaches;
/*N*/ 	delete pImp;
/*N*/ }

//--------------------------------------------------------------------

/*N*/ 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.
*/

/*N*/ {
/*N*/ 	// in der ersten Runde den SfxPopupWindows l"oschen
/*N*/ 	sal_uInt16 nCount = pImp->pCaches->Count();
/*N*/ 	sal_uInt16 nCache;
/*N*/ 	for ( nCache = 0; nCache < nCount; ++nCache )
/*N*/ 	{
/*N*/ 		// merken wo man ist
/*N*/ 		SfxStateCache *pCache = pImp->pCaches->GetObject(nCache);
/*N*/ 		sal_uInt16 nSlotId = pCache->GetId();
/*N*/ 
/*N*/ 		// SfxPopupWindow l"oschen lassen
/*N*/ 		pCache->DeleteFloatingWindows();
/*N*/ 
/*N*/ 		// da der Cache verkleinert worden sein kann, wiederaufsetzen
/*N*/ 		sal_uInt16 nNewCount = pImp->pCaches->Count();
/*N*/ 		if ( nNewCount < nCount )
/*N*/ 		{
/*?*/ 			nCache = GetSlotPos(nSlotId);
/*?*/ 			if ( nCache >= nNewCount ||
/*?*/ 				 nSlotId != pImp->pCaches->GetObject(nCache)->GetId() )
/*?*/ 				--nCache;
/*?*/ 			nCount = nNewCount;
/*N*/ 		}
/*N*/ 	}
/*N*/ 
/*N*/ 	// alle Caches l"oschen
/*N*/ 	for ( nCache = pImp->pCaches->Count(); nCache > 0; --nCache )
/*N*/ 	{
/*N*/ 		// Cache via ::com::sun::star::sdbcx::Index besorgen
/*N*/ 		SfxStateCache *pCache = pImp->pCaches->GetObject(nCache-1);
/*N*/ 
/*N*/ 		// alle Controller in dem Cache unbinden
/*N*/ 		SfxControllerItem *pNext;
/*N*/ 		for ( SfxControllerItem *pCtrl = pCache->GetItemLink();
/*N*/ 			  pCtrl; pCtrl = pNext )
/*N*/ 		{
/*N*/ 			pNext = pCtrl->GetItemLink();
/*N*/ 			pCtrl->UnBind();
/*N*/ 		}
/*N*/ 
/*N*/ 		// Cache l"oschen
/*N*/ 		if( nCache-1 < pImp->pCaches->Count() )
/*N*/ 			delete (*pImp->pCaches)[nCache-1];
/*N*/ 		pImp->pCaches->Remove(nCache-1, 1);
/*N*/ 	}
/*N*/ 
/*N*/ 	if( pImp->pUnoCtrlArr )
/*N*/ 	{
/*?*/ 		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 );
/*N*/ 	}
/*N*/ }

//--------------------------------------------------------------------



//--------------------------------------------------------------------


/*  [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.
*/


/*N*/ void SfxBindings::HidePopupCtrls_Impl( FASTBOOL bHide )
/*N*/ {
/*N*/ 	if ( bHide )
/*N*/ 	{
/*N*/ 		// SfxPopupWindows hiden
/*N*/ 		pImp->ePopupAction = SFX_POPUP_HIDE;
/*N*/ 	}
/*N*/ 	else
/*N*/ 	{
/*N*/ 		// SfxPopupWindows showen
/*N*/ 		pImp->ePopupAction = SFX_POPUP_SHOW;
/*N*/ 	}
/*N*/ 
/*N*/ 	for ( sal_uInt16 nCache = 0; nCache < pImp->pCaches->Count(); ++nCache )
/*N*/ 		pImp->pCaches->GetObject(nCache)->DeleteFloatingWindows();
/*N*/ 	pImp->ePopupAction = SFX_POPUP_DELETE;
/*N*/ }

//--------------------------------------------------------------------

/*N*/ void SfxBindings::Update_Impl
/*N*/ (
/*N*/ 	SfxStateCache*  pCache      // der upzudatende SfxStatusCache
/*N*/ )

/*  [Beschreibung]

	Interne Methode zum Updaten eines Caches und den von derselben
	Status-Methode in derselben Shell bedienten und dirty Slots.
*/

/*N*/ {
/*N*/     if( pCache->GetDispatch().is() && pCache->GetItemLink() )
/*N*/     {
/*?*/         pCache->SetCachedState(TRUE);
/*?*/         return;
/*N*/     }
/*N*/ 
/*N*/ 	if ( !pDispatcher )
/*N*/ 		return;
/*N*/ 	DBG_PROFSTART(SfxBindingsUpdate_Impl);
/*N*/ 
/*N*/ 	// alle mit derselben Statusmethode zusammensammeln, die dirty sind
/*N*/ 	SfxDispatcher &rDispat = *pDispatcher;
/*N*/ 	const SfxSlot *pRealSlot = 0;
/*N*/ 	const SfxSlotServer* pMsgServer = 0;
/*N*/ 	SfxFoundCacheArr_Impl aFound;
/*N*/ 	SfxItemSet *pSet = CreateSet_Impl( pCache, pRealSlot, &pMsgServer, aFound );
/*N*/ 	sal_Bool bUpdated = sal_False;
/*N*/ 	if ( pSet )
/*N*/ 	{
/*N*/ 		// Status erfragen
/*N*/ 		if ( rDispat._FillState( *pMsgServer, *pSet, pRealSlot ) )
/*N*/ 		{
/*N*/ 			// Status posten
/*N*/ 			const SfxInterface *pInterface =
/*N*/ 				rDispat.GetShell(pMsgServer->GetShellLevel())->GetInterface();
/*N*/ 			for ( sal_uInt16 nPos = 0; nPos < aFound.Count(); ++nPos )
/*N*/ 			{
/*N*/ 				const SfxFoundCache_Impl *pFound = aFound[nPos];
/*N*/ 				sal_uInt16 nWhich = pFound->nWhichId;
/*N*/ 				const SfxPoolItem *pItem = 0;
/*N*/ 				SfxItemState eState = pSet->GetItemState(nWhich, sal_True, &pItem);
/*N*/ 				if ( eState == SFX_ITEM_DEFAULT && SfxItemPool::IsWhich(nWhich) )
/*N*/ 					pItem = &pSet->Get(nWhich);
/*N*/ 				UpdateControllers_Impl( pInterface, aFound[nPos], pItem, eState );
/*N*/ 			}
/*N*/ 			bUpdated = sal_True;
/*N*/ 		}
/*N*/ 
/*N*/ 		delete pSet;
/*N*/ 	}
/*N*/ 
/*N*/ 	if ( !bUpdated && pCache )
/*N*/ 	{
/*N*/ 		// Wenn pCache == NULL und kein SlotServer ( z.B. weil Dispatcher gelockt! ),
/*N*/ 		// darf nat"urlich kein Update versucht werden
/*N*/ 		SfxFoundCache_Impl aFound( pCache->GetId(), 0,
/*N*/ 								   pRealSlot, pCache );
/*N*/ 		UpdateControllers_Impl( 0, &aFound, 0, SFX_ITEM_DISABLED);
/*N*/ 	}
/*N*/ 
/*N*/ 	DBG_PROFSTOP(SfxBindingsUpdate_Impl);
/*N*/ }

//--------------------------------------------------------------------

/*N*/ void SfxBindings::Update
/*N*/ (
/*N*/ 	sal_uInt16      nId     // die gebundene und upzudatende Slot-Id
/*N*/ )

/*  [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()>
*/

/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
/*N*/ 
/*N*/ //!!TLX: Fuehrte zu Vorlagenkatalogstillstand
/*N*/ //	if ( nRegLevel )
/*N*/ //  	return;
/*N*/ 
/*N*/ 	if ( pDispatcher )
/*N*/ 		pDispatcher->Flush();
/*N*/ 
/*N*/ 	if ( pImp->pSubBindings )
/*?*/ 		pImp->pSubBindings->Update( nId );
/*N*/ 
/*N*/ 	SfxStateCache* pCache = GetStateCache( nId );
/*N*/     if ( pCache )
/*N*/ 	{
/*N*/ 		pImp->bInUpdate = sal_True;
/*N*/ 		if ( pImp->bMsgDirty )
/*N*/ 		{
/*N*/ 			UpdateSlotServer_Impl();
/*N*/ 			pCache = GetStateCache( nId );
/*N*/ 		}
/*N*/ 
/*N*/ 		if (pCache)
/*N*/ 		{
/*N*/             if( pCache->GetDispatch().is() && pCache->GetItemLink() )
/*N*/             {
/*?*/                 pCache->SetCachedState(TRUE);
/*N*/             }
/*N*/             else
/*N*/             {
/*N*/                 // Status erfragen
/*N*/                 const SfxSlotServer* pMsgServer = pCache->GetSlotServer(*pDispatcher, pImp->xProv);
/*N*/                 if ( !pCache->IsControllerDirty() &&
/*N*/                     ( !pMsgServer ||
/*N*/                     !pMsgServer->GetSlot()->IsMode(SFX_SLOT_VOLATILE) ) )
/*N*/                 {
/*N*/                     pImp->bInUpdate = sal_False;
/*N*/                     return;
/*N*/                 }
/*N*/                 if (!pMsgServer)
/*N*/                 {
/*N*/                     pCache->SetState(SFX_ITEM_DISABLED, 0);
/*N*/                     pImp->bInUpdate = sal_False;
/*N*/                     return;
/*N*/                 }
/*N*/ 
/*N*/                 Update_Impl(pCache);
/*N*/             }
/*N*/ 
/*N*/ 			pImp->bAllDirty = sal_False;
/*N*/ 		}
/*N*/ 
/*N*/ 		pImp->bInUpdate = sal_False;
/*N*/ 	}
/*N*/ }

//--------------------------------------------------------------------

/*?*/ 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_BF_ASSERT(0, "STRIP"); //STRIP001 
/*N*/ }

//--------------------------------------------------------------------

/*?*/ 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&)>
*/

/*N*/ {DBG_BF_ASSERT(0, "STRIP"); //STRIP001 
	// wenn gelockt, dann nur invalidieren
/*N*/ }

//--------------------------------------------------------------------

/*N*/ void SfxBindings::SetState
/*N*/ (
/*N*/ 	const SfxPoolItem&  rItem   // zu setzender Status-Wert
/*N*/ )

/*  [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&)>
*/

/*N*/ {
/*N*/ 	if ( nRegLevel )
/*N*/ 	{
/*N*/ 		Invalidate( rItem.Which() );
/*N*/ 	}
/*N*/ 	else
/*N*/ 	{
/*N*/ 		// Status d"urfen nur angenommen werden, wenn alle Slot-Pointer gesetzt sind
/*N*/ 		if ( pImp->bMsgDirty )
/*N*/ 			UpdateSlotServer_Impl();
/*N*/ 
/*N*/ 		// falls der Slot gebunden ist, updaten
/*N*/ 		DBG_ASSERT( SfxItemPool::IsSlot( rItem.Which() ),
/*N*/ 					"cannot set items with which-id" );
/*N*/ 		SfxStateCache* pCache = GetStateCache( rItem.Which() );
/*N*/ 		if ( pCache )
/*N*/ 		{
/*N*/ 			// Status updaten
/*N*/ 			if ( !pCache->IsControllerDirty() )
/*N*/ 				pCache->Invalidate(sal_False);
/*N*/ 			pCache->SetState( SFX_ITEM_AVAILABLE, &rItem );
/*N*/ 
/*N*/ 			//! nicht implementiert: Updates von EnumSlots via MasterSlots
/*N*/ 		}
/*N*/ 	}
/*N*/ }


//--------------------------------------------------------------------

/*?*/ SfxStateCache* SfxBindings::GetAnyStateCache_Impl( sal_uInt16 nId )
/*?*/ {
/*?*/ 	SfxStateCache* pCache = GetStateCache( nId );
/*?*/ 	if ( !pCache && pImp->pSubBindings )
/*?*/ 		return pImp->pSubBindings->GetAnyStateCache_Impl( nId );
/*?*/ 	return pCache;
/*?*/ }

/*N*/ SfxStateCache* SfxBindings::GetStateCache
/*N*/ (
/*N*/ 	sal_uInt16      nId         /*  Slot-Id, deren SfxStatusCache gefunden
								werden soll */,
/*N*/ 	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. */
/*N*/ )

/*  [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.
*/

/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
/*N*/ 	// is the specified function bound?
/*N*/ 	const sal_uInt16 nStart = ( pPos ? *pPos : 0 );
/*N*/ 	const sal_uInt16 nPos = GetSlotPos( nId, nStart );
/*N*/ 
/*N*/ 	if ( nPos < pImp->pCaches->Count() &&
/*N*/ 		 (*pImp->pCaches)[nPos]->GetId() == nId )
/*N*/ 	{
/*N*/ 		if ( pPos )
/*N*/ 			*pPos = nPos;
/*N*/ 		return (*pImp->pCaches)[nPos];
/*N*/ 	}
/*N*/ 	return 0;
/*N*/ }

//--------------------------------------------------------------------

/*N*/ void SfxBindings::InvalidateAll
/*N*/ (
/*N*/ 	sal_Bool    bWithMsg        /*  sal_True
								Slot-Server als ung"ultig markieren

								sal_False
								Slot-Server bleiben g"ultig */
/*N*/ )

/*  [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)>
*/

/*N*/ {
/*N*/ 	DBG_PROFSTART(SfxBindingsInvalidateAll);
/*N*/ 	DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
/*N*/ 
/*N*/ 	DBG_MEMTEST();
/*N*/ 
/*N*/ 	if ( pImp->pSubBindings )
/*?*/ 		pImp->pSubBindings->InvalidateAll( bWithMsg );
/*N*/ 
/*N*/ 	// ist schon alles dirty gesetzt oder downing => nicht zu tun
/*N*/ 	if ( !pDispatcher ||
/*N*/ 		 ( pImp->bAllDirty && ( !bWithMsg || pImp->bAllMsgDirty ) ) ||
/*N*/ 		 SFX_APP()->IsDowning() )
/*N*/ 	{
/*N*/ 		DBG_PROFSTOP(SfxBindingsInvalidateAll);
/*N*/ 		return;
/*N*/ 	}
/*N*/ 
/*N*/ 	pImp->bAllMsgDirty = pImp->bAllMsgDirty || bWithMsg;
/*N*/ 	pImp->bMsgDirty = pImp->bMsgDirty || pImp->bAllMsgDirty || bWithMsg;
/*N*/ 	pImp->bAllDirty = sal_True;
/*N*/ 
/*N*/ 	for ( sal_uInt16 n = 0; n < pImp->pCaches->Count(); ++n )
/*N*/ 		pImp->pCaches->GetObject(n)->Invalidate(bWithMsg);
/*
    ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame > xFrame
        ( pDispatcher->GetFrame()->GetFrame()->GetFrameInterface(), UNO_QUERY );

    if ( bWithMsg && xFrame.is() )
        xFrame->contextChanged();
*/
/*N*/ 	pImp->nMsgPos = 0;
/*N*/ 	if ( !nRegLevel )
/*N*/ 	{
/*N*/ 		pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
/*N*/ 		pImp->aTimer.Start();
//		pImp->bFirstRound = sal_True;
//		pImp->nFirstShell = 0;
/*N*/ 	}
/*N*/ 
/*N*/ 	DBG_PROFSTOP(SfxBindingsInvalidateAll);
/*N*/ }

//--------------------------------------------------------------------

/*N*/ void SfxBindings::Invalidate
/*N*/ (
/*N*/ 	const sal_uInt16* pIds      /*  numerisch sortiertes 0-terminiertes Array
								von Slot-Ids (einzel, nicht als Paare!) */
/*N*/ )

/*  [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)>
*/

/*N*/ {
/*N*/ 	DBG_PROFSTART(SfxBindingsInvalidateAll);
/*N*/ 	DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
/*N*/ 
/*N*/ 	DBG_MEMTEST();
/*N*/ 
/*N*/ 	if ( pImp->pSubBindings )
/*N*/ 		pImp->pSubBindings->Invalidate( pIds );
/*N*/ 
/*N*/ 	// ist schon alles dirty gesetzt oder downing => nicht zu tun
/*N*/ 	if ( !pDispatcher || pImp->bAllDirty || SFX_APP()->IsDowning() )
/*N*/ 		return;
/*N*/ 
/*N*/ 	// in immer kleiner werdenden Berichen bin"ar suchen
/*N*/ 	for ( sal_uInt16 n = GetSlotPos(*pIds);
/*N*/ 		  *pIds && n < pImp->pCaches->Count();
/*N*/ 		  n = GetSlotPos(*pIds, n) )
/*N*/ 	{
/*N*/ 		// falls SID "uberhaupt gebunden ist, den Cache invalidieren
/*N*/ 		SfxStateCache *pCache = pImp->pCaches->GetObject(n);
/*N*/ 		if ( pCache->GetId() == *pIds )
/*N*/ 			pCache->Invalidate(sal_False);
/*N*/ 
/*N*/ 		// n"achste SID
/*N*/ 		if ( !*++pIds )
/*N*/ 			break;
/*N*/ 		DBG_ASSERT( *pIds > *(pIds-1), "pIds unsorted" );
/*N*/ 	}
/*N*/ 
/*N*/ 	// falls nicht gelockt, Update-Timer starten
/*N*/ 	pImp->nMsgPos = 0;
/*N*/ 	if ( !nRegLevel )
/*N*/ 	{
/*N*/ 		pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
/*N*/ 		pImp->aTimer.Start();
//		pImp->bFirstRound = sal_True;
//		pImp->nFirstShell = 0;
/*N*/ 	}
/*N*/ 
/*N*/ 	DBG_PROFSTOP(SfxBindingsInvalidateAll);
/*N*/ }

//--------------------------------------------------------------------

/*N*/ void SfxBindings::InvalidateShell
/*N*/ (
/*N*/ 	const SfxShell&     rSh             /*  Die <SfxShell>, deren Slot-Ids
											invalidiert werden sollen. */,

/*N*/ 	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
/*N*/ )

/*  [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)>
*/

/*N*/ {
/*N*/ 	DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
/*N*/ 
/*N*/ 	if ( pImp->pSubBindings )
/*?*/ 		pImp->pSubBindings->InvalidateShell( rSh, bDeep );
/*N*/ 
/*N*/ 	if ( !pDispatcher || pImp->bAllDirty || SFX_APP()->IsDowning() )
/*N*/ 		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);
/*N*/ }

//--------------------------------------------------------------------

/*N*/ void SfxBindings::Invalidate
/*N*/ (
/*N*/ 	sal_uInt16 nId              // zu invalidierende Slot-Id
/*N*/ )

/*  [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)>
*/

/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
/*N*/ 
/*N*/ 	if ( pImp->pSubBindings )
/*N*/ 		pImp->pSubBindings->Invalidate( nId );
/*N*/ 
/*N*/ 	if ( !pDispatcher || pImp->bAllDirty || SFX_APP()->IsDowning() )
/*N*/ 		return;
/*N*/ 
/*N*/ 	SfxStateCache* pCache = GetStateCache(nId);
/*N*/ 	if ( pCache )
/*N*/ 	{
/*N*/ 		pCache->Invalidate(sal_False);
/*N*/ 		pImp->nMsgPos = Min(GetSlotPos(nId), pImp->nMsgPos);
/*N*/ 		if ( !nRegLevel )
/*N*/ 		{
/*N*/ 			pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
/*N*/ 			pImp->aTimer.Start();
/*N*/ 		}
/*N*/ 	}
/*N*/ }

//--------------------------------------------------------------------

/*N*/ void SfxBindings::Invalidate
/*N*/ (
/*N*/ 	sal_uInt16  nId,                // zu invalidierende Slot-Id
/*N*/ 	sal_Bool    bWithItem,          // StateCache clearen ?
/*N*/ 	sal_Bool    bWithMsg            // SlotServer neu holen ?
/*N*/ )

/*  [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)>
*/

/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_ASSERT( !pImp->bInUpdate, "SfxBindings::Invalidate while in update" );
/*N*/ 
/*N*/ 	if ( pImp->pSubBindings )
/*?*/ 		pImp->pSubBindings->Invalidate( nId, bWithItem, bWithMsg );
/*N*/ 
/*N*/ 	if ( SFX_APP()->IsDowning() )
/*N*/ 		return;
/*N*/ 
/*N*/ 	SfxStateCache* pCache = GetStateCache(nId);
/*N*/ 	if ( pCache )
/*N*/ 	{
/*N*/ 		if ( bWithItem )
/*N*/ 			pCache->ClearCache();
/*N*/ 		pCache->Invalidate(bWithMsg);
/*N*/ 
/*N*/ 		if ( !pDispatcher || pImp->bAllDirty )
/*N*/ 			return;
/*N*/ 
/*N*/ 		pImp->nMsgPos = Min(GetSlotPos(nId), pImp->nMsgPos);
/*N*/ 		if ( !nRegLevel )
/*N*/ 		{
/*N*/ 			pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
/*N*/ 			pImp->aTimer.Start();
/*N*/ 		}
/*N*/ 	}
/*N*/ }

/*N*/ void SfxBindings::Invalidate
/*N*/ (
/*N*/ 	sal_uInt16  nId,                // zu invalidierende Slot-Id
/*N*/ 	sal_Bool    bWithMsg            // SlotServer neu holen ?
/*N*/ )

/*  [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)>
*/

/*N*/ {DBG_BF_ASSERT(0, "STRIP"); //STRIP001 
	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();
		}
	}
*/
/*N*/ }

//--------------------------------------------------------------------

/*N*/ 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.
*/

/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
/*N*/ 	return GetStateCache(nSlotId, &nStartSearchAt ) != 0;
/*N*/ }

//--------------------------------------------------------------------

/*N*/ 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.
*/

/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
/*N*/ 	DBG_PROFSTART(SfxBindingsMsgPos);
/*N*/ 
/*N*/ 	// answer immediately if a function-seek comes repeated
/*N*/ 	if ( pImp->nCachedFunc1 < pImp->pCaches->Count() &&
/*N*/ 		 (*pImp->pCaches)[pImp->nCachedFunc1]->GetId() == nId )
/*N*/ 	{
/*N*/ 		++nCache1;
/*N*/ 		DBG_PROFSTOP(SfxBindingsMsgPos);
/*N*/ 		return pImp->nCachedFunc1;
/*N*/ 	}
/*N*/ 	if ( pImp->nCachedFunc2 < pImp->pCaches->Count() &&
/*N*/ 		 (*pImp->pCaches)[pImp->nCachedFunc2]->GetId() == nId )
/*N*/ 	{
/*N*/ 		++nCache2;
/*N*/ 
/*N*/ 		// swap the caches
/*N*/ 		sal_uInt16 nTemp = pImp->nCachedFunc1;
/*N*/ 		pImp->nCachedFunc1 = pImp->nCachedFunc2;
/*N*/ 		pImp->nCachedFunc2 = nTemp;
/*N*/ 		DBG_PROFSTOP(SfxBindingsMsgPos);
/*N*/ 		return pImp->nCachedFunc1;
/*N*/ 	}
/*N*/ 
/*N*/ 	// binary search, if not found, seek to target-position
/*N*/ 	if ( pImp->pCaches->Count() <= nStartSearchAt )
/*N*/ 	{
/*N*/ 		DBG_PROFSTOP(SfxBindingsMsgPos);
/*N*/ 		return 0;
/*N*/ 	}
/*N*/ 	if ( pImp->pCaches->Count() == (nStartSearchAt+1) )
/*N*/ 	{
/*N*/ 		DBG_PROFSTOP(SfxBindingsMsgPos);
/*N*/ 		return (*pImp->pCaches)[nStartSearchAt]->GetId() >= nId ? 0 : 1;
/*N*/ 	}
/*N*/ 	size_t nLow = nStartSearchAt, nMid, nHigh = 0;
/*N*/ 	sal_Bool bFound = sal_False;
/*N*/ 	nHigh = pImp->pCaches->Count() - 1;
/*N*/ 	while ( !bFound && nLow <= nHigh )
/*N*/ 	{
/*N*/ 		nMid = (nLow + nHigh) >> 1;
/*N*/ 		DBG_ASSERT( nMid < pImp->pCaches->Count(), "bsearch ist buggy" );
/*N*/ 		int nDiff = (int) nId - (int) ( ((*pImp->pCaches)[nMid])->GetId() );
/*N*/ 		if ( nDiff < 0)
/*N*/ 		{   if ( nMid == 0 )
/*N*/ 				break;
/*N*/ 			nHigh = nMid - 1;
/*N*/ 		}
/*N*/ 		else if ( nDiff > 0 )
/*N*/ 		{   nLow = nMid + 1;
/*N*/ 			if ( nLow == 0 )
/*N*/ 				break;
/*N*/ 		}
/*N*/ 		else
/*N*/ 			bFound = sal_True;
/*N*/ 	}
/*N*/ 	sal_uInt16 nPos = bFound ? nMid : nLow;
/*N*/ 	DBG_ASSERT( nPos <= pImp->pCaches->Count(), "" );
/*N*/ 	DBG_ASSERT( nPos == pImp->pCaches->Count() ||
/*N*/ 				nId <= (*pImp->pCaches)[nPos]->GetId(), "" );
/*N*/ 	DBG_ASSERT( nPos == nStartSearchAt ||
/*N*/ 				nId > (*pImp->pCaches)[nPos-1]->GetId(), "" );
/*N*/ 	DBG_ASSERT( ( (nPos+1) >= pImp->pCaches->Count() ) ||
/*N*/ 				nId < (*pImp->pCaches)[nPos+1]->GetId(), "" );
/*N*/ 	pImp->nCachedFunc2 = pImp->nCachedFunc1;
/*N*/ 	pImp->nCachedFunc1 = nPos;
/*N*/ 	DBG_PROFSTOP(SfxBindingsMsgPos);
/*N*/ 	return nPos;
/*N*/ }
//--------------------------------------------------------------------

/*N*/ 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()>
*/

/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_ASSERT( nRegLevel > 0, "registration without EnterRegistrations" );
/*N*/ 	DBG_ASSERT( !pImp->bInNextJob, "SfxBindings::Register while status-updating" );
/*N*/ 	//! EnterRegistrations();
/*N*/ 
/*N*/ 	// if not exist, insert a new cache
/*N*/ 	sal_uInt16 nId = rItem.GetId();
/*N*/ 	sal_uInt16 nPos = GetSlotPos(nId);
/*N*/ 	if ( nPos >= pImp->pCaches->Count() ||
/*N*/ 		 (*pImp->pCaches)[nPos]->GetId() != nId )
/*N*/ 	{
/*N*/ 		SfxStateCache* pCache = new SfxStateCache(nId);
/*N*/ 		pImp->pCaches->Insert( nPos, pCache );
/*N*/ 		DBG_ASSERT( nPos == 0 ||
/*N*/ 					(*pImp->pCaches)[nPos]->GetId() >
/*N*/ 						(*pImp->pCaches)[nPos-1]->GetId(), "" );
/*N*/ 		DBG_ASSERT( (nPos == pImp->pCaches->Count()-1) ||
/*N*/ 					(*pImp->pCaches)[nPos]->GetId() <
/*N*/ 						(*pImp->pCaches)[nPos+1]->GetId(), "" );
/*N*/ 		pImp->bMsgDirty = sal_True;
/*N*/ 	}
/*N*/ 
/*N*/ 	// enqueue the new binding
/*N*/ 	SfxControllerItem *pOldItem = (*pImp->pCaches)[nPos]->ChangeItemLink(&rItem);
/*N*/ 	rItem.ChangeItemLink(pOldItem);
/*N*/ 
/*N*/ 	//! LeaveRegistrations();
/*N*/ }
//--------------------------------------------------------------------

/*N*/ 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()>
*/

/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
/*N*/ 	//! DBG_ASSERT( nRegLevel > 0, "release without EnterRegistrations" );
/*N*/ 	DBG_ASSERT( !pImp->bInNextJob, "SfxBindings::Release while status-updating" );
/*N*/ 	ENTERREGISTRATIONS();
/*N*/ 
/*N*/ 	// find the bound function
/*N*/ 	sal_uInt16 nId = rItem.GetId();
/*N*/ 	sal_uInt16 nPos = GetSlotPos(nId);
/*N*/ 	SfxStateCache* pCache = (*pImp->pCaches)[nPos];
/*N*/ 	if ( pCache->GetId() == nId )
/*N*/ 	{
/*N*/ 		// is this the first binding in the list?
/*N*/ 		SfxControllerItem* pItem = pCache->GetItemLink();
/*N*/ 		if ( pItem == &rItem )
/*N*/ 			pCache->ChangeItemLink( rItem.GetItemLink() );
/*N*/ 		else
/*N*/ 		{
/*N*/ 			// search the binding in the list
/*N*/ 			while ( pItem && pItem->GetItemLink() != &rItem )
/*N*/ 				pItem = pItem->GetItemLink();
/*N*/ 
/*N*/ 			// unlink it if it was found
/*N*/ 			if ( pItem )
/*N*/ 				pItem->ChangeItemLink( rItem.GetItemLink() );
/*N*/ 		}
/*N*/ 		// was this the last controller?
/*N*/ 		if ( pCache->GetItemLink() == 0 )
/*N*/ 		{
/*N*/ #ifdef slow
/*N*/ 			// remove the BoundFunc
/*N*/ 			delete (*pImp->pCaches)[nPos];
/*N*/ 			pImp->pCaches->Remove(nPos, 1);
/*N*/ #endif
/*N*/ 			if ( SfxMacroConfig::IsMacroSlot( nId ) )
/*N*/ 			{
/*?*/ 				delete (*pImp->pCaches)[nPos];
/*?*/ 				pImp->pCaches->Remove(nPos, 1);
/*N*/ 			}
/*N*/ 			else
/*N*/ 				pImp->bCtrlReleased = sal_True;
/*N*/ 		}
/*N*/ 	}
/*N*/ 
/*N*/ 	LEAVEREGISTRATIONS();
/*N*/ }

//--------------------------------------------------------------------
/*?*/ const SfxPoolItem* SfxBindings::ExecuteSynchron( sal_uInt16 nId, const SfxPoolItem** ppItems, sal_uInt16 nModi,
/*?*/             const SfxPoolItem **ppInternalArgs )
/*?*/ {
/*?*/ 	DBG_MEMTEST();
/*?*/ 	DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
/*?*/ 
/*?*/     if( !nId || !pDispatcher )
/*?*/         return NULL;
/*?*/ 
/*?*/     return Execute_Impl( nId, ppItems, nModi, SFX_CALLMODE_SYNCHRON, ppInternalArgs );
/*?*/ }

/*N*/ sal_Bool SfxBindings::Execute( sal_uInt16 nId, const SfxPoolItem** ppItems, sal_uInt16 nModi, SfxCallMode nCallMode,
/*N*/                         const SfxPoolItem **ppInternalArgs )

/*  [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>
*/
/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
/*N*/ 
/*N*/     if( !nId || !pDispatcher )
/*N*/ 		return sal_False;
/*N*/ 
/*N*/     const SfxPoolItem* pRet = Execute_Impl( nId, ppItems, nModi, nCallMode, ppInternalArgs );
/*N*/     return ( pRet != 0 );
/*N*/ }

/*?*/ void SfxBindings::ExecuteGlobal_Impl( USHORT nId )
/*?*/ {{DBG_BF_ASSERT(0, "STRIP");}//STRIP001 
/*?*/ }

/*N*/ const SfxPoolItem* SfxBindings::Execute_Impl( sal_uInt16 nId, const SfxPoolItem** ppItems, sal_uInt16 nModi, SfxCallMode nCallMode,
/*N*/                         const SfxPoolItem **ppInternalArgs, BOOL bGlobalOnly )
/*N*/ {
/*N*/ 	SfxStateCache *pCache = GetStateCache( nId );
/*N*/     if ( !pCache )
/*N*/     {
/*?*/         SfxBindings *pBind = pImp->pSubBindings;
/*?*/         while ( pBind )
/*?*/         {
/*?*/             if ( pBind->GetStateCache( nId ) )
/*?*/                 return pBind->Execute_Impl( nId, ppItems, nModi, nCallMode, ppInternalArgs, bGlobalOnly );
/*?*/             pBind = pBind->pImp->pSubBindings;
/*?*/         };
/*N*/     }
/*N*/ 
/*N*/ 	SfxDispatcher &rDispatcher = *pDispatcher;
/*N*/ 	rDispatcher.Flush();
/*N*/ 	SfxViewFrame *pFrame = rDispatcher.GetFrame();
/*N*/ 
/*N*/     // get SlotServer (Slot+ShellLevel) and Shell from cache
/*N*/     sal_Bool bDeleteCache = sal_False;
/*N*/     if ( !pCache )
/*N*/     {
/*?*/         // Execution of non cached slots (Accelerators don't use Controllers)
/*?*/         // slot is uncached, use SlotCache to handle external dispatch providers
/*?*/         pCache = new SfxStateCache( nId );
/*?*/         pCache->GetSlotServer( rDispatcher, pImp->xProv );
/*?*/         bDeleteCache = sal_True;
/*N*/     }
/*N*/ 
/*N*/     if ( pCache && pCache->GetDispatch().is() )
/*N*/ 	{
/*?*/         // cache binds to an external dispatch provider
/*?*/         pCache->Dispatch( nCallMode == SFX_CALLMODE_SYNCHRON );
/*?*/         if ( bDeleteCache )
/*?*/             DELETEZ( pCache );
/*?*/         SfxPoolItem *pVoid = new SfxVoidItem( nId );
/*?*/         DeleteItemOnIdle( pVoid );
/*?*/         return pVoid;
/*N*/ 	}
/*N*/ 
/*N*/     // slot is handled internally by SfxDispatcher
/*N*/ 	if ( pImp->bMsgDirty )
/*?*/ 		UpdateSlotServer_Impl();
/*N*/ 
/*N*/ 	SfxShell *pShell=0;
/*N*/ 	const SfxSlot *pSlot=0;
/*N*/ 
/*N*/     // if slot was uncached, we should have created a cache in this method!
/*N*/     DBG_ASSERT( pCache, "This code needs a cache!");
/*N*/     const SfxSlotServer* pServer = pCache ? pCache->GetSlotServer( rDispatcher, pImp->xProv ) : 0;
/*N*/ 	if ( !pServer )
/*N*/ 	{
/*?*/         return NULL;
/*N*/ 	}
/*N*/ 	else
/*N*/ 	{
/*N*/ 		pShell = rDispatcher.GetShell( pServer->GetShellLevel() );
/*N*/ 		pSlot = pServer->GetSlot();
/*N*/ 	}
/*N*/ 
/*N*/ 	if ( bGlobalOnly )
/*N*/ 		if ( !pShell->ISA(SfxModule) && !pShell->ISA(SfxApplication) && !pShell->ISA(SfxViewFrame) )
/*N*/ 			return NULL;
/*N*/ 
/*N*/ 	SfxItemPool &rPool = pShell->GetPool();
/*N*/     SfxRequest aReq( nId, nCallMode, rPool );
/*N*/ 	aReq.SetModifier( nModi );
/*N*/ 	if( ppItems )
/*N*/ 		while( *ppItems )
/*?*/ 			aReq.AppendItem( **ppItems++ );
/*N*/     if ( ppInternalArgs )
/*N*/     {
/*?*/         SfxAllItemSet aSet( rPool );
/*?*/         for ( const SfxPoolItem **pArg = ppInternalArgs; *pArg; ++pArg )
/*?*/             aSet.Put( **pArg );
/*?*/         aReq.SetInternalArgs_Impl( aSet );
/*N*/     }
/*N*/ 
/*N*/     Execute_Impl( aReq, pSlot, pShell );
/*N*/ 
/*N*/     const SfxPoolItem* pRet = aReq.GetReturnValue();
/*N*/     if ( !pRet )
/*N*/     {
/*N*/         SfxPoolItem *pVoid = new SfxVoidItem( nId );
/*N*/         DeleteItemOnIdle( pVoid );
/*N*/         pRet = pVoid;
/*N*/     }
/*N*/ 
/*N*/     if ( bDeleteCache )
/*N*/         delete pCache;
/*N*/ 
/*N*/     return pRet;
/*N*/ }

/*N*/ void SfxBindings::Execute_Impl( SfxRequest& aReq, const SfxSlot* pSlot, SfxShell* pShell )
/*N*/ {
/*N*/ 	SfxItemPool &rPool = pShell->GetPool();
/*N*/ 	if ( SFX_KIND_ENUM == pSlot->GetKind() )
/*N*/ 	{
/*?*/ 		// 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() ) );
/*?*/         pDispatcher->_Execute( *pShell, *pRealSlot, aReq, aReq.GetCallMode() | SFX_CALLMODE_RECORD );
/*N*/ 	}
/*N*/ 	else if ( SFX_KIND_ATTR == pSlot->GetKind() )
/*N*/ 	{
/*N*/ 		// bei Attr-Slots muá der Which-Wert gemapped werden
/*N*/ 		const sal_uInt16 nSlotId = pSlot->GetSlotId();
/*N*/ 		aReq.SetSlot( nSlotId );
/*N*/ 		if ( pSlot->IsMode(SFX_SLOT_TOGGLE) )
/*N*/ 		{
/*?*/ 			// 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" );
/*N*/ 		}
/*N*/ 
/*N*/         pDispatcher->_Execute( *pShell, *pSlot, aReq, aReq.GetCallMode() | SFX_CALLMODE_RECORD );
/*N*/ 	}
/*N*/ 	else
/*?*/         pDispatcher->_Execute( *pShell, *pSlot, aReq, aReq.GetCallMode() | SFX_CALLMODE_RECORD );
/*N*/ }

//--------------------------------------------------------------------

/*N*/ void SfxBindings::UpdateSlotServer_Impl()

/*  [Beschreibung]

	Interne Methode zum Updaten der Pointer auf die SlotServer
	nach <SfxBindings::InvalidateAll(sal_Bool)>.
*/

/*N*/ {
/*N*/ 	DBG_PROFSTART(SfxBindingsUpdateServers);
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
/*N*/ 
	// synchronisieren
/*N*/ 	pDispatcher->Flush();
//  pDispatcher->Update_Impl();

/*N*/ 	if ( pImp->bAllMsgDirty )
/*N*/ 	{
/*N*/ 		if ( !nRegLevel )
/*N*/ 		{
/*N*/ 			::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame > xFrame
/*N*/ 			    ( pDispatcher->GetFrame()->GetFrame()->GetFrameInterface(), UNO_QUERY );
/*N*/ 			if ( xFrame.is() )
/*N*/ 		    	xFrame->contextChanged();
/*N*/ 			pImp->bContextChanged = FALSE;
/*N*/ 		}
/*N*/ 		else
/*N*/ 			pImp->bContextChanged = TRUE;
/*N*/ 	}
/*N*/ 
/*N*/ 	const sal_uInt16 nCount = pImp->pCaches->Count();
/*N*/ 	for(sal_uInt16 i = 0; i < nCount; ++i)
/*N*/ 	{
/*N*/ 		SfxStateCache *pCache = pImp->pCaches->GetObject(i);
/*N*/         pCache->GetSlotServer(*pDispatcher, pImp->xProv);
/*N*/ 	}
/*N*/ 	pImp->bMsgDirty = pImp->bAllMsgDirty = sal_False;
/*N*/ 
/*N*/ 	Broadcast( SfxSimpleHint(SFX_HINT_DOCCHANGED) );
/*N*/ 
/*N*/ 	DBG_PROFSTOP(SfxBindingsUpdateServers);
/*N*/ }

//--------------------------------------------------------------------

/*?*/ #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;
/*?*/ }

//--------------------------------------------------------------------

/*N*/ SfxItemSet* SfxBindings::CreateSet_Impl
/*N*/ (
/*N*/ 	SfxStateCache*&             pCache,     // in: Status-Cache von nId
/*N*/ 	const SfxSlot*&             pRealSlot,  // out: RealSlot zu nId
/*N*/ 	const SfxSlotServer**	 pMsgServer, // out: Slot-Server zu nId
/*N*/ 	SfxFoundCacheArr_Impl&      rFound      // out: Liste der Caches der Siblings
/*N*/ )

/*  [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.
*/

/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
/*N*/ 
/*N*/ 	DBG_ASSERT( !pImp->bMsgDirty, "CreateSet_Impl mit dirty MessageServer" );
/*N*/ 
/*N*/     const SfxSlotServer* pMsgSvr = pCache->GetSlotServer(*pDispatcher, pImp->xProv);
/*N*/ 	if(!pMsgSvr || !pDispatcher)
/*N*/ 		return 0;
/*N*/ 
/*N*/ 	DBG_PROFSTART(SfxBindingsCreateSet);
/*N*/ 	pRealSlot = 0;
/*N*/ 	*pMsgServer = pMsgSvr;
/*N*/ 
/*N*/     sal_uInt16 nShellLevel = pMsgSvr->GetShellLevel();
/*N*/     SfxShell *pShell = pDispatcher->GetShell( nShellLevel );
/*N*/ 	if ( !pShell ) // seltener GPF beim Browsen durch Update aus Inet-Notify
/*N*/ 		return 0;
/*N*/ 
/*N*/ 	SfxItemPool &rPool = pShell->GetPool();
/*N*/ 
/*N*/ 	// hole die Status-Methode, von der pCache bedient wird
/*N*/ 	SfxStateFunc pFnc = 0;
/*N*/ 	const SfxInterface *pInterface = pShell->GetInterface();
/*N*/ 	if ( SFX_KIND_ENUM == pMsgSvr->GetSlot()->GetKind() )
/*N*/ 	{
/*?*/ 		pRealSlot = pInterface->GetRealSlot(pMsgSvr->GetSlot());
/*?*/ 		pCache = GetStateCache( pRealSlot->GetSlotId() );
/*N*/ //		DBG_ASSERT( pCache, "Kein Slotcache fuer den Masterslot gefunden!" );
/*N*/ 	}
/*N*/ 	else
/*N*/ 		pRealSlot = pMsgSvr->GetSlot();
/*N*/ 
/*N*/ 	//
/*N*/ 	// Achtung: pCache darf auch NULL sein !!!
/*N*/ 	//
/*N*/ 
/*N*/ 	pFnc = pRealSlot->GetStateFnc();
/*N*/ 
/*N*/ 	// der RealSlot ist immer drin
/*N*/ 	const SfxFoundCache_Impl *pFound = new SfxFoundCache_Impl(
/*N*/ 		pRealSlot->GetSlotId(), pRealSlot->GetWhich(rPool), pRealSlot, pCache );
/*N*/ 	rFound.Insert( pFound );
/*N*/ 
/*N*/     USHORT nSlot = pRealSlot->GetSlotId();
/*N*/     if ( !SfxMacroConfig::IsMacroSlot( nSlot ) && !(nSlot >= SID_VERB_START && nSlot <= SID_VERB_END) )
/*N*/ 	{
/*N*/         pInterface = pInterface->GetRealInterfaceForSlot( pRealSlot );
/*N*/ 		DBG_ASSERT (pInterface,"Slot in angegebener Shell nicht gefunden!");
/*N*/ 	}
/*N*/ 
/*N*/ 	// Durchsuche die Bindings nach den von derselben Funktion bedienten Slots.
/*N*/ 	// Daf"ur kommen nur Slots in Frage, die es im gefundenen Interface gibt.
/*N*/ 
/*N*/ 	// Die Position des Statecaches im StateCache-Array
/*N*/ 	sal_uInt16 nCachePos = pImp->nMsgPos;
/*N*/ 	const SfxSlot *pSibling = pRealSlot->GetNextSlot();
/*N*/ 
/*N*/ 	// Die Slots eines Interfaces sind im Kreis verkettet
/*N*/ 	while ( pSibling > pRealSlot )
/*N*/ 	{
/*N*/ 		SfxStateFunc pSiblingFnc=0;
/*N*/ 		SfxStateCache *pSiblingCache =
/*N*/ 				GetStateCache( pSibling->GetSlotId(), &nCachePos );
/*N*/ 
/*N*/ 		// Ist der Slot "uberhaupt gecached ?
/*N*/ 		if ( pSiblingCache )
/*N*/ 		{
/*N*/             const SfxSlotServer *pServ = pSiblingCache->GetSlotServer(*pDispatcher, pImp->xProv);
/*N*/ 			if ( pServ && pServ->GetShellLevel() == nShellLevel )
/*N*/ 				pSiblingFnc = pServ->GetSlot()->GetStateFnc();
/*N*/ 		}
/*N*/ 
/*N*/ 		// Mu\s der Slot "uberhaupt upgedatet werden ?
/*N*/ 		FASTBOOL bInsert = pSiblingCache && pSiblingCache->IsControllerDirty();
/*N*/ 
/*N*/ 		// Bugfix #26161#: Es reicht nicht, nach der selben Shell zu fragen !!
/*N*/ 		FASTBOOL bSameMethod = pSiblingCache && pFnc == pSiblingFnc;
/*N*/ 
/*N*/ 		// Wenn der Slot ein nicht-dirty MasterSlot ist, dann ist vielleicht
/*N*/ 		// einer seiner Slaves dirty ? Dann wird der Masterslot doch eingef"ugt.
/*N*/ 		if ( !bInsert && bSameMethod && pSibling->GetLinkedSlot() )
/*N*/ 		{
/*N*/ 			// 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;
/*?*/ 			}
/*N*/ 		}
/*N*/ 
/*N*/ 		if ( bInsert && bSameMethod )
/*N*/ 		{
/*N*/ 			const SfxFoundCache_Impl *pFound = new SfxFoundCache_Impl(
/*N*/ 				pSibling->GetSlotId(), pSibling->GetWhich(rPool),
/*N*/ 				pSibling, pSiblingCache );
/*N*/ 
/*N*/ 			rFound.Insert( pFound );
/*N*/ 		}
/*N*/ 
/*N*/ 		pSibling = pSibling->GetNextSlot();
/*N*/ 	}
/*N*/ 
/*N*/ 	// aus den Ranges ein Set erzeugen
/*N*/ 	sal_uInt16 *pRanges = new sal_uInt16[rFound.Count() * 2 + 1];
/*N*/ 	int j = 0;
/*N*/ 	int i = 0;
/*N*/ 	while ( i < rFound.Count() )
/*N*/ 	{
/*N*/ 		pRanges[j++] = rFound[i]->nWhichId;
/*N*/ 			// aufeinanderfolgende Zahlen
/*N*/ 		for ( ; i < rFound.Count()-1; ++i )
/*N*/ 			if ( rFound[i]->nWhichId+1 != rFound[i+1]->nWhichId )
/*N*/ 				break;
/*N*/ 		pRanges[j++] = rFound[i++]->nWhichId;
/*N*/ 	}
/*N*/ 	pRanges[j] = 0; // terminierende NULL
/*N*/ 	SfxItemSet *pSet = new SfxItemSet(rPool, pRanges);
/*N*/     delete [] pRanges;
/*N*/ 	DBG_PROFSTOP(SfxBindingsCreateSet);
/*N*/ 	return pSet;
/*N*/ }

//--------------------------------------------------------------------

/*N*/ void SfxBindings::UpdateControllers_Impl
/*N*/ (
/*N*/ 	const SfxInterface*         pIF,    // das diese Id momentan bedienende Interface
/*N*/ 	const SfxFoundCache_Impl*   pFound, // Cache, Slot, Which etc.
/*N*/ 	const SfxPoolItem*			pItem,	// item to send to controller
/*N*/ 	SfxItemState				eState	// state of item
/*N*/ )

/*  [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.
*/

/*N*/ {
/*N*/ 	DBG_ASSERT( !pFound->pSlot || SFX_KIND_ENUM != pFound->pSlot->GetKind(),
/*N*/ 				"direct update of enum slot isn't allowed" );
/*N*/ 	DBG_PROFSTART(SfxBindingsUpdateCtrl1);
/*N*/ 
/*N*/ 	SfxStateCache* pCache = pFound->pCache;
/*N*/ 	const SfxSlot* pSlot = pFound->pSlot;
/*N*/ 	DBG_ASSERT( !pCache || !pSlot || pCache->GetId() == pSlot->GetSlotId(), "SID mismatch" );
/*N*/ 
/*N*/ 	// insofern gebunden, die Controller f"uer den Slot selbst updaten
/*N*/ 	if ( pCache && pCache->IsControllerDirty() )
/*N*/ 	{
/*N*/         if ( SFX_ITEM_DONTCARE == eState )
/*N*/         {
/*N*/             // uneindeuting
/*?*/             pCache->SetState( SFX_ITEM_DONTCARE, (SfxPoolItem *)-1 );
/*N*/         }
/*N*/         else if ( SFX_ITEM_DEFAULT == eState &&
/*N*/                     pFound->nWhichId > SFX_WHICH_MAX )
/*N*/         {
/*N*/             // kein Status oder Default aber ohne Pool
/*N*/             SfxVoidItem aVoid(0);
/*N*/             pCache->SetState( SFX_ITEM_UNKNOWN, &aVoid );
/*N*/         }
/*N*/         else if ( SFX_ITEM_DISABLED == eState )
/*N*/             pCache->SetState(SFX_ITEM_DISABLED, 0);
/*N*/         else
/*N*/             pCache->SetState(SFX_ITEM_AVAILABLE, pItem);
/*N*/ 	}
/*N*/ 
/*N*/ 	DBG_PROFSTOP(SfxBindingsUpdateCtrl1);
/*N*/ 
/*N*/ 	// insofern vorhanden und gebunden, die Controller f"uer Slave-Slots
/*N*/ 	// (Enum-Werte) des Slots updaten
/*N*/ 	DBG_PROFSTART(SfxBindingsUpdateCtrl2);
/*N*/ 	DBG_ASSERT( !pSlot || 0 == pSlot->GetLinkedSlot() || !pItem ||
/*N*/ 				pItem->ISA(SfxEnumItemInterface),
/*N*/ 				"master slot with non-enum-type found" );
/*N*/ 	const SfxSlot *pFirstSlave = pSlot ? pSlot->GetLinkedSlot() : 0;
/*N*/ 	if ( pIF && pFirstSlave)
/*N*/ 	{
/*N*/ 		// Items auf EnumItem casten
/*N*/ 		const SfxEnumItemInterface *pEnumItem =
/*N*/ 				PTR_CAST(SfxEnumItemInterface,pItem);
/*N*/ 		if ( eState == SFX_ITEM_AVAILABLE && !pEnumItem )
/*N*/ 			eState = SFX_ITEM_DONTCARE;
/*N*/ 		else
/*N*/ 			eState = SfxControllerItem::GetItemState( pEnumItem );
/*N*/ 
/*N*/ 		// "uber alle Slaves-Slots iterieren
/*N*/ 		for ( const SfxSlot *pSlave = pFirstSlave; pSlave; pSlave = pSlave->GetNextSlot() )
/*N*/ 		{
/*N*/ 			DBG_ASSERT(pSlave, "Falsche SlaveSlot-Verkettung!");
/*N*/ 			DBG_ASSERT(SFX_KIND_ENUM == pSlave->GetKind(),"non enum slaves aren't allowed");
/*N*/ 			DBG_ASSERT(pSlave->GetMasterSlotId() == pSlot->GetSlotId(),"falscher MasterSlot!");
/*N*/ 
/*N*/ 			// ist die Funktion gebunden?
/*N*/ 			SfxStateCache *pEnumCache = GetStateCache( pSlave->GetSlotId() );
/*N*/ 			if ( pEnumCache )
/*N*/ 			{
/*?*/ 				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 || !pEnumItem->IsEnabled( pSlave->GetSlotId()) )
/*?*/ 				{
/*?*/ 					// 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 );
/*?*/ 				}
/*N*/ 			}
/*N*/ 
/*N*/ 			if (pSlave->GetNextSlot() == pFirstSlave)
/*N*/ 				break;
/*N*/ 		}
/*N*/ 	}
/*N*/ 
/*N*/ 	DBG_PROFSTOP(SfxBindingsUpdateCtrl2);
/*N*/ }


//--------------------------------------------------------------------

/*N*/ IMPL_LINK( SfxBindings, NextJob_Impl, Timer *, pTimer )

/*  [Beschreibung]

	Die SfxController werden "uber einen Timer updated. Dieses ist der
	dazugeh"orige interne TimeOut-Handler.
 */

/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_ASSERT( pImp->pCaches != 0, "SfxBindings not initialized" );
/*N*/ 
/*N*/ 	DBG_PROFSTART(SfxBindingsNextJob_Impl0);
/*N*/ 	SfxApplication *pSfxApp = SFX_APP();
/*N*/ 
/*N*/ 	if( pDispatcher )
/*N*/ 		pDispatcher->Update_Impl();
/*N*/ 
/*N*/ 	// modifying the SfxObjectInterface-stack without SfxBindings => nothing to do
/*N*/     SfxViewFrame* pFrame = pDispatcher->GetFrame();
/*N*/     if ( pFrame && pFrame->GetObjectShell()->IsInModalMode() || pSfxApp->IsDowning() || !pImp->pCaches->Count() )
/*N*/ 	{
/*N*/ 		DBG_PROFSTOP(SfxBindingsNextJob_Impl0);
/*N*/ 		return sal_True;
/*N*/ 	}
/*N*/ 	if ( !pDispatcher || !pDispatcher->IsFlushed() )
/*N*/ 	{
/*N*/ 		DBG_PROFSTOP(SfxBindingsNextJob_Impl0);
/*N*/ 		return sal_True;
/*N*/ 	}
/*N*/ 
/*N*/ 	// gfs. alle Server aktualisieren / geschieht in eigener Zeitscheibe
/*N*/ 	if ( pImp->bMsgDirty )
/*N*/ 	{
/*N*/ 		UpdateSlotServer_Impl();
/*N*/ 		DBG_PROFSTOP(SfxBindingsNextJob_Impl0);
/*N*/ 		return sal_False;
/*N*/ 	}
/*N*/ 
/*N*/ 	DBG_PROFSTOP(SfxBindingsNextJob_Impl0);
/*N*/ 	DBG_PROFSTART(SfxBindingsNextJob_Impl);
/*N*/ 	pImp->bAllDirty = sal_False;
/*N*/ 	pImp->aTimer.SetTimeout(TIMEOUT_UPDATING);
/*N*/ 
/*N*/ 	// at least 10 loops and further if more jobs are available but no input
/*N*/ 	FASTBOOL bPreEmptive = pTimer && !pSfxApp->Get_Impl()->nInReschedule;
/*N*/ 	sal_uInt16 nLoops = 10;
/*N*/ 	pImp->bInNextJob = sal_True;
/*N*/ 	const sal_uInt16 nCount = pImp->pCaches->Count();
/*N*/ 	while ( pImp->nMsgPos < nCount )
/*N*/ 	{
/*N*/ 		// iterate through the bound functions
/*N*/ 		sal_Bool bJobDone = sal_False;
/*N*/ 		while ( !bJobDone )
/*N*/ 		{
/*N*/ 			SfxStateCache* pCache = (*pImp->pCaches)[pImp->nMsgPos];
/*N*/ 			DBG_ASSERT( pCache, "invalid SfxStateCache-position in job queue" );
/*N*/ 			sal_Bool bWasDirty = pCache->IsControllerDirty();
/*N*/ 			if ( bWasDirty )
/*N*/ 			{
/*
				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 )
				{
*/
/*N*/ 					Update_Impl( pCache );
/*N*/ 					DBG_ASSERT( nCount == pImp->pCaches->Count(),
/*N*/ 							"Reschedule in StateChanged => buff" );
/*N*/ //				}
/*N*/ 			}

			// skip to next function binding
/*N*/ 			++pImp->nMsgPos;

			// keep job if it is not completed, but any input is available
/*N*/ 			bJobDone = pImp->nMsgPos >= nCount;
/*N*/ 			if ( bJobDone && pImp->bFirstRound )
/*N*/ 			{
/*N*/ 				// Update der bevorzugten Shell ist gelaufen, nun d"urfen
/*N*/ 				// auch die anderen
/*?*/ 				bJobDone = sal_False;
/*?*/ 				pImp->bFirstRound = sal_False;
/*?*/ 				pImp->nMsgPos = 0;
/*N*/ 			}
/*N*/ 
/*N*/ 			if ( bWasDirty && !bJobDone && bPreEmptive && (--nLoops == 0) )
/*N*/ 			{
/*N*/ 				DBG_PROFSTOP(SfxBindingsNextJob_Impl);
/*N*/ 				pImp->bInNextJob = sal_False;
/*N*/ 				return sal_False;
/*N*/ 			}
/*N*/ 		}
/*N*/ 	}
/*N*/ 
/*N*/ 	// volatiles wieder von vorne starten
/*N*/ 	pImp->nMsgPos = 0;
/*N*/ 	pImp->aTimer.SetTimeout(TIMEOUT_IDLE);
/*N*/ 	for ( sal_uInt16 n = 0; n < nCount; ++n )
/*N*/ 	{
/*N*/ 		SfxStateCache* pCache = (*pImp->pCaches)[n];
/*N*/         const SfxSlotServer *pSlotServer = pCache->GetSlotServer(*pDispatcher, pImp->xProv);
/*N*/ 		if ( pSlotServer &&
/*N*/ 			 pSlotServer->GetSlot()->IsMode(SFX_SLOT_VOLATILE) )
/*N*/ 			pCache->Invalidate(sal_False);
/*N*/ 	}
/*N*/ 
/*N*/ 	// Update-Runde ist beendet
/*N*/ 	pImp->bInNextJob = sal_False;
/*N*/ 	Broadcast(SfxSimpleHint(SFX_HINT_UPDATEDONE));
/*N*/ 	DBG_PROFSTOP(SfxBindingsNextJob_Impl);
/*N*/ 	return sal_True;
/*N*/ }

//--------------------------------------------------------------------

/*N*/ 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()>
*/

/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ #ifdef DBG_UTIL
/*N*/ 	ByteString aMsg;
/*N*/ 	aMsg.Fill( Min(nRegLevel, sal_uInt16(8) ) );
/*N*/ 	aMsg += "this = ";
/*N*/ 	aMsg += ByteString::CreateFromInt32((long)this);
/*N*/ 	aMsg += " Level = ";
/*N*/ 	aMsg += ByteString::CreateFromInt32(nRegLevel);
/*N*/ 	aMsg += " SfxBindings::EnterRegistrations ";
/*N*/ 	if(pFile) {
/*N*/ 		aMsg += "File: ";
/*N*/ 		aMsg += pFile;
/*N*/ 		aMsg += " Line: ";
/*N*/ 		aMsg += ByteString::CreateFromInt32(nLine);
/*N*/ 	}
/*N*/ 	DbgTrace( aMsg.GetBuffer() );
/*N*/ #endif
/*N*/ 
/*N*/ 	// Wenn Bindings gelockt werden, auch SubBindings locken
/*N*/ 	if ( pImp->pSubBindings )
/*N*/ 	{
/*?*/ 		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;
/*N*/ 	}
/*N*/ 
/*N*/ 	pImp->nOwnRegLevel++;
/*N*/ 
/*N*/ 	// check if this is the outer most level
/*N*/ 	if ( ++nRegLevel == 1 )
/*N*/ 	{
/*N*/ 		// stop background-processing
/*N*/ 		pImp->aTimer.Stop();
/*N*/ 
/*N*/ 		// flush the cache
/*N*/ 		pImp->nCachedFunc1 = 0;
/*N*/ 		pImp->nCachedFunc2 = 0;
/*N*/ 
/*N*/ 		// merken, ob ganze Caches verschwunden sind
/*N*/ 		pImp->bCtrlReleased = sal_False;
/*N*/ 	}
/*N*/ 
/*N*/ 	return nRegLevel;
/*N*/ }
//--------------------------------------------------------------------

/*N*/ 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()>
*/

/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_ASSERT( nRegLevel, "Leave without Enter" );
/*N*/ 	DBG_ASSERT( nLevel == USHRT_MAX || nLevel == nRegLevel, "wrong Leave" );
/*N*/ 
/*N*/ 	// Nur wenn die SubBindings noch von den SuperBindings gelockt sind, diesen Lock entfernen
/*N*/ 	// ( d.h. wenn es mehr Locks als "echte" Locks dort gibt )
/*N*/ 	if ( pImp->pSubBindings && pImp->pSubBindings->nRegLevel > pImp->pSubBindings->pImp->nOwnRegLevel )
/*N*/ 	{
/*?*/ 		// 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();
/*N*/ 	}
/*N*/ 
/*N*/ 	pImp->nOwnRegLevel--;
/*N*/ 
/*N*/ 	// check if this is the outer most level
/*N*/ 	if ( --nRegLevel == 0 && !SFX_APP()->IsDowning() )
/*N*/ 	{
/*N*/ 		if ( pImp->bContextChanged )
/*N*/ 		{
/*N*/ 			::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame > xFrame
/*N*/ 			    ( pDispatcher->GetFrame()->GetFrame()->GetFrameInterface(), UNO_QUERY );
/*N*/ 			if ( xFrame.is() )
/*N*/ 		    	xFrame->contextChanged();
/*N*/ 			pImp->bContextChanged = FALSE;
/*N*/ 		}
/*N*/ 
/*N*/ #ifndef slow
/*N*/ 		SfxViewFrame* pFrame = pDispatcher->GetFrame();
/*N*/ 
/*N*/ 		// ggf unbenutzte Caches entfernen bzw. PlugInInfo aufbereiten
/*N*/ 		if ( pImp->bCtrlReleased )
/*N*/ 		{
/*N*/ 			for ( sal_uInt16 nCache = pImp->pCaches->Count(); nCache > 0; --nCache )
/*N*/ 			{
/*N*/ 				// Cache via ::com::sun::star::sdbcx::Index besorgen
/*N*/ 				SfxStateCache *pCache = pImp->pCaches->GetObject(nCache-1);
/*N*/ 
/*N*/ 				// kein Controller mehr interessiert
/*N*/ 				if ( pCache->GetItemLink() == 0 )
/*N*/ 				{
/*N*/ 					// Cache entfernen
/*N*/ 					delete (*pImp->pCaches)[nCache-1];
/*N*/ 					pImp->pCaches->Remove(nCache-1, 1);
/*N*/ 				}
/*N*/ 				else
/*N*/ 				{
/*N*/ 					// neue Controller mit den alten Items benachrichtigen
/*N*/ 					//!pCache->SetCachedState();
/*N*/ 				}
/*N*/ 			}
/*N*/ 		}
/*N*/ #endif
/*N*/ 		// restart background-processing
/*N*/ 		pImp->nMsgPos = 0;
/*N*/ 		if ( !pFrame || !pFrame->GetObjectShell() )
/*N*/ 			return;
/*N*/ 		if ( pImp->pCaches && pImp->pCaches->Count() )
/*N*/ 		{
/*N*/ 			pImp->aTimer.SetTimeout(TIMEOUT_FIRST);
/*N*/ 			pImp->aTimer.Start();
/*N*/ //			pImp->bFirstRound = sal_True;
/*N*/ 		}
/*N*/ 	}
/*N*/ 
/*N*/ #ifdef DBG_UTIL
/*N*/ 	ByteString aMsg;
/*N*/ 	aMsg.Fill( Min(nRegLevel, sal_uInt16(8)) );
/*N*/ 	aMsg += "this = ";
/*N*/ 	aMsg += ByteString::CreateFromInt32((long)this);
/*N*/ 	aMsg += " Level = ";
/*N*/ 	aMsg += ByteString::CreateFromInt32(nRegLevel);
/*N*/ 	aMsg += " SfxBindings::LeaveRegistrations ";
/*N*/ 	if(pFile) {
/*N*/ 		aMsg += "File: ";
/*N*/ 		aMsg += pFile;
/*N*/ 		aMsg += " Line: ";
/*N*/ 		aMsg += ByteString::CreateFromInt32(nLine);
/*N*/ 	}
/*N*/ 	DbgTrace( aMsg.GetBuffer() );
/*N*/ #endif
/*N*/ }

//--------------------------------------------------------------------

/*?*/ 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;
/*?*/ }

//--------------------------------------------------------------------

/*N*/ 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.
*/

/*N*/ {
/*N*/ 	SfxDispatcher *pOldDispat = pDispatcher;
/*N*/ 	if ( pDisp != pDispatcher )
/*N*/ 	{
/*N*/ 		if ( pOldDispat )
/*N*/ 		{
/*N*/ 			SfxBindings* pBind = pOldDispat->GetBindings();
/*N*/ 			while ( pBind )
/*N*/ 			{
/*N*/ 				if ( pBind->pImp->pSubBindings == this && pBind->pDispatcher != pDisp )
/*N*/ 					pBind->SetSubBindings_Impl( NULL );
/*?*/ 				pBind = pBind->pImp->pSubBindings;
/*N*/ 			}
/*N*/ 		}
/*N*/ 
/*N*/ 		pDispatcher = pDisp;
/*N*/ 
/*N*/         ::com::sun::star::uno::Reference < ::com::sun::star::frame::XDispatchProvider > xProv;
/*N*/         if ( pDisp )
/*N*/             xProv = ::com::sun::star::uno::Reference < ::com::sun::star::frame::XDispatchProvider >
/*N*/                                         ( pDisp->GetFrame()->GetFrame()->GetFrameInterface(), UNO_QUERY );
/*N*/ 
/*N*/         SetDispatchProvider_Impl( xProv );
/*N*/         InvalidateAll( sal_True );
/*N*/         InvalidateUnoControllers_Impl();
/*N*/ 
/*N*/ 		if ( pDispatcher && !pOldDispat )
/*N*/ 		{
/*N*/ 			if ( pImp->pSubBindings && pImp->pSubBindings->pDispatcher != pOldDispat )
/*N*/ 			{
/*?*/ 				DBG_ERROR( "SubBindings vor Aktivieren schon gesetzt!" );
/*?*/ 				pImp->pSubBindings->ENTERREGISTRATIONS();
/*N*/ 			}
/*N*/ 			LEAVEREGISTRATIONS();
/*N*/ 		}
/*N*/ 		else if( !pDispatcher )
/*N*/ 		{
/*N*/ 			ENTERREGISTRATIONS();
/*N*/ 			if ( pImp->pSubBindings && pImp->pSubBindings->pDispatcher != pOldDispat )
/*N*/ 			{
/*?*/ 				DBG_ERROR( "SubBindings im Deaktivieren immer noch gesetzt!" );
/*?*/ 				pImp->pSubBindings->LEAVEREGISTRATIONS();
/*N*/ 			}
/*N*/ 		}
/*N*/ 
/*N*/ 		Broadcast( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
/*N*/ 
/*N*/ 		if ( pDisp )
/*N*/ 		{
/*N*/ 			SfxBindings* pBind = pDisp->GetBindings();
/*N*/ 			while ( pBind && pBind != this )
/*N*/ 			{
/*?*/ 				if ( !pBind->pImp->pSubBindings )
/*?*/ 				{
/*?*/ 					pBind->SetSubBindings_Impl( this );
/*?*/ 					break;
/*?*/ 				}
/*?*/ 
/*?*/ 				pBind = pBind->pImp->pSubBindings;
/*N*/ 			}
/*N*/ 		}
/*N*/ 	}
/*N*/ }

//--------------------------------------------------------------------

/*?*/ 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);
/*?*/ }

//--------------------------------------------------------------------
// Obsolete code, remove later








//-------------------------------------------------------------------------

/*?*/ 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.
*/

/*?*/ {DBG_BF_ASSERT(0, "STRIP"); return SfxItemState();//STRIP001 
/*?*/ }

/*?*/ void SfxBindings::SetSubBindings_Impl( SfxBindings *pSub )
/*?*/ {DBG_BF_ASSERT(0, "STRIP"); //STRIP001 
/*?*/ }

/*N*/ SfxBindings* SfxBindings::GetSubBindings_Impl( sal_Bool bTop ) const
/*N*/ {
/*N*/ 	SfxBindings *pRet = pImp->pSubBindings;
/*N*/ 	if ( bTop )
/*N*/ 	{
/*?*/ 		while ( pRet->pImp->pSubBindings )
/*?*/ 			pRet = pRet->pImp->pSubBindings;
/*N*/ 	}
/*N*/ 
/*N*/ 	return pRet;
/*N*/ }

/*N*/ void SfxBindings::SetWorkWindow_Impl( SfxWorkWindow* pWork )
/*N*/ {
/*N*/ 	pImp->pWorkWin = pWork;
/*N*/ }

/*N*/ SfxWorkWindow* SfxBindings::GetWorkWindow_Impl() const
/*N*/ {
/*N*/ 	return pImp->pWorkWin;
/*N*/ }

/*?*/ void SfxBindings::RegisterUnoController_Impl( SfxUnoControllerItem* pControl )
/*?*/ {DBG_BF_ASSERT(0, "STRIP"); //STRIP001 
/*?*/ }

/*?*/ void SfxBindings::ReleaseUnoController_Impl( SfxUnoControllerItem* pControl )
/*?*/ {DBG_BF_ASSERT(0, "STRIP"); //STRIP001 
/*?*/ }

/*N*/ void SfxBindings::InvalidateUnoControllers_Impl()
/*N*/ {
/*N*/ 	if ( pImp->pUnoCtrlArr )
/*N*/ 	{
/*?*/ 		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();
/*?*/ 		}
/*N*/ 	}
/*N*/ 
/*N*/ 	if ( pImp->pSubBindings )
/*?*/ 		pImp->pSubBindings->InvalidateUnoControllers_Impl();
/*N*/ }

/*N*/ sal_Bool SfxBindings::IsInUpdate() const
/*N*/ {
/*N*/ 	sal_Bool bInUpdate = pImp->bInUpdate;
/*N*/ 	if ( !bInUpdate && pImp->pSubBindings )
/*?*/ 		bInUpdate = pImp->pSubBindings->IsInUpdate();
/*N*/ 	return bInUpdate;
/*N*/ }

/*N*/ void SfxBindings::SetActiveFrame( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > & rFrame )
/*N*/ {
/*N*/     if ( rFrame.is() || !pDispatcher )
/*N*/         SetDispatchProvider_Impl( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > ( rFrame, ::com::sun::star::uno::UNO_QUERY ) );
/*N*/     else
/*N*/         SetDispatchProvider_Impl( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > (
/*N*/             pDispatcher->GetFrame()->GetFrame()->GetFrameInterface(), ::com::sun::star::uno::UNO_QUERY ) );
/*N*/ }

/*N*/ const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > SfxBindings::GetActiveFrame() const
/*N*/ {
/*N*/     const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xFrame( pImp->xProv, ::com::sun::star::uno::UNO_QUERY );
/*N*/     if ( xFrame.is() || !pDispatcher )
/*N*/         return xFrame;
/*N*/     else
/*?*/         return pDispatcher->GetFrame()->GetFrame()->GetFrameInterface();
/*N*/ }

/*N*/ void SfxBindings::SetDispatchProvider_Impl( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > & rProv )
/*N*/ {
/*N*/ 	sal_Bool bInvalidate = ( rProv != pImp->xProv );
/*N*/ 	if ( bInvalidate )
/*N*/ 	{
/*N*/ 		pImp->xProv = rProv;
/*N*/ 		InvalidateAll( sal_True );
/*N*/ 		InvalidateUnoControllers_Impl();
/*N*/ 	}
/*N*/ 
/*N*/ 	if ( pImp->pSubBindings )
/*N*/ 		pImp->pSubBindings->SetDispatchProvider_Impl( pImp->xProv );
/*N*/ }

/*?*/ const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider > & SfxBindings::GetDispatchProvider_Impl() const
/*?*/ {
/*?*/ 	return pImp->xProv;
/*?*/ }

/*N*/ SystemWindow* SfxBindings::GetSystemWindow() const
/*N*/ {
/*N*/     SfxViewFrame *pFrame = pDispatcher->GetFrame();
/*N*/     while ( pFrame->GetParentViewFrame_Impl() )
/*?*/         pFrame = pFrame->GetParentViewFrame_Impl();
/*N*/     SfxTopViewFrame* pTop = PTR_CAST( SfxTopViewFrame, pFrame->GetTopViewFrame() );
/*N*/     return pTop->GetTopFrame_Impl()->GetTopWindow_Impl();
/*N*/ }
/*N*/ 
/*?*/ BOOL SfxBindings::ExecuteCommand_Impl( const String& rCommand )
/*?*/ {DBG_BF_ASSERT(0, "STRIP"); //STRIP001 
/*?*/     return FALSE;
/*?*/ }

/*N*/ SfxImageManager* SfxBindings::GetImageManager() const
/*N*/ {
/*N*/     if ( pDispatcher )
/*N*/         return pDispatcher->GetFrame()->GetImageManager();
/*N*/     return NULL;
/*N*/ }

/*N*/ SfxToolBoxConfig* SfxBindings::GetToolBoxConfig() const
/*N*/ {
/*N*/     if ( pDispatcher && pDispatcher->GetFrame()->GetObjectShell() )
/*N*/         return pDispatcher->GetFrame()->GetObjectShell()->GetToolBoxConfig_Impl();
/*N*/     return NULL;
/*N*/ }

/*N*/ SfxConfigManager* SfxBindings::GetConfigManager( USHORT nType ) const
/*N*/ {
/*N*/     SfxConfigManager *pMgr = pDispatcher->GetFrame()->GetObjectShell()->GetConfigManager();
/*N*/     if ( pMgr && pMgr->HasConfigItem( nType ) )
/*N*/         return pMgr;
/*N*/     else
/*N*/         return SFX_APP()->GetConfigManager_Impl();
/*N*/ }


/*N*/ void SfxBindings::SetRecorder_Impl( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchRecorder >& rRecorder )
/*N*/ {
/*N*/ 	pImp->xRecorder = rRecorder;
/*N*/ }

/*N*/ void SfxBindings::ContextChanged_Impl()
/*N*/ {
/*N*/ 	if ( !pImp->bInUpdate && ( !pImp->bContextChanged || !pImp->bAllMsgDirty ) )
/*N*/ 	{
/*N*/ 		InvalidateAll( TRUE );
/*N*/ 	}
/*N*/ }
}
