/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/




// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sfx2.hxx"

#include <com/sun/star/frame/DispatchStatement.hpp>
#include <com/sun/star/container/XIndexReplace.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/uno/Sequence.hxx>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/util/XURLTransformer.hpp>
#include <com/sun/star/frame/XDispatchRecorderSupplier.hpp>
#include <svl/itemiter.hxx>

#ifndef _ARGS_HXX //autogen
#include <svl/itempool.hxx>
#endif
#include <svtools/itemdel.hxx>

#include <comphelper/processfactory.hxx>

#ifndef GCC
#endif

#include <svl/smplhint.hxx>

#include <sfx2/request.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/msg.hxx>
#include <sfx2/viewfrm.hxx>
#include "macro.hxx"
#include <sfx2/objface.hxx>
#include <sfx2/appuno.hxx>

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

using namespace ::com::sun::star;

struct SfxRequest_Impl: public SfxListener

/* 	[Beschreibung]

	Implementations-Struktur der Klasse <SfxRequest>.
*/

{
	SfxRequest*			pAnti;		 // Owner wegen sterbendem Pool
	String				aTarget;	 // ggf. von App gesetztes Zielobjekt
	SfxItemPool*        pPool;		 // ItemSet mit diesem Pool bauen
	SfxPoolItem*		pRetVal;	 // R"uckgabewert geh"ort sich selbst
    SfxShell*           pShell;      // ausgef"uhrt an dieser Shell
	const SfxSlot*		pSlot;		 // ausgef"uhrter Slot
	sal_uInt16              nModifier;   // welche Modifier waren gedrueckt?
	sal_Bool				bDone;		 // "uberhaupt ausgef"uhrt
	sal_Bool				bIgnored;	 // vom User abgebrochen
	sal_Bool				bCancelled;	 // nicht mehr zustellen
	sal_Bool				bUseTarget;	 // aTarget wurde von Applikation gesetzt
	sal_uInt16  			nCallMode;   // Synch/Asynch/API/Record
    sal_Bool                bAllowRecording;
	SfxAllItemSet*      pInternalArgs;
    SfxViewFrame*       pViewFrame;

    com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > xRecorder;

						SfxRequest_Impl( SfxRequest *pOwner )
						: pAnti( pOwner)
						, pPool(0)
						, nModifier(0)
						, bCancelled(sal_False)
						, nCallMode( SFX_CALLMODE_SYNCHRON )
						, bAllowRecording( sal_False )
						, pInternalArgs( 0 )
						, pViewFrame(0)
						{}
	~SfxRequest_Impl() { delete pInternalArgs; }


	void				SetPool( SfxItemPool *pNewPool );
	virtual void		Notify( SfxBroadcaster &rBC, const SfxHint &rHint );
    void                Record( const uno::Sequence < beans::PropertyValue >& rArgs );
};


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

void SfxRequest_Impl::Notify( SfxBroadcaster&, const SfxHint &rHint )
{
	SfxSimpleHint *pSimpleHint = PTR_CAST(SfxSimpleHint, &rHint);
	if ( pSimpleHint && pSimpleHint->GetId() == SFX_HINT_DYING )
		pAnti->Cancel();
}

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

void SfxRequest_Impl::SetPool( SfxItemPool *pNewPool )
{
	if ( pNewPool != pPool )
	{
		if ( pPool )
			EndListening( pPool->BC() );
		pPool = pNewPool;
		if ( pNewPool )
			StartListening( pNewPool->BC() );
	}
}

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


SfxRequest::~SfxRequest()
{
	DBG_MEMTEST();

	// nicht mit Done() marktierte Requests mit 'rem' rausschreiben
	if ( pImp->xRecorder.is() && !pImp->bDone && !pImp->bIgnored )
        pImp->Record( uno::Sequence < beans::PropertyValue >() );

	// Objekt abr"aumen
	delete pArgs;
	if ( pImp->pRetVal )
		DeleteItemOnIdle(pImp->pRetVal);
	delete pImp;
}
//--------------------------------------------------------------------


