/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: sfx2_msgpool.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2006/10/27 19:09:48 $
 *
 *  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 _STREAM_HXX //autogen
#include <tools/stream.hxx>
#endif
#ifndef _RSCSFX_HXX //autogen
#include <rsc/rscsfx.hxx>
#endif
#pragma hdrstop

#include "msgpool.hxx"
#include "app.hxx"
#include "objface.hxx"
#include "idpool.hxx"
#include "slotinfo.hxx"
#include "macrconf.hxx"
#include "arrdecl.hxx"

#include "sfx.hrc"
namespace binfilter {

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

/*N*/ struct SfxSIDRegistration_Impl
/*N*/ {
/*N*/ 	String			_aGroup;
/*N*/ 	String			_aName;
/*N*/ 	USHORT			_nSID;
/*N*/ };

/*N*/ struct SfxSlotType_Impl
/*N*/ {
/*N*/ 	USHORT  nId;
/*N*/ 	TypeId  nType;
/*N*/ 
/*N*/ 	SfxSlotType_Impl( USHORT nTheId, TypeId nTheType ):
/*N*/ 		nId(nTheId), nType(nTheType)
/*N*/ 	{}
/*N*/ };
/*N*/ 
/*N*/ DECL_2BYTEARRAY(SfxSlotGroupArr_Impl, USHORT, 6, 4)//STRIP008 ;
/*N*/ DECL_PTRARRAY(SfxInterfaceArr_Impl, SfxInterface*, 6, 3)//STRIP008 ;
/*N*/ DECL_PTRARRAY(SfxSlotTypeArr_Impl, SfxSlotType_Impl*, 8, 8)//STRIP008 ;
/*N*/ 

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

/*N*/ SfxSlotPool::SfxSlotPool( SfxSlotPool *pParent, ResMgr* pResManager )
/*N*/  : _pParentPool( pParent )
/*N*/  , _pIdPool(0)
/*N*/  , _pTypes(0)
/*N*/  , _pGroups(0)
/*N*/  , _nCurGroup(0)
/*N*/  , _pInterfaces(0)
/*N*/  , _nCurInterface(0)
/*N*/  , _nCurMsg(0)
/*N*/  , _pResMgr( pResManager )
/*N*/  , _pUnoSlots( 0 )
/*N*/ {
/*N*/ 	if ( !_pResMgr )
/*N*/ 		_pResMgr = Resource::GetResManager();
/*N*/ }

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

/*N*/ SfxSlotPool::~SfxSlotPool()
/*N*/ {
/*N*/ 	_pParentPool = 0;
/*N*/ 	for ( SfxInterface *pIF = FirstInterface(); pIF; pIF = FirstInterface() )
/*N*/ 		delete pIF;
/*N*/ 	delete _pInterfaces;
/*N*/ 	delete _pGroups;
/*N*/ 	if ( _pTypes )
/*N*/ 	{
/*N*/ 		for ( USHORT n =_pTypes->Count(); n--; )
/*?*/ 			delete _pTypes->GetObject(n);
/*N*/ 		delete _pTypes;
/*N*/ 	}
/*N*/ 	delete _pIdPool;
/*N*/ }

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

// registers the availability of the Interface of functions

/*N*/ void SfxSlotPool::RegisterInterface( SfxInterface& rInterface )
/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 
/*N*/ 	// add to the list of SfxObjectInterface instances
/*N*/ 	if ( _pInterfaces == 0 )
/*N*/ 		_pInterfaces = new SfxInterfaceArr_Impl;
/*N*/ 	_pInterfaces->Append(&rInterface);
/*N*/ 
/*N*/ 	// bei einem (einzelnen) Null-Slot abbrechen (aus syntaktischen Gr"unden
/*N*/ 	// enthalten interfaces immer mindestens einen Slot)
/*N*/ 	if ( rInterface.Count() == 1 && !rInterface[0]->nSlotId )
/*N*/ 		return;
/*N*/ 
/*N*/ 	// possibly add Interface-id and group-ids of funcs to the list of groups
/*N*/ 	if ( !_pGroups )
/*N*/ 	{
/*N*/ 		_pGroups = new SfxSlotGroupArr_Impl;
/*N*/ 
/*N*/ 		if ( _pParentPool )
/*N*/ 		{
/*N*/ 			// Die Groups im parent Slotpool sind auch hier bekannt
/*N*/ 			SfxSlotGroupArr_Impl& rGroups = *_pParentPool->_pGroups;
/*N*/ 			for ( USHORT n=0; n<rGroups.Count(); n++ )
/*N*/ 				_pGroups->Append( rGroups[n] );
/*N*/ 		}
/*N*/ 	}
/*N*/ 
/*N*/ 	if ( !_pTypes )
/*N*/ 		_pTypes = new SfxSlotTypeArr_Impl;
/*N*/ 	for ( USHORT nFunc = 0; nFunc < rInterface.Count(); ++nFunc )
/*N*/ 	{
/*N*/ 		SfxSlot *pDef = rInterface[nFunc];
/*N*/ 		if ( pDef->GetGroupId() && /* pDef->GetGroupId() != GID_INTERN && */
/*N*/ 			 !_pGroups->Contains(pDef->GetGroupId()) )
/*N*/ 		{
/*N*/ 			if (pDef->GetGroupId() == GID_INTERN)
/*N*/ 				_pGroups->Insert(0, pDef->GetGroupId());
/*N*/ 			else
/*N*/ 				_pGroups->Append(pDef->GetGroupId());
/*N*/ 		}
/*N*/ #if 0
/*N*/ 		const TypeId &rTypeId = pDef->GetType()->Type();
/*N*/ 		if ( /*rTypeId != TYPE(SfxVoidItem) &&*/ rTypeId != 0 )
/*N*/ 		{
/*N*/ 			USHORT nPos;
/*N*/ 			for ( nPos = 0; nPos < _pTypes->Count(); ++nPos )
/*N*/ 			{
/*N*/ 				if ( _pTypes->GetObject(nPos)->nId == pDef->GetSlotId() )
/*N*/ 				{
/*N*/ 					DBG_ASSERT( rTypeId == _pTypes->GetObject(nPos)->nType,
/*N*/ 								"same slot id with unequal item types" );
/*N*/ 				}
/*N*/ 				else if ( _pTypes->GetObject(nPos)->nId > pDef->GetSlotId() )
/*N*/ 					break;
/*N*/ 			}
/*N*/ 			if ( nPos >= _pTypes->Count() ||
/*N*/ 				 _pTypes->GetObject(nPos)->nId > pDef->GetSlotId() )
/*N*/ 				_pTypes->Append( new SfxSlotType_Impl( pDef->GetSlotId(), rTypeId ) );
/*N*/ 		}
/*N*/ #endif
/*N*/ 	}
/*N*/ }

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

