xref: /aoo41x/main/sfx2/source/control/macro.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 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sfx2.hxx"
30 
31 #if OSL_DEBUG_LEVEL > 1
32 #include <tools/stream.hxx>
33 #endif
34 
35 #include "macro.hxx"
36 #include <sfx2/request.hxx>
37 #include <sfx2/msg.hxx>
38 
39 //====================================================================
40 
41 SV_DECL_PTRARR_DEL( SfxStatements_Impl, SfxMacroStatement*, 16, 8 )
42 SV_IMPL_PTRARR( SfxStatements_Impl, SfxMacroStatement* );
43 
44 //--------------------------------------------------------------------
45 
46 struct SfxMacro_Impl
47 
48 /*	[Beschreibung]
49 
50 	Implementations-Struktur der Klasse <SfxMacro>.
51 */
52 
53 {
54 	SfxMacroMode		eMode;	/*	Zweck der <SfxMacro>-Instanz,
55 									Bedeutung siehe enum <SfxMacroMode> */
56 	SfxStatements_Impl	aList;  /* 	Liste von aufgezeichneten Statements */
57 };
58 
59 //====================================================================
60 
61 SfxMacroStatement::SfxMacroStatement
62 (
63 	const SfxShell& /*rShell*/,		// <SfxShell>, die den Request ausf"uhrte
64 	const String&	/*rTarget*/,	// Name des Zielobjektes vor der Ausf"urhung
65 	sal_Bool			/*bAbsolute*/,	// obsolet
66 	const SfxSlot&	rSlot,			// der <SfxSlot>, der das Statement abspielen kann
67 	sal_Bool			bRequestDone,	// wurde der Request tats"achlich ausgef"uhrt
68     ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue >& rArgs
69 )
70 
71 /* 	[Beschreibung]
72 
73 	Dieser Konstruktor der Klasse SfxMacroStatement erzeugt ein Statement,
74 	bei dem ein Objekt angesprochen wird, welches durch 'rShell' angegeben
75 	ist. Dabei erfolgt die Addressierung je nach 'bAbsolute' absolut,
76 	also z.B. als '[mydoc.sdc]' oder relativ, also z.B. 'ActiveDocument'.
77 
78 	Je nach Art der Subklasse von 'rShell' ergeben sich folgende
79 	Ausdr"ucke:
80 
81                           | absolut                  relativ
82 	-----------------------------------------------------------------------
83 	SfxApplication'       | 'StarCalc'  			'Application'
84     SfxViewFrame'         | '[mydoc.sdc:1]'         'ActiveWindow'
85 	SfxViewShell'         | '[mydoc.sdc:1]'         'AvtiveWindow'
86 	SfxObjectShell'       | '[mydoc.sdc]'           'ActiveDocument'
87 	sonstige (Sub-Shells) | '[mydoc.sdc:1]'			'ActiveWindow'
88 
89     Dabei sind 'StarCalc' stellvertretend fuer den Namen der Applikation
90 	(Application::GetAppName()const). In der absoluten Fassung k"onnte
91 	die Selektion auch deskriptiv z.B. als 'CellSelection("A5-D8")')
92 	angesprochen werden, dazu mu\ jedoch vom Anwendungsprogrammierer der
93 	Konstruktor <SfxMacroStatement::SfxMacroStatement(const String&,
94 	const SfxSlot&,sal_Bool,SfxArguments*)> verwendet werden.
95 
96 	F"ur das so bezeichnete Objekt wird dann je nach Typ des Slots
97 	eine Zuweisung an eines seiner Properties oder der Aufruf einer seiner
98 	Methoden ausgedr"uckt.
99 
100 
101 	[Beispiele]
102 
103 	absolut:
104 	SCalc3.OpenDocument( "\docs\mydoc.sdd", "StarDraw Presentation", 0, 0 )
105 	[mydoc.sdd].Activate()
106 	[mydoc.sdd:1].SwitchToView( 2 )
107 	[mydoc.sdc:1:1].CellSelection( "A5-D8" ).LineColor = 192357
108 
109 	relativ:
110 	ActiveWindow.LineColor = 192357
111 
112 
113 	[Querverweise]
114 
115 	<SfxMacroStatement::SfxMacroStatement(const String&,const SfxSlot&,sal_Bool,SfxArguments*)>
116 	<SfxMacroStatement::SfxMacroStatement(const String&)>
117 */
118 
119 :	nSlotId( rSlot.GetSlotId() ),
120     aArgs( rArgs ),
121 	bDone( bRequestDone ),
122 	pDummy( 0 )
123 {
124 	// Workaround Recording nicht exportierter Slots (#25386#)
125 	if ( !rSlot.pName )
126 		return;
127 /*
128 	// Objekt-Typ bestimmen
129 	bool bIsApp = rShell.ISA(SfxApplication);
130 	bool bIsDoc = rShell.ISA(SfxObjectShell);
131 	bool bIsWin = !bIsApp && !bIsDoc &&
132 					  ( rShell.ISA(SfxViewShell) || rShell.ISA(SfxViewFrame) );
133 	bool bIsSel = !bIsApp && !bIsDoc && !bIsWin;
134 
135 	// Objekt nicht schon im Slot-Namen enthalten?
136 	if ( bIsSel || rSlot.pName[0] == '.' )
137 	{
138 		// absolutes Aufzeichnen?
139 		if ( rSlot.IsMode( SFX_SLOT_RECORDABSOLUTE ) )
140 		{
141 			// an der Applikation oder am Modul
142 			if ( rShell.ISA(SfxApplication) || rShell.ISA(SfxModule) )
143 				aStatement = rTarget;
144 
145 			// am Dokument?
146 			// '[' = 5Bh
147 			// ']' = 5Dh
148 			else if ( rShell.ISA(SfxObjectShell) )
149 			{
150 				aStatement = 0x005B;
151 				aStatement += rTarget;
152 				aStatement += 0x005D;
153 			}
154 
155 			else if ( rShell.ISA(SfxViewFrame) )
156 			{
157 				aStatement = 0x005B;
158                 aStatement += String::CreateFromAscii("ViewFrame");//rShell.GetSbxObject()->GetName();
159 				aStatement += 0x005D;
160 			}
161 
162 			else
163 			{
164 				// an der View oder Sub-Shell
165 				SfxViewShell *pViewShell = rShell.GetViewShell();
166 				aStatement = 0x005B;
167                 aStatement += String::CreateFromAscii("ViewShell");//pViewShell->GetViewFrame()->GetSbxObject()->GetName();
168 				aStatement += 0x005D;
169 				if ( !rShell.ISA(SfxViewFrame) )
170                     // an einer Sub-Shell zus"atlich ".Selection" anh"angen
171 					aStatement += DEFINE_CONST_UNICODE(".Selection");
172 			}
173 		}
174 		else // relatives Aufzeichnen
175 		{
176 			// an der Application?
177 			if ( rShell.ISA(SfxApplication) )
178 				aStatement = DEFINE_CONST_UNICODE("Application");
179 
180 			// am Modul?
181 			else if ( rShell.ISA(SfxModule) )
182 				aStatement = DEFINE_CONST_UNICODE("ActiveModule");
183 
184 			// am Dokument
185 			else if ( rShell.ISA(SfxObjectShell) )
186 				aStatement = DEFINE_CONST_UNICODE("ActiveDocument");
187 
188 			// am Window
189 			else if ( rShell.ISA(SfxViewShell) || rShell.ISA(SfxViewFrame) )
190 				aStatement = DEFINE_CONST_UNICODE("ActiveWindow");
191 
192 			else
193 				// an einer Sub-Shell
194 				aStatement = DEFINE_CONST_UNICODE("Selection");
195 		}
196 	}
197 
198 	if ( bIsSel )
199 	{
200 		// bei Selection ggf. noch den Namen der SubShell anh"angen
201 		const SfxShellObject *pShObj =
202 					(const SfxShellObject*) rShell.GetSbxObject();
203 		if ( pShObj )
204 		{
205 			const SfxShellObject *pParentObj =
206 						(const SfxShellObject*) pShObj->GetParent();
207 			SfxShell *pParentSh = pParentObj->GetShell();
208 			DBG_ASSERT( pParentSh->ISA(SfxViewFrame),
209 						"parent of SubShell must be a Frame" );
210 			if ( rSlot.pName[0] == '.' )
211 			{
212 				aStatement += '.';
213 				aStatement += rShell.GetSbxObject()->GetName();
214 			}
215 		}
216 		else
217 			DBG_ASSERT( rSlot.pName[0] != '0', "recording unnamed object" );
218 	}
219 */
220     aStatement = DEFINE_CONST_UNICODE("Selection");
221 
222 	// an diesen Objekt-Ausdruck den Methoden-/Property-Namen und Parameter
223     GenerateNameAndArgs_Impl( SfxRequest::GetRecordingMacro(), rSlot, bRequestDone, aArgs);
224 }
225 
226 //--------------------------------------------------------------------
227 
228 SfxMacroStatement::SfxMacroStatement
229 (
230 	const String&   rTarget,		// Objekt, was beim Playing angesprochen wird
231 	const SfxSlot&	rSlot,			// der <SfxSlot>, der das Statement abspielen kann
232 	sal_Bool			bRequestDone,	// wurde der Request tats"achlich ausgef"uhrt
233     ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue >& rArgs
234 )
235 
236 /* 	[Beschreibung]
237 
238 
239 	[Querverweise]
240 
241 	<SfxMacroStatement::SfxMacroStatement(const String&)>
242 	<SfxMacroStatement::SfxMacroStatement(const SfxShell&,sal_Bool,const SfxSlot&,sal_Bool,SfxArguments*)>
243 */
244 
245 :	nSlotId( rSlot.GetSlotId() ),
246     aArgs( rArgs ),
247 	bDone( bRequestDone ),
248 	pDummy( 0 )
249 {
250 	aStatement = rTarget;
251 	aStatement += '.';
252     GenerateNameAndArgs_Impl( SfxRequest::GetRecordingMacro(), rSlot, bRequestDone, aArgs);
253 }
254 
255 //--------------------------------------------------------------------
256 
257 SfxMacroStatement::SfxMacroStatement
258 (
259 	const String&   rStatement  	// manuell erzeugte(s) Statement(s)
260 )
261 
262 /* 	[Beschreibung]
263 
264 	Dieser Konstruktor erzeugt eine SfxMacroStatement-Instanz, deren
265 	Aufbau vollst"andig vom Applikationsentwickler bestimmt wird. Da der
266 	angegebene String auch mehrere mit CR/LF getrennte Statements
267 	enthalten darf, ist damit ein weitgehender Eingriff in das Aufzeichnen
268 	von BASIC-Makros m"oglich, um Spezialf"alle zu behandeln.
269 
270 
271 	[Querverweise]
272 
273 	<SfxMacroStatement::SfxMacroStatement(const String&,const SfxSlot&,sal_Bool,SfxArguments*)>
274 	<SfxMacroStatement::SfxMacroStatement(const SfxShell&,sal_Bool,const SfxSlot&,sal_Bool,SfxArguments*)>
275 */
276 
277 :	nSlotId( 0 ),
278        aStatement( rStatement ),
279 	bDone( sal_True ),
280 	pDummy( 0 )
281 {
282 }
283 
284 //--------------------------------------------------------------------
285 
286 SfxMacroStatement::SfxMacroStatement
287 (
288 	const SfxMacroStatement&	rOrig // Original, von dem kopiert wird
289 )
290 
291 /* 	[Beschreibung]
292 
293 	Copy-Konstruktor der SfxMacroStatement-Klasse.
294 */
295 
296 :	nSlotId( rOrig.nSlotId ),
297 	aStatement( rOrig.aStatement ),
298        bDone( rOrig.bDone ),
299 	pDummy( 0 )
300 {
301     aArgs = rOrig.aArgs;
302 }
303 
304 //--------------------------------------------------------------------
305 
306 SfxMacroStatement::~SfxMacroStatement()
307 
308 /* 	[Beschreibung]
309 
310 	Destruktor der Klasse SfxMacroStatement. Gibt die Liste der
311 	aktuellen Parameter frei.
312 */
313 
314 {
315 }
316 
317 //--------------------------------------------------------------------
318 
319 void SfxMacroStatement::GenerateNameAndArgs_Impl
320 (
321 	SfxMacro*		/*pMacro*/,			// darin wird aufgezeichnet
322 	const SfxSlot&	rSlot,			// der Slot, der das Statement abspielen kann
323 	sal_Bool			bRequestDone,	// sal_True=wurde ausgef"uhrt, sal_False=abgebrochen
324     ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue >& /*rArgs*/
325 )
326 
327 /*	[Beschreibung]
328 
329 	Interne Hilfsmethode zum generieren des Funktions-/Property-Names
330 	sowie der Parameter. Diese Methode wird nur verwendet, wenn der
331 	Anwendungsprogrammierer keinen eigenen Source an den <SfxRequest>
332 	geh"angt hat.
333 */
334 
335 {
336 	if ( aStatement.Len() && aStatement.GetChar( aStatement.Len() - 1 ) != '.'
337          && rSlot.pName[0] != '.' )
338 		aStatement += '.';
339 
340 	// der Name des Slots ist der Name der Methode / des Properties
341 	aStatement += String::CreateFromAscii(rSlot.pName);
342 	if ( rSlot.IsMode(SFX_SLOT_METHOD) )
343 		aStatement += DEFINE_CONST_UNICODE("( ");
344 	else
345 		aStatement += DEFINE_CONST_UNICODE(" = ");
346 
347 	// alle zusammengesuchten Parameter rausschreiben
348     if ( aArgs.getLength() )
349         for ( sal_uInt16 nArg = 0; nArg < aArgs.getLength(); ++nArg )
350 		{
351 			// den Parameter textuell darstellen
352 			String aArg;
353             ::com::sun::star::uno::Any& rValue = aArgs[nArg].Value;
354             ::com::sun::star::uno::Type pType = rValue.getValueType();
355 			if ( pType == ::getBooleanCppuType() )
356 			{
357                 sal_Bool bTemp = false;
358                 rValue >>= bTemp;
359                 aArg = bTemp ? DEFINE_CONST_UNICODE("TRUE") : DEFINE_CONST_UNICODE("FALSE");
360 			}
361             else if ( pType == ::getCppuType((const sal_Int16*)0) )
362 			{
363                 sal_uInt16 nTemp = 0;
364                 rValue >>= nTemp;
365                 aArg = String::CreateFromInt32( (sal_Int32) nTemp );
366 			}
367             else if ( pType == ::getCppuType((const sal_Int32*)0) )
368 			{
369                 sal_uInt32 nTemp = 0;
370                 rValue >>= nTemp;
371                 aArg = String::CreateFromInt32( nTemp );
372 			}
373 			else if ( pType == ::getCppuType((const ::rtl::OUString*)0) )
374 			{
375                 ::rtl::OUString sTemp;
376                 rValue >>= sTemp;
377 
378                 // Anf"uhrungszeichen werden verdoppelt
379                 XubString aRecordable( sTemp );
380                 sal_uInt16 nPos = 0;
381                 while ( sal_True )
382                 {
383                     nPos = aRecordable.SearchAndReplace( DEFINE_CONST_UNICODE('"'), DEFINE_CONST_UNICODE("\"\""), nPos );
384                     if ( STRING_NOTFOUND == nPos )
385                         break;
386                     nPos += 2;
387                 }
388 
389                 // nicht druckbare Zeichen werden als chr$(...) geschrieben
390                 bool bPrevReplaced = sal_False;
391                 for ( sal_uInt16 n = 0; n < aRecordable.Len(); ++n )
392                 {
393                     sal_Unicode cChar = aRecordable.GetChar(n);
394                     if ( !( cChar>=32 && cChar!=127 ) ) // ALS ERSATZ FUER String::IsPrintable()!
395                     {
396                         XubString aReplacement( DEFINE_CONST_UNICODE("+chr$(") );
397                         aReplacement += cChar;
398 
399                         if ( bPrevReplaced )
400                         {
401                             aRecordable.Insert( aReplacement, n - 2 );
402                             n = n + aReplacement.Len();
403                             aRecordable.SetChar((unsigned short) (n-2), 0x0029);// ')' = 29h
404                             aRecordable.Replace( n-1, 2, DEFINE_CONST_UNICODE("+\"") );
405                             // ++n;
406                         }
407                         else
408                         {
409                             aReplacement += DEFINE_CONST_UNICODE(")+\"");
410                             aRecordable.SetChar(n, 0x0022 );// '"' = 22h
411                             aRecordable.Insert( aReplacement, n + 1 );
412                             n = n + aReplacement.Len();
413                         }
414                         bPrevReplaced = sal_True;
415                     }
416                     else
417                         bPrevReplaced = sal_False;
418 
419                     // Argument in Anf"uhrungszeichen
420                     aArg = '"';
421                     aArg += aRecordable;
422                     aArg += '"';
423                 }
424 /*
425 				case SbxBYTE:
426 				{
427 					// als Zahl darstellen
428 					aArg = (sal_uInt16) rVar.GetByte();
429 					break;
430 				}
431 */
432 			}
433             else
434             {
435                 OSL_ENSURE(
436                     pType == ::getVoidCppuType(), "Unknown Type in recorder!" );
437             }
438 
439 			// den Parameter anh"angen
440 			aStatement += aArg;
441 			aStatement += DEFINE_CONST_UNICODE(", ");
442 		}
443 
444 	// Statement beeden
445     if ( aArgs.getLength() )
446 		aStatement.Erase( aStatement.Len() - 2, 1 );
447 	else
448 		aStatement.Erase( aStatement.Len() - 1, 1 );
449 	if ( rSlot.IsMode(SFX_SLOT_METHOD) )
450 		aStatement += ')';
451 
452 	if ( !bRequestDone )
453 		// nicht als "Done()" gekennzeichnete Statements auskommentieren
454 		aStatement.InsertAscii( "rem ", 0 );
455 }
456 
457 //--------------------------------------------------------------------
458 
459 SfxMacro::SfxMacro
460 (
461 	SfxMacroMode 	eMode		// Zweck der Instanz, siehe <SfxMacroMode>
462 )
463 
464 /*	[Beschreibung]
465 
466 	Konstruktor der Klasse SfxMacro. Instanzen dieser Klasse werden im
467 	SFx zu zwei Zwecken ben"otigt:
468 
469 	1. zum Aufzeichnen von Makros
470 	In diesem Fall wird der Konstruktor mit SFX_MACRO_RECORDINGABSOLUTE
471 	oder SFX_MACRO_RECORDINGRELATIVE aufgerufen. Es sollte sich um eine
472 	Instanz einer abgeleiteten Klasse handeln, um in der Ableitung
473 	die Information dar"uber unterzubringen, wo das Makro gespeichert
474 	werden soll. Ein solches Makro solle sich dann in seinem Destruktor
475 	an der vom Benutzer gew"ahlten Stelle speichern.
476 
477 	2. zum Zuordnen von exisitierenden Makros
478 	In diesem Fall wird der Konstruktor mit SFX_MACRO_EXISTING aufgerufen.
479 	Eine solche Instanz wird z.B. ben"otigt, wenn Makros auf Events
480 	oder <SfxControllerItem>s konfiguriert werden sollen.
481 */
482 
483 :	pImp( new SfxMacro_Impl )
484 
485 {
486 	pImp->eMode = eMode;
487 }
488 
489 //--------------------------------------------------------------------
490 
491 SfxMacro::~SfxMacro()
492 
493 /*	[Beschreibung]
494 
495 	Virtueller Destruktor der Klasse SfxMacro. Dieser sollte in den
496 	abgeleiteten Klassen "uberladen werden, um in den Modi
497 	SFX_MACRO_RECORDINGABSOLUTE und SFX_MACRO_RECORDINGRELATIVE den
498 	aufgezeichneten Source abzuspeichern.
499 
500 
501 	[Querverweise]
502 
503 	<SfxMacro::GenerateSource()const>
504 */
505 
506 {
507 #if OSL_DEBUG_LEVEL > 1
508     SvFileStream aStream( String::CreateFromAscii("file:///f:/testmacro.bas" ), STREAM_STD_READWRITE | STREAM_TRUNC );
509     aStream << ByteString( GenerateSource(), RTL_TEXTENCODING_UTF8 ).GetBuffer();
510 #endif
511 	delete pImp;
512 }
513 
514 //--------------------------------------------------------------------
515 
516 SfxMacroMode SfxMacro::GetMode() const
517 
518 /*	[Beschreibung]
519 
520 	Liefert den Modus, der besagt zu welchem Zweck das SfxMacro konstruiert
521 	wurde.
522 
523 
524 	[Querverweise]
525 
526 	enum <SfxMacroMode>
527 */
528 
529 {
530 	return pImp->eMode;
531 }
532 
533 //--------------------------------------------------------------------
534 
535 void SfxMacro::Record
536 (
537 	SfxMacroStatement*	pStatement 	// aufzuzeichnendes <SfxMacroStatement>
538 )
539 
540 /*	[Beschreibung]
541 
542 	Diese Methode zeichnet das als Parameter "ubergeben Statement auf.
543 	Die Instanz auf die der "ubergebe Pointer zeigt, geht in das Eigentum
544 	des SfxMacro "uber.
545 
546 	Der Aufruf ist nur g"ultig, wenn es sich um ein SfxMacro handelt,
547 	welches mit SFX_MACRO_RECORDINGABSOLUTE oder SFX_MACRO_RECORDINGRELATIVE
548 	konstruiert wirde.
549 
550 
551 	[Querverweise]
552 
553 	<SfxMacro::Replace(SfxMacroStatement*)>
554 	<SfxMacro::Remove()>
555 	<SfxMacro::GetLastStatement()const>
556 */
557 
558 {
559     DBG_ASSERT( pImp->eMode != SFX_MACRO_EXISTING, "invalid call to non-recording SfxMacro" );
560 	pImp->aList.C40_INSERT( SfxMacroStatement, pStatement, pImp->aList.Count() );
561 }
562 
563 //--------------------------------------------------------------------
564 
565 void SfxMacro::Replace
566 (
567 	SfxMacroStatement*	pStatement	// aufzuzeichnendes <SfxMacroStatement>
568 )
569 
570 /*	[Beschreibung]
571 
572 	Diese Methode zeichnet das als Parameter "ubergeben Statement auf.
573 	Dabei wird das jeweils zuletzt aufgezeichnete Statement "uberschrieben.
574 	Die Instanz auf die der "ubergebe Pointer zeigt, geht in das Eigentum
575 	des SfxMacro "uber.
576 
577 	Mit dieser Methode ist es m"oglich, Statements zusammenzufassen. Z.B.
578 	anstelle f"unfmal hintereinander 'CursorLeft()' aufzurufen, k"onnte
579 	das zu 'CursorLeft(5)' zusammengefa\st werden. Oder anstelle ein Wort
580 	Buchstabe f"ur Buchstabe aufzubauen, k"onnte dies durch ein einziges
581 	Statement 'InsertString("Hallo")' ersetzt werden.
582 
583 	Der Aufruf ist nur g"ultig, wenn es sich um ein SfxMacro handelt,
584 	welches mit SFX_MACRO_RECORDINGABSOLUTE oder SFX_MACRO_RECORDINGRELATIVE
585 	konstruiert wurde und bereits ein aufgezeichnetes Statement vorhanden
586 	ist.
587 
588 
589 	[Anmerkung]
590 
591 	Diese Methode wird typischerweise aus den Execute-Methoden der
592 	<SfxSlot>s von den Applikationsentwicklern gerufen.
593 
594 
595 	[Querverweise]
596 
597 	<SfxMacro::Record(SfxMacroStatement*)>
598 	<SfxMacro::Remove()>
599 	<SfxMacro::GetLastStatement()const>
600 */
601 
602 {
603     DBG_ASSERT( pImp->eMode != SFX_MACRO_EXISTING, "invalid call to non-recording SfxMacro" );
604 	DBG_ASSERT( pImp->aList.Count(), "no replaceable statement available" );
605 	pImp->aList.Remove( pImp->aList.Count() - 1 );
606 	pImp->aList.C40_INSERT( SfxMacroStatement,pStatement, pImp->aList.Count() );
607 }
608 
609 //--------------------------------------------------------------------
610 
611 void SfxMacro::Remove()
612 
613 /*	[Beschreibung]
614 
615 	Diese Methode l"oscht das zuletzt aufgezeichnete <SfxMacroStatement>
616 	und entfernt es aus dem Macro.
617 
618 	Mit dieser Methode ist es m"oglich, Statements zusammenzufassen. Z.B.
619 	anstelle f"unfmal hintereinander 'CursorLeft()' aufzurufen, k"onnte
620 	das zu 'CursorLeft(5)' zusammengefa\st werden. Oder anstelle ein Wort
621 	Buchstabe f"ur Buchstabe aufzubauen, k"onnte dies durch ein einziges
622 	Statement 'InsertString("Hallo")' ersetzt werden.
623 
624 	Der Aufruf ist nur g"ultig, wenn es sich um ein SfxMacro handelt,
625 	welches mit SFX_MACRO_RECORDINGABSOLUTE oder SFX_MACRO_RECORDINGRELATIVE
626 	konstruiert wurde und bereits ein aufgezeichnetes Statement vorhanden
627 	ist.
628 
629 
630 	[Anmerkung]
631 
632 	Diese Methode wird typischerweise aus den Execute-Methoden der
633 	<SfxSlot>s von den Applikationsentwicklern gerufen.
634 
635 
636 	[Querverweise]
637 
638 	<SfxMacro::Replace(SfxMacroStatement*)>
639 	<SfxMacro::Record(SfxMacroStatement*)>
640 	<SfxMacro::GetLastStatement()const>
641 */
642 
643 {
644     DBG_ASSERT( pImp->eMode != SFX_MACRO_EXISTING, "invalid call to non-recording SfxMacro" );
645 	DBG_ASSERT( pImp->aList.Count(), "no replaceable statement available" );
646 	pImp->aList.Remove( pImp->aList.Count() - 1 );
647 }
648 
649 //--------------------------------------------------------------------
650 
651 const SfxMacroStatement* SfxMacro::GetLastStatement() const
652 
653 /*  [Beschreibung]
654 
655 	Mit dieser Methode kann auf das jeweils zuletzt aufgezeichnete Statement
656 	lesend zugegriffen werden. Zusammen mit der Methode
657 	<SfxMacro::Replace(SfxMacroStatement*)> ergibt sich dadurch die
658 	M"oglichkeit, Statements zusammenzufassen.
659 
660 	Der Aufruf ist nur g"ultig, wenn es sich um ein SfxMacro handelt,
661 	welches mit SFX_MACRO_RECORDINGABSOLUTE oder SFX_MACRO_RECORDINGRELATIVE
662 	konstruiert wurde.
663 
664 
665 	[Querverweise]
666 
667 	<SfxMacro::Record(SfxMacroStatement*)>
668 	<SfxMacro::Replace(SfxMacroStatement*)>
669 */
670 
671 {
672     DBG_ASSERT( pImp->eMode != SFX_MACRO_EXISTING, "invalid call to non-recording SfxMacro" );
673 	if ( pImp->aList.Count() )
674 		return pImp->aList.GetObject( pImp->aList.Count() - 1 );
675 	return 0;
676 }
677 
678 //--------------------------------------------------------------------
679 
680 String SfxMacro::GenerateSource() const
681 
682 /*  [Beschreibung]
683 
684 	Diese Funktion generiert aus den, seit dem Konstruieren der Instanz
685 	bis zum Zeitpunkt des Aufrufs dieser Methode aufgezeichneten
686 	<SfxMacroStatement>s einen BASIC-Sourcecode, der die Statements,
687 	jedoch nicht den Header ('Sub X') und den Footer ('End Sub') enth"alt.
688 
689 
690 	[Querverweise]
691 
692 	<SfxMacro::Record(SfxMacroStatement*)>
693 	<SfxMacro::Repeat(SfxMacroStatement*)>
694 */
695 
696 {
697     DBG_ASSERT( pImp->eMode != SFX_MACRO_EXISTING, "invalid call to non-recording SfxMacro" );
698 	String aSource;
699 	for ( sal_uInt16 n = 0; n < pImp->aList.Count(); ++n )
700 	{
701 		aSource += pImp->aList.GetObject(n)->GetStatement();
702 		if ( (n+1) < pImp->aList.Count() )
703 			aSource += DEFINE_CONST_UNICODE("\n");
704 	}
705 
706 	return aSource;
707 }
708 
709