SfxRequest::SfxRequest
(
	const SfxRequest& rOrig
)
:	SfxHint( rOrig ),
    nSlot(rOrig.nSlot),
	pArgs(rOrig.pArgs? new SfxAllItemSet(*rOrig.pArgs): 0),
	pImp( new SfxRequest_Impl(this) )
{
	DBG_MEMTEST();

    pImp->bAllowRecording = rOrig.pImp->bAllowRecording;
    pImp->bDone = sal_False;
	pImp->bIgnored = sal_False;
	pImp->pRetVal = 0;
	pImp->pShell = 0;
	pImp->pSlot = 0;
	pImp->nCallMode = rOrig.pImp->nCallMode;
	pImp->bUseTarget = rOrig.pImp->bUseTarget;
	pImp->aTarget = rOrig.pImp->aTarget;
	pImp->nModifier = rOrig.pImp->nModifier;

    // deep copy needed !
    pImp->pInternalArgs = (rOrig.pImp->pInternalArgs ? new SfxAllItemSet(*rOrig.pImp->pInternalArgs) : 0);

	if ( pArgs )
		pImp->SetPool( pArgs->GetPool() );
	else
		pImp->SetPool( rOrig.pImp->pPool );
}
//--------------------------------------------------------------------


SfxRequest::SfxRequest
(
    SfxViewFrame*   pViewFrame,
    sal_uInt16          nSlotId

)

/*	[Beschreibung]

	Mit diesem Konstruktor k"onnen Events, die nicht "uber den SfxDispatcher
	gelaufen sind (z.B aus KeyInput() oder Mouse-Events) nachtr"aglich
	recorded werden. Dazu wird eine SfxRequest-Instanz mit diesem Konstruktor
	erzeugt und dann genauso verfahren, wie mit einem SfxRequest, der in
	eine <Slot-Execute-Methode> als Parameter gegeben wird.
*/

:	nSlot(nSlotId),
	pArgs(0),
	pImp( new SfxRequest_Impl(this) )
{
	DBG_MEMTEST();

	pImp->bDone = sal_False;
	pImp->bIgnored = sal_False;
    pImp->SetPool( &pViewFrame->GetPool() );
	pImp->pRetVal = 0;
	pImp->pShell = 0;
    pImp->pSlot = 0;
	pImp->nCallMode = SFX_CALLMODE_SYNCHRON;
	pImp->bUseTarget = sal_False;
    pImp->pViewFrame = pViewFrame;
    if( pImp->pViewFrame->GetDispatcher()->GetShellAndSlot_Impl( nSlotId, &pImp->pShell, &pImp->pSlot, sal_True, sal_True ) )
    {
        pImp->SetPool( &pImp->pShell->GetPool() );
        pImp->xRecorder = SfxRequest::GetMacroRecorder( pViewFrame );
        pImp->aTarget = pImp->pShell->GetName();
    }
#ifdef DBG_UTIL
    else
    {
        ByteString aStr( "Recording unsupported slot: ");
        aStr += ByteString::CreateFromInt32( pImp->pPool->GetSlotId(nSlotId) );
        DBG_ERROR( aStr.GetBuffer() );
    }
#endif
}

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


SfxRequest::SfxRequest
(
	sal_uInt16 			nSlotId, 	// auszuf"uhrende <Slot-Id>
	SfxCallMode 	nMode,		// Synch/API/...
	SfxItemPool&	rPool 		// ggf. f"ur das SfxItemSet f"ur Parameter
)

// creates a SfxRequest without arguments

:	nSlot(nSlotId),
	pArgs(0),
	pImp( new SfxRequest_Impl(this) )
{
	DBG_MEMTEST();

	pImp->bDone = sal_False;
	pImp->bIgnored = sal_False;
	pImp->SetPool( &rPool );
	pImp->pRetVal = 0;
	pImp->pShell = 0;
	pImp->pSlot = 0;
	pImp->nCallMode = nMode;
	pImp->bUseTarget = sal_False;
}