/*N*/ TypeId SfxSlotPool::GetSlotType( USHORT nId ) const
/*N*/ {
/*N*/ 	const SfxSlot* pSlot = (const_cast <SfxSlotPool*> (this))->GetSlot( nId );
/*N*/ 	return pSlot ? pSlot->GetType()->Type() : 0;
/*
	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;
 */
/*N*/ }

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

// unregisters the availability of the Interface of functions

/*N*/ void SfxSlotPool::ReleaseInterface( SfxInterface& rInterface )
/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_ASSERT( _pInterfaces, "releasing SfxInterface, but there are none" );
/*N*/ 	// remove from the list of SfxInterface instances
/*N*/ 	_pInterfaces->Remove(&rInterface);
/*N*/ }

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

// get the first SfxMessage for a special Id (e.g. for getting check-mode)

/*N*/ const SfxSlot* SfxSlotPool::GetSlot( USHORT nId )
/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_ASSERT( _pInterfaces != 0, "no Interfaces registered" );
/*N*/ 
/*N*/ 	// Zun"achst die eigenen Interfaces absuchen
/*N*/ 	for ( USHORT nInterf = 0; nInterf < _pInterfaces->Count(); ++nInterf )
/*N*/ 	{
/*N*/ 		const SfxSlot *pDef = _pInterfaces->GetObject(nInterf)->GetSlot(nId);
/*N*/ 		if ( pDef )
/*N*/ 			return pDef;
/*N*/ 	}
/*N*/ 
/*N*/ 	// Dann beim eventuell vorhandenen parent versuchen
/*N*/ 	return _pParentPool ? _pParentPool->GetSlot( nId ) : 0;
/*N*/ }

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

// returns the pool of unused ids for macros, menus etc.

/*N*/ IdPool& SfxSlotPool::GetIdPool()
/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_ASSERT( _pInterfaces != 0 && _pInterfaces->Count(),
/*N*/ 				"no Interfaces registered" );
/*N*/ 
/*N*/ 	if ( !_pIdPool )
/*N*/ 	{
/*N*/ 		_pIdPool = new IdPool();
/*N*/ 
/*N*/ 		// create a set of all registered function-ids
/*N*/ 		BitSet aRegIds;
/*N*/ 		for ( USHORT nInterface = 0; nInterface < _pInterfaces->Count(); ++nInterface )
/*N*/ 		{
/*N*/ 			SfxInterface* pInterface = (*_pInterfaces)[nInterface];
/*N*/ 			for ( USHORT nFunc = 0; nFunc < pInterface->Count(); ++nFunc )
/*N*/ 				aRegIds |= (*pInterface)[nFunc]->GetGroupId();
/*N*/ 		}
/*N*/ 
/*N*/ 		//lock all registered ids
/*N*/ 		_pIdPool->Lock(aRegIds);
/*N*/ 	}
/*N*/ 
/*N*/ 	return *_pIdPool;
/*N*/ }


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

// stores the id persistent to a stream (expand macros-names)

