xref: /trunk/main/sfx2/source/control/request.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 
29 // MARKER(update_precomp.py): autogen include statement, do not remove
30 #include "precompiled_sfx2.hxx"
31 
32 #include <com/sun/star/frame/DispatchStatement.hpp>
33 #include <com/sun/star/container/XIndexReplace.hpp>
34 #include <com/sun/star/beans/PropertyValue.hpp>
35 #include <com/sun/star/uno/Sequence.hxx>
36 #include <com/sun/star/beans/XPropertySet.hpp>
37 #include <com/sun/star/util/XURLTransformer.hpp>
38 #include <com/sun/star/frame/XDispatchRecorderSupplier.hpp>
39 #include <svl/itemiter.hxx>
40 
41 #ifndef _ARGS_HXX //autogen
42 #include <svl/itempool.hxx>
43 #endif
44 #include <svtools/itemdel.hxx>
45 
46 #include <comphelper/processfactory.hxx>
47 
48 #ifndef GCC
49 #endif
50 
51 #include <svl/smplhint.hxx>
52 
53 #include <sfx2/request.hxx>
54 #include <sfx2/dispatch.hxx>
55 #include <sfx2/msg.hxx>
56 #include <sfx2/viewfrm.hxx>
57 #include "macro.hxx"
58 #include <sfx2/objface.hxx>
59 #include <sfx2/appuno.hxx>
60 
61 //===================================================================
62 
63 using namespace ::com::sun::star;
64 
65 struct SfxRequest_Impl: public SfxListener
66 
67 /* 	[Beschreibung]
68 
69 	Implementations-Struktur der Klasse <SfxRequest>.
70 */
71 
72 {
73 	SfxRequest*			pAnti;		 // Owner wegen sterbendem Pool
74 	String				aTarget;	 // ggf. von App gesetztes Zielobjekt
75 	SfxItemPool*        pPool;		 // ItemSet mit diesem Pool bauen
76 	SfxPoolItem*		pRetVal;	 // R"uckgabewert geh"ort sich selbst
77     SfxShell*           pShell;      // ausgef"uhrt an dieser Shell
78 	const SfxSlot*		pSlot;		 // ausgef"uhrter Slot
79 	sal_uInt16              nModifier;   // welche Modifier waren gedrueckt?
80 	sal_Bool				bDone;		 // "uberhaupt ausgef"uhrt
81 	sal_Bool				bIgnored;	 // vom User abgebrochen
82 	sal_Bool				bCancelled;	 // nicht mehr zustellen
83 	sal_Bool				bUseTarget;	 // aTarget wurde von Applikation gesetzt
84 	sal_uInt16  			nCallMode;   // Synch/Asynch/API/Record
85     sal_Bool                bAllowRecording;
86 	SfxAllItemSet*      pInternalArgs;
87     SfxViewFrame*       pViewFrame;
88 
89     com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > xRecorder;
90 
91 						SfxRequest_Impl( SfxRequest *pOwner )
92 						: pAnti( pOwner)
93 						, pPool(0)
94 						, nModifier(0)
95 						, bCancelled(sal_False)
96 						, nCallMode( SFX_CALLMODE_SYNCHRON )
97 						, bAllowRecording( sal_False )
98 						, pInternalArgs( 0 )
99 						, pViewFrame(0)
100 						{}
101 	~SfxRequest_Impl() { delete pInternalArgs; }
102 
103 
104 	void				SetPool( SfxItemPool *pNewPool );
105 	virtual void		Notify( SfxBroadcaster &rBC, const SfxHint &rHint );
106     void                Record( const uno::Sequence < beans::PropertyValue >& rArgs );
107 };
108 
109 
110 //====================================================================
111 
112 void SfxRequest_Impl::Notify( SfxBroadcaster&, const SfxHint &rHint )
113 {
114 	SfxSimpleHint *pSimpleHint = PTR_CAST(SfxSimpleHint, &rHint);
115 	if ( pSimpleHint && pSimpleHint->GetId() == SFX_HINT_DYING )
116 		pAnti->Cancel();
117 }
118 
119 //====================================================================
120 
121 void SfxRequest_Impl::SetPool( SfxItemPool *pNewPool )
122 {
123 	if ( pNewPool != pPool )
124 	{
125 		if ( pPool )
126 			EndListening( pPool->BC() );
127 		pPool = pNewPool;
128 		if ( pNewPool )
129 			StartListening( pNewPool->BC() );
130 	}
131 }
132 
133 //====================================================================
134 
135 
136 SfxRequest::~SfxRequest()
137 {
138 	DBG_MEMTEST();
139 
140 	// nicht mit Done() marktierte Requests mit 'rem' rausschreiben
141 	if ( pImp->xRecorder.is() && !pImp->bDone && !pImp->bIgnored )
142         pImp->Record( uno::Sequence < beans::PropertyValue >() );
143 
144 	// Objekt abr"aumen
145 	delete pArgs;
146 	if ( pImp->pRetVal )
147 		DeleteItemOnIdle(pImp->pRetVal);
148 	delete pImp;
149 }
150 //--------------------------------------------------------------------
151 
152 
153 SfxRequest::SfxRequest
154 (
155 	const SfxRequest& rOrig
156 )
157 :	SfxHint( rOrig ),
158     nSlot(rOrig.nSlot),
159 	pArgs(rOrig.pArgs? new SfxAllItemSet(*rOrig.pArgs): 0),
160 	pImp( new SfxRequest_Impl(this) )
161 {
162 	DBG_MEMTEST();
163 
164     pImp->bAllowRecording = rOrig.pImp->bAllowRecording;
165     pImp->bDone = sal_False;
166 	pImp->bIgnored = sal_False;
167 	pImp->pRetVal = 0;
168 	pImp->pShell = 0;
169 	pImp->pSlot = 0;
170 	pImp->nCallMode = rOrig.pImp->nCallMode;
171 	pImp->bUseTarget = rOrig.pImp->bUseTarget;
172 	pImp->aTarget = rOrig.pImp->aTarget;
173 	pImp->nModifier = rOrig.pImp->nModifier;
174 
175     // deep copy needed !
176     pImp->pInternalArgs = (rOrig.pImp->pInternalArgs ? new SfxAllItemSet(*rOrig.pImp->pInternalArgs) : 0);
177 
178 	if ( pArgs )
179 		pImp->SetPool( pArgs->GetPool() );
180 	else
181 		pImp->SetPool( rOrig.pImp->pPool );
182 }
183 //--------------------------------------------------------------------
184 
185 
186 SfxRequest::SfxRequest
187 (
188     SfxViewFrame*   pViewFrame,
189     sal_uInt16          nSlotId
190 
191 )
192 
193 /*	[Beschreibung]
194 
195 	Mit diesem Konstruktor k"onnen Events, die nicht "uber den SfxDispatcher
196 	gelaufen sind (z.B aus KeyInput() oder Mouse-Events) nachtr"aglich
197 	recorded werden. Dazu wird eine SfxRequest-Instanz mit diesem Konstruktor
198 	erzeugt und dann genauso verfahren, wie mit einem SfxRequest, der in
199 	eine <Slot-Execute-Methode> als Parameter gegeben wird.
200 */
201 
202 :	nSlot(nSlotId),
203 	pArgs(0),
204 	pImp( new SfxRequest_Impl(this) )
205 {
206 	DBG_MEMTEST();
207 
208 	pImp->bDone = sal_False;
209 	pImp->bIgnored = sal_False;
210     pImp->SetPool( &pViewFrame->GetPool() );
211 	pImp->pRetVal = 0;
212 	pImp->pShell = 0;
213     pImp->pSlot = 0;
214 	pImp->nCallMode = SFX_CALLMODE_SYNCHRON;
215 	pImp->bUseTarget = sal_False;
216     pImp->pViewFrame = pViewFrame;
217     if( pImp->pViewFrame->GetDispatcher()->GetShellAndSlot_Impl( nSlotId, &pImp->pShell, &pImp->pSlot, sal_True, sal_True ) )
218     {
219         pImp->SetPool( &pImp->pShell->GetPool() );
220         pImp->xRecorder = SfxRequest::GetMacroRecorder( pViewFrame );
221         pImp->aTarget = pImp->pShell->GetName();
222     }
223 #ifdef DBG_UTIL
224     else
225     {
226         ByteString aStr( "Recording unsupported slot: ");
227         aStr += ByteString::CreateFromInt32( pImp->pPool->GetSlotId(nSlotId) );
228         DBG_ERROR( aStr.GetBuffer() );
229     }
230 #endif
231 }
232 
233 //--------------------------------------------------------------------
234 
235 
236 SfxRequest::SfxRequest
237 (
238 	sal_uInt16 			nSlotId, 	// auszuf"uhrende <Slot-Id>
239 	SfxCallMode 	nMode,		// Synch/API/...
240 	SfxItemPool&	rPool 		// ggf. f"ur das SfxItemSet f"ur Parameter
241 )
242 
243 // creates a SfxRequest without arguments
244 
245 :	nSlot(nSlotId),
246 	pArgs(0),
247 	pImp( new SfxRequest_Impl(this) )
248 {
249 	DBG_MEMTEST();
250 
251 	pImp->bDone = sal_False;
252 	pImp->bIgnored = sal_False;
253 	pImp->SetPool( &rPool );
254 	pImp->pRetVal = 0;
255 	pImp->pShell = 0;
256 	pImp->pSlot = 0;
257 	pImp->nCallMode = nMode;
258 	pImp->bUseTarget = sal_False;
259 }
260 
261 SfxRequest::SfxRequest
262 (
263 	const SfxSlot* pSlot, 	// auszuf"uhrende <Slot-Id>
264 	const com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue >& rArgs,
265 	SfxCallMode 	nMode,		// Synch/API/...
266 	SfxItemPool&	rPool 		// ggf. f"ur das SfxItemSet f"ur Parameter
267 )
268 :	nSlot(pSlot->GetSlotId()),
269 	pArgs(new SfxAllItemSet(rPool)),
270 	pImp( new SfxRequest_Impl(this) )
271 {
272 	DBG_MEMTEST();
273 
274 	pImp->bDone = sal_False;
275 	pImp->bIgnored = sal_False;
276 	pImp->SetPool( &rPool );
277 	pImp->pRetVal = 0;
278 	pImp->pShell = 0;
279 	pImp->pSlot = 0;
280 	pImp->nCallMode = nMode;
281 	pImp->bUseTarget = sal_False;
282 	TransformParameters( nSlot, rArgs, *pArgs, pSlot );
283 }
284 
285 //-----------------------------------------------------------------------
286 
287 SfxRequest::SfxRequest
288 (
289 	sal_uInt16 					nSlotId,
290 	sal_uInt16					nMode,
291 	const SfxAllItemSet&	rSfxArgs
292 )
293 
294 // creates a SfxRequest with arguments
295 
296 :	nSlot(nSlotId),
297 	pArgs(new SfxAllItemSet(rSfxArgs)),
298 	pImp( new SfxRequest_Impl(this) )
299 {
300 	DBG_MEMTEST();
301 
302 	pImp->bDone = sal_False;
303 	pImp->bIgnored = sal_False;
304 	pImp->SetPool( rSfxArgs.GetPool() );
305 	pImp->pRetVal = 0;
306 	pImp->pShell = 0;
307 	pImp->pSlot = 0;
308 	pImp->nCallMode = nMode;
309 	pImp->bUseTarget = sal_False;
310 }
311 //--------------------------------------------------------------------
312 
313 sal_uInt16 SfxRequest::GetCallMode() const
314 {
315 	return pImp->nCallMode;
316 }
317 
318 //--------------------------------------------------------------------
319 
320 sal_Bool SfxRequest::IsSynchronCall() const
321 {
322 	return SFX_CALLMODE_SYNCHRON == ( SFX_CALLMODE_SYNCHRON & pImp->nCallMode );
323 }
324 
325 //--------------------------------------------------------------------
326 
327 void SfxRequest::SetSynchronCall( sal_Bool bSynchron )
328 {
329 	if ( bSynchron )
330 		pImp->nCallMode |= SFX_CALLMODE_SYNCHRON;
331 	else
332 		pImp->nCallMode &= ~(sal_uInt16) SFX_CALLMODE_SYNCHRON;
333 }
334 
335 void SfxRequest::SetInternalArgs_Impl( const SfxAllItemSet& rArgs )
336 {
337 	delete pImp->pInternalArgs;
338 	pImp->pInternalArgs = new SfxAllItemSet( rArgs );
339 }
340 
341 const SfxItemSet* SfxRequest::GetInternalArgs_Impl() const
342 {
343 	return pImp->pInternalArgs;
344 }
345 
346 //--------------------------------------------------------------------
347 
348 
349 void SfxRequest_Impl::Record
350 (
351     const uno::Sequence < beans::PropertyValue >& rArgs    // aktuelle Parameter
352 )
353 
354 /*	[Beschreibung]
355 
356 	Interne Hilfsmethode zum erzeugen einer <SfxMacroStatement>-Instanz,
357 	welche den bereits ausgef"uhrten SfxRequest wiederholbar beschreibt.
358 
359 	Die erzeugte Instanz, auf die ein Pointer zur"uckgeliefert wird
360 	geht in das Eigentum des Aufrufers "uber.
361 */
362 
363 {
364     String aCommand = String::CreateFromAscii(".uno:");
365     aCommand.AppendAscii( pSlot->GetUnoName() );
366 	::rtl::OUString aCmd( aCommand );
367     if(xRecorder.is())
368     {
369 		uno::Reference< container::XIndexReplace > xReplace( xRecorder, uno::UNO_QUERY );
370 		if ( xReplace.is() && aCmd.compareToAscii(".uno:InsertText") == COMPARE_EQUAL )
371 		{
372 			sal_Int32 nCount = xReplace->getCount();
373 			if ( nCount )
374 			{
375 				frame::DispatchStatement aStatement;
376 				uno::Any aElement = xReplace->getByIndex(nCount-1);
377 				if ( (aElement >>= aStatement) && aStatement.aCommand == aCmd )
378 				{
379 					::rtl::OUString aStr;
380 					::rtl::OUString aNew;
381 		            aStatement.aArgs[0].Value >>= aStr;
382 					rArgs[0].Value >>= aNew;
383 					aStr += aNew;
384 		            aStatement.aArgs[0].Value <<= aStr;
385 					aElement <<= aStatement;
386 					xReplace->replaceByIndex( nCount-1, aElement );
387 					return;
388 				}
389 			}
390 		}
391 
392         com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > xFactory(
393                 ::comphelper::getProcessServiceFactory(),
394                 com::sun::star::uno::UNO_QUERY);
395 
396         com::sun::star::uno::Reference< com::sun::star::util::XURLTransformer > xTransform(
397                 xFactory->createInstance(rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer")),
398                 com::sun::star::uno::UNO_QUERY);
399 
400         com::sun::star::util::URL aURL;
401         aURL.Complete = aCmd;
402         xTransform->parseStrict(aURL);
403 
404         if (bDone)
405             xRecorder->recordDispatch(aURL,rArgs);
406         else
407             xRecorder->recordDispatchAsComment(aURL,rArgs);
408     }
409 }
410 
411 //--------------------------------------------------------------------
412 
413 void SfxRequest::Record_Impl
414 (
415     SfxShell& rSh,    // die <SfxShell>, die den Request ausgef"uhrt hat
416 	const SfxSlot&	rSlot, 	// der <SfxSlot>, der den Request ausgef"uhrt hat
417     com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > xRecorder,  // der Recorder, mit dem aufgezeichnet wird
418     SfxViewFrame* pViewFrame
419 )
420 
421 /*	[Beschreibung]
422 
423 	Diese interne Methode markiert den SfxRequest als in dem angegebenen
424 	SfxMakro aufzuzeichnen.
425 
426 	Pointer auf die Parameter werden in Done() wieder verwendet, m"usseb
427 	dann also noch leben.
428 */
429 
430 {
431 	DBG_MEMTEST();
432 	pImp->pShell = &rSh;
433 	pImp->pSlot = &rSlot;
434     pImp->xRecorder = xRecorder;
435 	pImp->aTarget = rSh.GetName();
436     pImp->pViewFrame = pViewFrame;
437 }
438 
439 //--------------------------------------------------------------------
440 
441 void SfxRequest::SetArgs( const SfxAllItemSet& rArgs )
442 {
443 	delete pArgs;
444 	pArgs = new SfxAllItemSet(rArgs);
445 	pImp->SetPool( pArgs->GetPool() );
446 }
447 
448 //--------------------------------------------------------------------
449 
450 void SfxRequest::AppendItem(const SfxPoolItem &rItem)
451 {
452 	if(!pArgs)
453 		pArgs = new SfxAllItemSet(*pImp->pPool);
454 	pArgs->Put(rItem, rItem.Which());
455 }
456 
457 //--------------------------------------------------------------------
458 
459 void SfxRequest::RemoveItem( sal_uInt16 nID )
460 {
461 	if (pArgs)
462 	{
463 		pArgs->ClearItem(nID);
464 		if ( !pArgs->Count() )
465 			DELETEZ(pArgs);
466 	}
467 }
468 
469 //--------------------------------------------------------------------
470 
471 const SfxPoolItem* SfxRequest::GetArg
472 (
473 	sal_uInt16 			nSlotId, 	// Slot-Id oder Which-Id des Parameters
474 	bool 		bDeep,	 	// false: nicht in Parent-ItemSets suchen
475 	TypeId			aType		// != 0:  RTTI Pruefung mit Assertion
476 ) 	const
477 {
478 	return GetItem( pArgs, nSlotId, bDeep, aType );
479 }
480 
481 
482 //--------------------------------------------------------------------
483 const SfxPoolItem* SfxRequest::GetItem
484 (
485 	const SfxItemSet* pArgs,
486 	sal_uInt16 			nSlotId, 	// Slot-Id oder Which-Id des Parameters
487 	bool    		bDeep,	 	// false: nicht in Parent-ItemSets suchen
488 	TypeId			aType		// != 0:  RTTI Pruefung mit Assertion
489 )
490 
491 /*	[Beschreibung]
492 
493 	Mit dieser Methode wird der Zugriff auf einzelne Parameter im
494 	SfxRequest wesentlich vereinfacht. Insbesondere wird die Typpr"ufung
495 	(per Assertion) durchgef"uhrt, wodurch die Applikations-Sourcen
496 	wesentlich "ubersichtlicher werden. In der PRODUCT-Version wird
497 	eine 0 zur"uckgegeben, wenn das gefundene Item nicht von der
498 	angegebenen Klasse ist.
499 
500 
501 	[Beispiel]
502 
503 	void MyShell::Execute( SfxRequest &rReq )
504 	{
505 		switch ( rReq.GetSlot() )
506 		{
507 			case SID_MY:
508 			{
509 				...
510 				// ein Beispiel ohne Verwendung des Makros
511 				const SfxInt32Item *pPosItem = (const SfxUInt32Item*)
512 					rReq.GetArg( SID_POS, sal_False, TYPE(SfxInt32Item) );
513 				sal_uInt16 nPos = pPosItem ? pPosItem->GetValue() : 0;
514 
515 				// ein Beispiel mit Verwendung des Makros
516 				SFX_REQUEST_ARG(rReq, pSizeItem, SfxInt32Item, SID_SIZE, sal_False);
517 				sal_uInt16 nSize = pSizeItem ? pPosItem->GetValue() : 0;
518 
519 				...
520 			}
521 
522 			...
523 		}
524 	}
525 */
526 
527 {
528 	if ( pArgs )
529 	{
530 		// ggf. in Which-Id umrechnen
531 		sal_uInt16 nWhich = pArgs->GetPool()->GetWhich(nSlotId);
532 
533 		// ist das Item gesetzt oder bei bDeep==TRUE verf"ugbar?
534 		const SfxPoolItem *pItem = 0;
535 		if ( ( bDeep ? SFX_ITEM_AVAILABLE : SFX_ITEM_SET )
536 			 <= pArgs->GetItemState( nWhich, bDeep, &pItem ) )
537 		{
538 			// stimmt der Typ "uberein?
539 			if ( !pItem || pItem->IsA(aType) )
540 				return pItem;
541 
542 			// Item da aber falsch => Programmierfehler
543 			DBG_ERROR(  "invalid argument type" );
544 		}
545 	}
546 
547 	// keine Parameter, nicht gefunden oder falschen Typ gefunden
548 	return 0;
549 }
550 
551 //--------------------------------------------------------------------
552 
553 void SfxRequest::SetReturnValue(const SfxPoolItem &rItem)
554 {
555 	DBG_ASSERT(!pImp->pRetVal, "Returnwert mehrfach setzen?");
556 	if(pImp->pRetVal)
557 		delete pImp->pRetVal;
558 	pImp->pRetVal = rItem.Clone();
559 }
560 
561 //--------------------------------------------------------------------
562 
563 const SfxPoolItem* SfxRequest::GetReturnValue() const
564 {
565 	return pImp->pRetVal;
566 }
567 
568 //--------------------------------------------------------------------
569 
570 void SfxRequest::Done
571 (
572 	const SfxItemSet&	rSet,   /* 	von der Applikation mitgeteilte Parameter,
573 									die z.B. in einem Dialog vom Benuter
574 									erfragt wurden, ggf. 0 falls keine
575 									Parameter gesetzt wurden */
576 
577 	bool 			bKeep	/*  true (default)
578 									'rSet' wird gepeichert und ist "uber
579 									GetArgs() abfragbar
580 
581 									false
582 									'rSet' wird nicht kopiert (schneller) */
583 )
584 
585 /*	[Beschreibung]
586 
587 	Diese Methode mu\s in der <Execute-Methode> des <SfxSlot>s gerufen
588 	werden, der den SfxRequest ausgef"uhrt hat, wenn die Ausf"uhrung
589 	tats"achlich stattgefunden hat. Wird 'Done()' nicht gerufen, gilt
590 	der SfxRequest als abgebrochen.
591 
592 	Etwaige Returnwerte werden nur durchgereicht, wenn 'Done()' gerufen
593 	wurde. Ebenso werden beim Aufzeichnen von Makros nur echte
594 	Statements erzeugt, wenn 'Done()' gerufen wurde; f"ur SfxRequests,
595 	die nicht derart gekennzeichnet wurden, wird anstelle dessen eine
596 	auf die abgebrochene Funktion hinweisende Bemerkung ('rem') eingf"ugt.
597 
598 
599 	[Anmerkung]
600 
601 	'Done()' wird z.B. nicht gerufen, wenn ein durch die Funktion gestarteter
602 	Dialog vom Benutzer	abgebrochen wurde oder das Ausf"uhren aufgrund
603 	eines falschen Kontextes (ohne Verwendung separater <SfxShell>s)
604 	nicht durchgef"uhrt werden konnte. 'Done()' mu\s sehr wohl gerufen
605 	werden, wenn das Ausf"uhren der Funktion zu einem regul"aren Fehler
606 	f"uhrte (z.B. Datei konnte nicht ge"offnet werden).
607 */
608 
609 {
610 	Done_Impl( &rSet );
611 
612 	// ggf. Items merken, damit StarDraw sie abfragen kann
613 	if ( bKeep )
614 	{
615 		if ( !pArgs )
616 		{
617 			pArgs = new SfxAllItemSet( rSet );
618 			pImp->SetPool( pArgs->GetPool() );
619 		}
620 		else
621 		{
622 			SfxItemIter aIter(rSet);
623 			const SfxPoolItem* pItem = aIter.FirstItem();
624 			while(pItem)
625 			{
626 				if(!IsInvalidItem(pItem))
627 					pArgs->Put(*pItem,pItem->Which());
628 				pItem = aIter.NextItem();
629 			}
630 		}
631 	}
632 }
633 
634 //--------------------------------------------------------------------
635 
636 
637 void SfxRequest::Done( sal_Bool bRelease )
638 //	[<SfxRequest::Done(SfxItemSet&)>]
639 {
640 	Done_Impl( pArgs );
641 	if( bRelease )
642 		DELETEZ( pArgs );
643 }
644 
645 //--------------------------------------------------------------------
646 
647 void SfxRequest::ForgetAllArgs()
648 {
649     DELETEZ( pArgs );
650     DELETEZ( pImp->pInternalArgs );
651 }
652 
653 //--------------------------------------------------------------------
654 
655 sal_Bool SfxRequest::IsCancelled() const
656 {
657 	return pImp->bCancelled;
658 }
659 
660 //--------------------------------------------------------------------
661 
662 void SfxRequest::Cancel()
663 
664 /*	[Beschreibung]
665 
666 	Markiert diesen Request als nicht mehr auszufuehren. Wird z.B. gerufen,
667 	wenn das Ziel (genauer dessen Pool) stirbt.
668 */
669 
670 {
671 	pImp->bCancelled = sal_True;
672 	pImp->SetPool( 0 );
673 	DELETEZ( pArgs );
674 }
675 
676 //--------------------------------------------------------------------
677 
678 
679 void SfxRequest::Ignore()
680 
681 /*	[Beschreibung]
682 
683 	Wird diese Methode anstelle von <SfxRequest::Done()> gerufen, dann
684 	wird dieser Request nicht recorded.
685 
686 
687 	[Bespiel]
688 
689 	Das Selektieren von Tools im StarDraw soll nicht aufgezeichnet werden,
690 	dieselben Slots sollen aber zum erzeugen der von den Tools zu
691 	erzeugenden Objekte verwendet werde. Also kann nicht NoRecord
692 	angegeben werden, dennoch soll u.U. nicht aufgezeichnet werden.
693 */
694 
695 {
696 	// als tats"achlich ausgef"uhrt markieren
697 	pImp->bIgnored = sal_True;
698 }
699 
700 //--------------------------------------------------------------------
701 
702 void SfxRequest::Done_Impl
703 (
704 	const SfxItemSet*	pSet	/* 	von der Applikation mitgeteilte Parameter,
705 									die z.B. in einem Dialog vom Benuter
706 									erfragt wurden, ggf. 0 falls keine
707 									Parameter gesetzt wurden */
708 )
709 
710 /*	[Beschreibung]
711 
712 	Interne Methode zum als 'done' markieren des SfxRequest und zum Auswerten
713     der Parameter in 'pSet' falls aufgezeichnet wird.
714 */
715 
716 {
717 	// als tats"achlich ausgef"uhrt markieren
718 	pImp->bDone = sal_True;
719 
720 	// nicht Recorden
721 	if ( !pImp->xRecorder.is() )
722 		return;
723 
724 	// wurde ein anderer Slot ausgef"uhrt als angefordert (Delegation)
725 	if ( nSlot != pImp->pSlot->GetSlotId() )
726 	{
727 		// Slot neu suchen
728 		pImp->pSlot = pImp->pShell->GetInterface()->GetSlot(nSlot);
729 		DBG_ASSERT( pImp->pSlot, "delegated SlotId not found" );
730 		if ( !pImp->pSlot ) // Hosentr"ger und G"urtel
731 			return;
732 	}
733 
734 	// record-f"ahig?
735     // neues Recorden verwendet UnoName!
736     if ( !pImp->pSlot->pUnoName )
737     {
738         ByteString aStr( "Recording not exported slot: ");
739         aStr += ByteString::CreateFromInt32( pImp->pSlot->GetSlotId() );
740         DBG_ERROR( aStr.GetBuffer() );
741     }
742 
743     if ( !pImp->pSlot->pUnoName ) // Hosentr"ger und G"urtel
744         return;
745 
746 	// "ofters ben"otigte Werte
747 	SfxItemPool &rPool = pImp->pShell->GetPool();
748 
749 	// Property-Slot?
750 	if ( !pImp->pSlot->IsMode(SFX_SLOT_METHOD) )
751 	{
752 		// des Property als SfxPoolItem besorgen
753 		const SfxPoolItem *pItem;
754 		sal_uInt16 nWhich = rPool.GetWhich(pImp->pSlot->GetSlotId());
755         SfxItemState eState = pSet ? pSet->GetItemState( nWhich, sal_False, &pItem ) : SFX_ITEM_UNKNOWN;
756 #ifdef DBG_UTIL
757         if ( SFX_ITEM_SET != eState )
758         {
759             ByteString aStr( "Recording property not available: ");
760             aStr += ByteString::CreateFromInt32( pImp->pSlot->GetSlotId() );
761             DBG_ERROR( aStr.GetBuffer() );
762         }
763 #endif
764         uno::Sequence < beans::PropertyValue > aSeq;
765 		if ( eState == SFX_ITEM_SET )
766             TransformItems( pImp->pSlot->GetSlotId(), *pSet, aSeq, pImp->pSlot );
767         pImp->Record( aSeq );
768 	}
769 
770 	// alles in ein einziges Statement aufzeichnen?
771 	else if ( pImp->pSlot->IsMode(SFX_SLOT_RECORDPERSET) )
772 	{
773         uno::Sequence < beans::PropertyValue > aSeq;
774         if ( pSet )
775             TransformItems( pImp->pSlot->GetSlotId(), *pSet, aSeq, pImp->pSlot );
776         pImp->Record( aSeq );
777 	}
778 
779 	// jedes Item als einzelnes Statement recorden
780 	else if ( pImp->pSlot->IsMode(SFX_SLOT_RECORDPERITEM) )
781 	{
782 		if ( pSet )
783 		{
784 			// "uber die Items iterieren
785 			SfxItemIter aIter(*pSet);
786             for ( const SfxPoolItem* pItem = aIter.FirstItem(); pItem; pItem = aIter.NextItem() )
787 			{
788 				// die Slot-Id f"ur das einzelne Item ermitteln
789 				sal_uInt16 nSlotId = rPool.GetSlotId( pItem->Which() );
790 				if ( nSlotId == nSlot )
791 				{
792 					// mit Hosentr"ager und G"urtel reparieren des falschen Flags
793 					DBG_ERROR( "recursion RecordPerItem - use RecordPerSet!" );
794 					SfxSlot *pSlot = (SfxSlot*) pImp->pSlot;
795 					pSlot->nFlags &= ~((sal_uIntPtr)SFX_SLOT_RECORDPERITEM);
796 					pSlot->nFlags &=  SFX_SLOT_RECORDPERSET;
797 				}
798 
799 				// einen Sub-Request recorden
800                 SfxRequest aReq( pImp->pViewFrame, nSlotId );
801                 if ( aReq.pImp->pSlot )
802                     aReq.AppendItem( *pItem );
803                 aReq.Done();
804 			}
805 		}
806 		else
807 		{
808 			HACK(hierueber nochmal nachdenken)
809             pImp->Record( uno::Sequence < beans::PropertyValue >() );
810 		}
811 	}
812 }
813 
814 //--------------------------------------------------------------------
815 
816 sal_Bool SfxRequest::IsDone() const
817 
818 /*	[Beschreibung]
819 
820 	Mit dieser Methode kann abgefragt werden, ob der SfxRequest tats"achlich
821 	ausgef"uhrt wurde oder nicht. Wurde ein SfxRequest nicht ausgef"uhrt,
822 	liegt dies z.B. daran, da\s der Benutzer abgebrochen hat oder
823 	der Kontext f"ur diesen Request falsch war, dieses aber nicht "uber
824 	eine separate <SfxShell> realisiert wurde.
825 
826 	SfxRequest-Instanzen, die hier sal_False liefern, werden nicht recorded.
827 
828 
829 	[Querverweise]
830 
831 	<SfxRequest::Done(const SfxItemSet&)>
832 	<SfxRequest::Done()>
833 */
834 
835 {
836 	return pImp->bDone;
837 }
838 
839 //--------------------------------------------------------------------
840 
841 SfxMacro* SfxRequest::GetRecordingMacro()
842 
843 /*	[Beschreibung]
844 
845 	Mit dieser Methode kann abgefragt werden, ob und in welchem <SfxMacro>
846 	die SfxRequests gerade aufgezeichnet werden.
847 */
848 
849 {
850     return NULL;
851 }
852 
853 //--------------------------------------------------------------------
854 
855 com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > SfxRequest::GetMacroRecorder( SfxViewFrame* pView )
856 
857 /*  [Beschreibung]
858 
859     Hier wird versucht einen Recorder fuer dispatch() Aufrufe vom Frame zu bekommen.
860     Dieser ist dort per Property an einem Supplier verfuegbar - aber nur dann, wenn
861     recording angeschaltet wurde.
862     (Siehe auch SfxViewFrame::MiscExec_Impl() und SID_RECORDING)
863 */
864 
865 {
866     com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > xRecorder;
867 
868     com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet > xSet(
869         (pView ? pView : SfxViewFrame::Current())->GetFrame().GetFrameInterface(),
870         com::sun::star::uno::UNO_QUERY);
871 
872     if(xSet.is())
873     {
874         com::sun::star::uno::Any aProp = xSet->getPropertyValue(rtl::OUString::createFromAscii("DispatchRecorderSupplier"));
875         com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorderSupplier > xSupplier;
876         aProp >>= xSupplier;
877         if(xSupplier.is())
878             xRecorder = xSupplier->getDispatchRecorder();
879     }
880 
881     return xRecorder;
882 }
883 
884 sal_Bool SfxRequest::HasMacroRecorder( SfxViewFrame* pView )
885 {
886     return GetMacroRecorder( pView ).is();
887 }
888 
889 
890 //--------------------------------------------------------------------
891 
892 sal_Bool SfxRequest::IsAPI() const
893 
894 /*	[Beschreibung]
895 
896 	Liefert sal_True, wenn dieser SfxRequest von einer API (z.B. BASIC)
897 	erzeugt wurde, sonst sal_False.
898 */
899 
900 {
901 	return SFX_CALLMODE_API == ( SFX_CALLMODE_API & pImp->nCallMode );
902 }
903 
904 //--------------------------------------------------------------------
905 
906 
907 bool SfxRequest::IsRecording() const
908 
909 /*	[Beschreibung]
910 
911 	Liefert sal_True, wenn dieser SfxRequest recorded werden soll, d.h.
912 	1. zu Zeit ein Makro aufgezeichnet wird
913 	2. dieser Request "uberhaupt aufgezeichnet wird
914 	3. der Request nicht von reiner API (z.B. BASIC) ausgeht,
915 	sonst sal_False.
916 */
917 
918 {
919     return ( AllowsRecording() && GetMacroRecorder().is() );
920 }
921 
922 //--------------------------------------------------------------------
923 void SfxRequest::SetModifier( sal_uInt16 nModi )
924 {
925 	pImp->nModifier = nModi;
926 }
927 
928 //--------------------------------------------------------------------
929 sal_uInt16 SfxRequest::GetModifier() const
930 {
931 	return pImp->nModifier;
932 }
933 
934 //--------------------------------------------------------------------
935 
936 void SfxRequest::SetTarget( const String &rTarget )
937 
938 /*	[Beschreibung]
939 
940 	Mit dieser Methode kann das zu recordende Zielobjekt umgesetzt werden.
941 
942 
943 	[Beispiel]
944 
945 	Die BASIC-Methode 'Open' wird zwar von der Shell 'Application' ausgef"uhrt,
946 	aber am Objekt 'Documents' (global) recorded:
947 
948 		rReq.SetTarget( "Documents" );
949 
950 	Dies f"uhrt dann zu:
951 
952 		Documents.Open( ... )
953 */
954 
955 {
956 	pImp->aTarget = rTarget;
957 	pImp->bUseTarget = sal_True;
958 }
959 
960 void SfxRequest::AllowRecording( sal_Bool bSet )
961 {
962     pImp->bAllowRecording = bSet;
963 }
964 
965 sal_Bool SfxRequest::AllowsRecording() const
966 {
967     sal_Bool bAllow = pImp->bAllowRecording;
968     if( !bAllow )
969         bAllow = ( SFX_CALLMODE_API != ( SFX_CALLMODE_API & pImp->nCallMode ) ) &&
970                  ( SFX_CALLMODE_RECORD == ( SFX_CALLMODE_RECORD & pImp->nCallMode ) );
971     return bAllow;
972 }
973 
974 void SfxRequest::ReleaseArgs()
975 {
976     DELETEZ( pArgs );
977     DELETEZ( pImp->pInternalArgs );
978 }
979