SfxRequest::SfxRequest
(
	const SfxSlot* pSlot, 	// auszuf"uhrende <Slot-Id>
	const com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue >& rArgs,
	SfxCallMode 	nMode,		// Synch/API/...
	SfxItemPool&	rPool 		// ggf. f"ur das SfxItemSet f"ur Parameter
)
:	nSlot(pSlot->GetSlotId()),
	pArgs(new SfxAllItemSet(rPool)),
	pImp( new SfxRequest_Impl(this) )
{
	DBG_MEMTEST();

	pImp->bDone = sal_False;
	pImp->bIgnored = sal_False;
	pImp->SetPool( &rPool );
	pImp->pRetVal = 0;
	pImp->pShell = 0;
	pImp->pSlot = 0;
	pImp->nCallMode = nMode;
	pImp->bUseTarget = sal_False;
	TransformParameters( nSlot, rArgs, *pArgs, pSlot );
}

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

SfxRequest::SfxRequest
(
	sal_uInt16 					nSlotId,
	sal_uInt16					nMode,
	const SfxAllItemSet&	rSfxArgs
)

// creates a SfxRequest with arguments

:	nSlot(nSlotId),
	pArgs(new SfxAllItemSet(rSfxArgs)),
	pImp( new SfxRequest_Impl(this) )
{
	DBG_MEMTEST();

	pImp->bDone = sal_False;
	pImp->bIgnored = sal_False;
	pImp->SetPool( rSfxArgs.GetPool() );
	pImp->pRetVal = 0;
	pImp->pShell = 0;
	pImp->pSlot = 0;
	pImp->nCallMode = nMode;
	pImp->bUseTarget = sal_False;
}
//--------------------------------------------------------------------

sal_uInt16 SfxRequest::GetCallMode() const
{
	return pImp->nCallMode;
}

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

sal_Bool SfxRequest::IsSynchronCall() const
{
	return SFX_CALLMODE_SYNCHRON == ( SFX_CALLMODE_SYNCHRON & pImp->nCallMode );
}

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

void SfxRequest::SetSynchronCall( sal_Bool bSynchron )
{
	if ( bSynchron )
		pImp->nCallMode |= SFX_CALLMODE_SYNCHRON;
	else
		pImp->nCallMode &= ~(sal_uInt16) SFX_CALLMODE_SYNCHRON;
}

void SfxRequest::SetInternalArgs_Impl( const SfxAllItemSet& rArgs )
{
	delete pImp->pInternalArgs;
	pImp->pInternalArgs = new SfxAllItemSet( rArgs );
}

const SfxItemSet* SfxRequest::GetInternalArgs_Impl() const
{
	return pImp->pInternalArgs;
}

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


void SfxRequest_Impl::Record
(
    const uno::Sequence < beans::PropertyValue >& rArgs    // aktuelle Parameter
)

/*	[Beschreibung]

	Interne Hilfsmethode zum erzeugen einer <SfxMacroStatement>-Instanz,
	welche den bereits ausgef"uhrten SfxRequest wiederholbar beschreibt.

	Die erzeugte Instanz, auf die ein Pointer zur"uckgeliefert wird
	geht in das Eigentum des Aufrufers "uber.
*/