/*N*/ void SfxSlotPool::StoreId( SvStream& rStream, USHORT nId )
/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_ASSERT( _pInterfaces != 0, "no Interfaces registered" );
/*N*/ 
/*N*/ 	rStream << nId;
/*N*/ 	//! later: write 0 and macro-lib/name
/*N*/ }


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

// load a persistent id from a stream (assign id if a macro)

/*N*/ void SfxSlotPool::LoadId( SvStream& rStream, USHORT &rId )
/*N*/ {
/*N*/ 	DBG_MEMTEST();
/*N*/ 	DBG_ASSERT( _pInterfaces != 0, "no Interfaces registered" );
/*N*/ 
/*N*/ 	rStream >> (unsigned short&) rId;
/*N*/ }


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

// skips to the next group

/*?*/ String SfxSlotPool::SeekGroup( USHORT nNo )
/*?*/ {DBG_BF_ASSERT(0, "STRIP"); return String(); //STRIP001 
/*?*/ }


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

/*N*/ USHORT SfxSlotPool::GetGroupCount()
/*N*/ {
/*N*/ 	return _pGroups->Count();
/*N*/ }


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

// internal search loop

/*?*/ const SfxSlot* SfxSlotPool::SeekSlot( USHORT nStartInterface )
/*?*/ {DBG_BF_ASSERT(0, "STRIP"); //STRIP001 
/*?*/ 	return 0;
/*?*/ }

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

// skips to the next func in the current group

/*N*/ const SfxSlot* SfxSlotPool::NextSlot()
/*N*/ {DBG_BF_ASSERT(0, "STRIP"); return 0;//STRIP001 
/*?*/ }


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

// SlotName erfragen, gfs. mit HilfeText

/*N*/ String SfxSlotPool::GetSlotName_Impl(USHORT nId, String *pHelpText) const
/*N*/ {
/*N*/ 	// ist es eine Makro-SlotId?
/*N*/ 	if ( SfxMacroConfig::IsMacroSlot( nId ) )
/*N*/ 	{
/*?*/ 		const SfxMacroInfo *pMacro = SFX_APP()->GetMacroConfig()->GetMacroInfo(nId);
/*?*/ 		if ( pMacro )
/*?*/ 			return pMacro->GetMacroName();
/*?*/ 		else
/*?*/ 			return String();
/*N*/ 	}
/*N*/ 
/*N*/ 	// Zun"achst den eigenen ResManager testen, dann evtl. den des parent pools
/*N*/ 	ResId aResId( nId, _pResMgr );
/*N*/ 	aResId.SetRT( RSC_SFX_SLOT_INFO );
/*N*/ 	if( !Resource::GetResManager()->IsAvailable( aResId ) && _pParentPool )
/*N*/ 		aResId.SetResMgr( _pParentPool->_pResMgr );
/*N*/ 	if( Resource::GetResManager()->IsAvailable( aResId ) )
/*N*/ 	{
/*N*/ 		SfxSlotInfo aInfo(aResId);
/*N*/ 		if(pHelpText)
/*N*/ 			*pHelpText = aInfo.GetHelpText();
/*N*/ 		return aInfo.GetName();
/*N*/ 	}
/*N*/ 
///*N*/ #ifdef DBG_UTIL
///*N*/ 	String aError(DEFINE_CONST_UNICODE("Slot ohne ConfigName: "));
///*N*/ 	aError += String::CreateFromInt32( nId );
///*N*/ //	DBG_ERROR( aError );
///*N*/ 	return aError;
///*N*/ #endif
/*N*/ 	return String();
/*N*/ }


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

// SlotName erfragen, gfs. mit HilfeText

/*N*/ String SfxSlotPool::GetSlotHelpText_Impl(USHORT nId) const
/*N*/ {
/*N*/ 	String aHelpText;
/*N*/ 	GetSlotName_Impl( nId, &aHelpText );
/*N*/ 	return aHelpText;
/*N*/ }

//--------------------------------------------------------------------
#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

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

/*N*/ SfxInterface* SfxSlotPool::FirstInterface()
/*N*/ {
/*N*/ 	_nCurInterface = 0;
/*N*/ 	if ( !_pInterfaces || !_pInterfaces->Count() )
/*N*/ 		return 0;
/*N*/ 	return _pParentPool ? _pParentPool->FirstInterface() : (*_pInterfaces)[0];
/*N*/ }


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

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

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

/*N*/ USHORT SfxSlotPool::RegisterSID( const String &rGroup, const String &rName )
/*N*/ {
/*N*/ 	return 0;
/*N*/ }

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

/*N*/ void SfxSlotPool::ReleaseSID( const String &rGroup, const String &rName )
/*N*/ {
/*N*/ }

/*?*/ const SfxSlot* SfxSlotPool::GetUnoSlot( const String& rName )
/*?*/ {DBG_BF_ASSERT(0, "STRIP");return 0; //STRIP001 
/*?*/ }



}
