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