{
    String aCommand = String::CreateFromAscii(".uno:");
    aCommand.AppendAscii( pSlot->GetUnoName() );
	::rtl::OUString aCmd( aCommand );
    if(xRecorder.is())
    {
		uno::Reference< container::XIndexReplace > xReplace( xRecorder, uno::UNO_QUERY );
		if ( xReplace.is() && aCmd.compareToAscii(".uno:InsertText") == COMPARE_EQUAL )
		{
			sal_Int32 nCount = xReplace->getCount();
			if ( nCount )
			{
				frame::DispatchStatement aStatement;
				uno::Any aElement = xReplace->getByIndex(nCount-1);
				if ( (aElement >>= aStatement) && aStatement.aCommand == aCmd )
				{
					::rtl::OUString aStr;
					::rtl::OUString aNew;
		            aStatement.aArgs[0].Value >>= aStr;
					rArgs[0].Value >>= aNew;
					aStr += aNew;
		            aStatement.aArgs[0].Value <<= aStr;
					aElement <<= aStatement;
					xReplace->replaceByIndex( nCount-1, aElement );
					return;
				}
			}
		}

        com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > xFactory(
                ::comphelper::getProcessServiceFactory(),
                com::sun::star::uno::UNO_QUERY);

        com::sun::star::uno::Reference< com::sun::star::util::XURLTransformer > xTransform(
                xFactory->createInstance(rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer")),
                com::sun::star::uno::UNO_QUERY);

        com::sun::star::util::URL aURL;
        aURL.Complete = aCmd;
        xTransform->parseStrict(aURL);

        if (bDone)
            xRecorder->recordDispatch(aURL,rArgs);
        else
            xRecorder->recordDispatchAsComment(aURL,rArgs);
    }
}

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

void SfxRequest::Record_Impl
(
    SfxShell& rSh,    // die <SfxShell>, die den Request ausgef"uhrt hat
	const SfxSlot&	rSlot, 	// der <SfxSlot>, der den Request ausgef"uhrt hat
    com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > xRecorder,  // der Recorder, mit dem aufgezeichnet wird
    SfxViewFrame* pViewFrame
)

/*	[Beschreibung]

	Diese interne Methode markiert den SfxRequest als in dem angegebenen
	SfxMakro aufzuzeichnen.

	Pointer auf die Parameter werden in Done() wieder verwendet, m"usseb
	dann also noch leben.
*/

{
	DBG_MEMTEST();
	pImp->pShell = &rSh;
	pImp->pSlot = &rSlot;
    pImp->xRecorder = xRecorder;
	pImp->aTarget = rSh.GetName();
    pImp->pViewFrame = pViewFrame;
}

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

void SfxRequest::SetArgs( const SfxAllItemSet& rArgs )
{
	delete pArgs;
	pArgs = new SfxAllItemSet(rArgs);
	pImp->SetPool( pArgs->GetPool() );
}

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

void SfxRequest::AppendItem(const SfxPoolItem &rItem)
{
	if(!pArgs)
		pArgs = new SfxAllItemSet(*pImp->pPool);
	pArgs->Put(rItem, rItem.Which());
}

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

void SfxRequest::RemoveItem( sal_uInt16 nID )
{
	if (pArgs)
	{
		pArgs->ClearItem(nID);
		if ( !pArgs->Count() )
			DELETEZ(pArgs);
	}
}

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

const SfxPoolItem* SfxRequest::GetArg
(
	sal_uInt16 			nSlotId, 	// Slot-Id oder Which-Id des Parameters
	bool 		bDeep,	 	// false: nicht in Parent-ItemSets suchen
	TypeId			aType		// != 0:  RTTI Pruefung mit Assertion
) 	const
{
	return GetItem( pArgs, nSlotId, bDeep, aType );
}


//--------------------------------------------------------------------
const SfxPoolItem* SfxRequest::GetItem
(
	const SfxItemSet* pArgs,
	sal_uInt16 			nSlotId, 	// Slot-Id oder Which-Id des Parameters
	bool    		bDeep,	 	// false: nicht in Parent-ItemSets suchen
	TypeId			aType		// != 0:  RTTI Pruefung mit Assertion
)

/*	[Beschreibung]

	Mit dieser Methode wird der Zugriff auf einzelne Parameter im
	SfxRequest wesentlich vereinfacht. Insbesondere wird die Typpr"ufung
	(per Assertion) durchgef"uhrt, wodurch die Applikations-Sourcen
	wesentlich "ubersichtlicher werden. In der PRODUCT-Version wird
	eine 0 zur"uckgegeben, wenn das gefundene Item nicht von der
	angegebenen Klasse ist.


	[Beispiel]

	void MyShell::Execute( SfxRequest &rReq )
	{
		switch ( rReq.GetSlot() )
		{
			case SID_MY:
			{
				...
				// ein Beispiel ohne Verwendung des Makros
				const SfxInt32Item *pPosItem = (const SfxUInt32Item*)
					rReq.GetArg( SID_POS, sal_False, TYPE(SfxInt32Item) );
				sal_uInt16 nPos = pPosItem ? pPosItem->GetValue() : 0;

				// ein Beispiel mit Verwendung des Makros
				SFX_REQUEST_ARG(rReq, pSizeItem, SfxInt32Item, SID_SIZE, sal_False);
				sal_uInt16 nSize = pSizeItem ? pPosItem->GetValue() : 0;

				...
			}

			...
		}
	}
*/

{
	if ( pArgs )
	{
		// ggf. in Which-Id umrechnen
		sal_uInt16 nWhich = pArgs->GetPool()->GetWhich(nSlotId);

		// ist das Item gesetzt oder bei bDeep==TRUE verf"ugbar?
		const SfxPoolItem *pItem = 0;
		if ( ( bDeep ? SFX_ITEM_AVAILABLE : SFX_ITEM_SET )
			 <= pArgs->GetItemState( nWhich, bDeep, &pItem ) )
		{
			// stimmt der Typ "uberein?
			if ( !pItem || pItem->IsA(aType) )
				return pItem;

			// Item da aber falsch => Programmierfehler
			DBG_ERROR(  "invalid argument type" );
		}
	}

	// keine Parameter, nicht gefunden oder falschen Typ gefunden
	return 0;
}

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

void SfxRequest::SetReturnValue(const SfxPoolItem &rItem)
{
	DBG_ASSERT(!pImp->pRetVal, "Returnwert mehrfach setzen?");
	if(pImp->pRetVal)
		delete pImp->pRetVal;
	pImp->pRetVal = rItem.Clone();
}

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

const SfxPoolItem* SfxRequest::GetReturnValue() const
{
	return pImp->pRetVal;
}

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

void SfxRequest::Done
(
	const SfxItemSet&	rSet,   /* 	von der Applikation mitgeteilte Parameter,
									die z.B. in einem Dialog vom Benuter
									erfragt wurden, ggf. 0 falls keine
									Parameter gesetzt wurden */

	bool 			bKeep	/*  true (default)
									'rSet' wird gepeichert und ist "uber
									GetArgs() abfragbar

									false
									'rSet' wird nicht kopiert (schneller) */
)

/*	[Beschreibung]

	Diese Methode mu\s in der <Execute-Methode> des <SfxSlot>s gerufen
	werden, der den SfxRequest ausgef"uhrt hat, wenn die Ausf"uhrung
	tats"achlich stattgefunden hat. Wird 'Done()' nicht gerufen, gilt
	der SfxRequest als abgebrochen.

	Etwaige Returnwerte werden nur durchgereicht, wenn 'Done()' gerufen
	wurde. Ebenso werden beim Aufzeichnen von Makros nur echte
	Statements erzeugt, wenn 'Done()' gerufen wurde; f"ur SfxRequests,
	die nicht derart gekennzeichnet wurden, wird anstelle dessen eine
	auf die abgebrochene Funktion hinweisende Bemerkung ('rem') eingf"ugt.


	[Anmerkung]

	'Done()' wird z.B. nicht gerufen, wenn ein durch die Funktion gestarteter
	Dialog vom Benutzer	abgebrochen wurde oder das Ausf"uhren aufgrund
	eines falschen Kontextes (ohne Verwendung separater <SfxShell>s)
	nicht durchgef"uhrt werden konnte. 'Done()' mu\s sehr wohl gerufen
	werden, wenn das Ausf"uhren der Funktion zu einem regul"aren Fehler
	f"uhrte (z.B. Datei konnte nicht ge"offnet werden).
*/

{
	Done_Impl( &rSet );

	// ggf. Items merken, damit StarDraw sie abfragen kann
	if ( bKeep )
	{
		if ( !pArgs )
		{
			pArgs = new SfxAllItemSet( rSet );
			pImp->SetPool( pArgs->GetPool() );
		}
		else
		{
			SfxItemIter aIter(rSet);
			const SfxPoolItem* pItem = aIter.FirstItem();
			while(pItem)
			{
				if(!IsInvalidItem(pItem))
					pArgs->Put(*pItem,pItem->Which());
				pItem = aIter.NextItem();
			}
		}
	}
}

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


void SfxRequest::Done( sal_Bool bRelease )
//	[<SfxRequest::Done(SfxItemSet&)>]
{
	Done_Impl( pArgs );
	if( bRelease )
		DELETEZ( pArgs );
}

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

void SfxRequest::ForgetAllArgs()
{
    DELETEZ( pArgs );
    DELETEZ( pImp->pInternalArgs );
}

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

sal_Bool SfxRequest::IsCancelled() const
{
	return pImp->bCancelled;
}

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

void SfxRequest::Cancel()

/*	[Beschreibung]

	Markiert diesen Request als nicht mehr auszufuehren. Wird z.B. gerufen,
	wenn das Ziel (genauer dessen Pool) stirbt.
*/

{
	pImp->bCancelled = sal_True;
	pImp->SetPool( 0 );
	DELETEZ( pArgs );
}

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


void SfxRequest::Ignore()

/*	[Beschreibung]

	Wird diese Methode anstelle von <SfxRequest::Done()> gerufen, dann
	wird dieser Request nicht recorded.


	[Bespiel]

	Das Selektieren von Tools im StarDraw soll nicht aufgezeichnet werden,
	dieselben Slots sollen aber zum erzeugen der von den Tools zu
	erzeugenden Objekte verwendet werde. Also kann nicht NoRecord
	angegeben werden, dennoch soll u.U. nicht aufgezeichnet werden.
*/

{
	// als tats"achlich ausgef"uhrt markieren
	pImp->bIgnored = sal_True;
}

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

void SfxRequest::Done_Impl
(
	const SfxItemSet*	pSet	/* 	von der Applikation mitgeteilte Parameter,
									die z.B. in einem Dialog vom Benuter
									erfragt wurden, ggf. 0 falls keine
									Parameter gesetzt wurden */
)

/*	[Beschreibung]

	Interne Methode zum als 'done' markieren des SfxRequest und zum Auswerten
    der Parameter in 'pSet' falls aufgezeichnet wird.
*/

{
	// als tats"achlich ausgef"uhrt markieren
	pImp->bDone = sal_True;

	// nicht Recorden
	if ( !pImp->xRecorder.is() )
		return;

	// wurde ein anderer Slot ausgef"uhrt als angefordert (Delegation)
	if ( nSlot != pImp->pSlot->GetSlotId() )
	{
		// Slot neu suchen
		pImp->pSlot = pImp->pShell->GetInterface()->GetSlot(nSlot);
		DBG_ASSERT( pImp->pSlot, "delegated SlotId not found" );
		if ( !pImp->pSlot ) // Hosentr"ger und G"urtel
			return;
	}

	// record-f"ahig?
    // neues Recorden verwendet UnoName!
    if ( !pImp->pSlot->pUnoName )
    {
        ByteString aStr( "Recording not exported slot: ");
        aStr += ByteString::CreateFromInt32( pImp->pSlot->GetSlotId() );
        DBG_ERROR( aStr.GetBuffer() );
    }

    if ( !pImp->pSlot->pUnoName ) // Hosentr"ger und G"urtel
        return;

	// "ofters ben"otigte Werte
	SfxItemPool &rPool = pImp->pShell->GetPool();

	// Property-Slot?
	if ( !pImp->pSlot->IsMode(SFX_SLOT_METHOD) )
	{
		// des Property als SfxPoolItem besorgen
		const SfxPoolItem *pItem;
		sal_uInt16 nWhich = rPool.GetWhich(pImp->pSlot->GetSlotId());
        SfxItemState eState = pSet ? pSet->GetItemState( nWhich, sal_False, &pItem ) : SFX_ITEM_UNKNOWN;
#ifdef DBG_UTIL
        if ( SFX_ITEM_SET != eState )
        {
            ByteString aStr( "Recording property not available: ");
            aStr += ByteString::CreateFromInt32( pImp->pSlot->GetSlotId() );
            DBG_ERROR( aStr.GetBuffer() );
        }
#endif
        uno::Sequence < beans::PropertyValue > aSeq;
		if ( eState == SFX_ITEM_SET )
            TransformItems( pImp->pSlot->GetSlotId(), *pSet, aSeq, pImp->pSlot );
        pImp->Record( aSeq );
	}

	// alles in ein einziges Statement aufzeichnen?
	else if ( pImp->pSlot->IsMode(SFX_SLOT_RECORDPERSET) )
	{
        uno::Sequence < beans::PropertyValue > aSeq;
        if ( pSet )
            TransformItems( pImp->pSlot->GetSlotId(), *pSet, aSeq, pImp->pSlot );
        pImp->Record( aSeq );
	}

	// jedes Item als einzelnes Statement recorden
	else if ( pImp->pSlot->IsMode(SFX_SLOT_RECORDPERITEM) )
	{
		if ( pSet )
		{
			// "uber die Items iterieren
			SfxItemIter aIter(*pSet);
            for ( const SfxPoolItem* pItem = aIter.FirstItem(); pItem; pItem = aIter.NextItem() )
			{
				// die Slot-Id f"ur das einzelne Item ermitteln
				sal_uInt16 nSlotId = rPool.GetSlotId( pItem->Which() );
				if ( nSlotId == nSlot )
				{
					// mit Hosentr"ager und G"urtel reparieren des falschen Flags
					DBG_ERROR( "recursion RecordPerItem - use RecordPerSet!" );
					SfxSlot *pSlot = (SfxSlot*) pImp->pSlot;
					pSlot->nFlags &= ~((sal_uIntPtr)SFX_SLOT_RECORDPERITEM);
					pSlot->nFlags &=  SFX_SLOT_RECORDPERSET;
				}

				// einen Sub-Request recorden
                SfxRequest aReq( pImp->pViewFrame, nSlotId );
                if ( aReq.pImp->pSlot )
                    aReq.AppendItem( *pItem );
                aReq.Done();
			}
		}
		else
		{
			HACK(hierueber nochmal nachdenken)
            pImp->Record( uno::Sequence < beans::PropertyValue >() );
		}
	}
}

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

sal_Bool SfxRequest::IsDone() const

/*	[Beschreibung]

	Mit dieser Methode kann abgefragt werden, ob der SfxRequest tats"achlich
	ausgef"uhrt wurde oder nicht. Wurde ein SfxRequest nicht ausgef"uhrt,
	liegt dies z.B. daran, da\s der Benutzer abgebrochen hat oder
	der Kontext f"ur diesen Request falsch war, dieses aber nicht "uber
	eine separate <SfxShell> realisiert wurde.

	SfxRequest-Instanzen, die hier sal_False liefern, werden nicht recorded.


	[Querverweise]

	<SfxRequest::Done(const SfxItemSet&)>
	<SfxRequest::Done()>
*/

{
	return pImp->bDone;
}

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

SfxMacro* SfxRequest::GetRecordingMacro()

/*	[Beschreibung]

	Mit dieser Methode kann abgefragt werden, ob und in welchem <SfxMacro>
	die SfxRequests gerade aufgezeichnet werden.
*/

{
    return NULL;
}

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

com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > SfxRequest::GetMacroRecorder( SfxViewFrame* pView )

/*  [Beschreibung]

    Hier wird versucht einen Recorder fuer dispatch() Aufrufe vom Frame zu bekommen.
    Dieser ist dort per Property an einem Supplier verfuegbar - aber nur dann, wenn
    recording angeschaltet wurde.
    (Siehe auch SfxViewFrame::MiscExec_Impl() und SID_RECORDING)
*/

{
    com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > xRecorder;

    com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet > xSet(
        (pView ? pView : SfxViewFrame::Current())->GetFrame().GetFrameInterface(),
        com::sun::star::uno::UNO_QUERY);

    if(xSet.is())
    {
        com::sun::star::uno::Any aProp = xSet->getPropertyValue(rtl::OUString::createFromAscii("DispatchRecorderSupplier"));
        com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorderSupplier > xSupplier;
        aProp >>= xSupplier;
        if(xSupplier.is())
            xRecorder = xSupplier->getDispatchRecorder();
    }

    return xRecorder;
}

sal_Bool SfxRequest::HasMacroRecorder( SfxViewFrame* pView )
{
    return GetMacroRecorder( pView ).is();
}


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

sal_Bool SfxRequest::IsAPI() const

/*	[Beschreibung]

	Liefert sal_True, wenn dieser SfxRequest von einer API (z.B. BASIC)
	erzeugt wurde, sonst sal_False.
*/

{
	return SFX_CALLMODE_API == ( SFX_CALLMODE_API & pImp->nCallMode );
}

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


bool SfxRequest::IsRecording() const

/*	[Beschreibung]

	Liefert sal_True, wenn dieser SfxRequest recorded werden soll, d.h.
	1. zu Zeit ein Makro aufgezeichnet wird
	2. dieser Request "uberhaupt aufgezeichnet wird
	3. der Request nicht von reiner API (z.B. BASIC) ausgeht,
	sonst sal_False.
*/

{
    return ( AllowsRecording() && GetMacroRecorder().is() );
}

//--------------------------------------------------------------------
void SfxRequest::SetModifier( sal_uInt16 nModi )
{
	pImp->nModifier = nModi;
}

//--------------------------------------------------------------------
sal_uInt16 SfxRequest::GetModifier() const
{
	return pImp->nModifier;
}

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

void SfxRequest::SetTarget( const String &rTarget )

/*	[Beschreibung]

	Mit dieser Methode kann das zu recordende Zielobjekt umgesetzt werden.


	[Beispiel]

	Die BASIC-Methode 'Open' wird zwar von der Shell 'Application' ausgef"uhrt,
	aber am Objekt 'Documents' (global) recorded:

		rReq.SetTarget( "Documents" );

	Dies f"uhrt dann zu:

		Documents.Open( ... )
*/

{
	pImp->aTarget = rTarget;
	pImp->bUseTarget = sal_True;
}

void SfxRequest::AllowRecording( sal_Bool bSet )
{
    pImp->bAllowRecording = bSet;
}

sal_Bool SfxRequest::AllowsRecording() const
{
    sal_Bool bAllow = pImp->bAllowRecording;
    if( !bAllow )
        bAllow = ( SFX_CALLMODE_API != ( SFX_CALLMODE_API & pImp->nCallMode ) ) &&
                 ( SFX_CALLMODE_RECORD == ( SFX_CALLMODE_RECORD & pImp->nCallMode ) );
    return bAllow;
}

void SfxRequest::ReleaseArgs()
{
    DELETEZ( pArgs );
    DELETEZ( pImp->pInternalArgs );
}
