xref: /AOO41X/main/sfx2/source/control/macro.cxx (revision 24c56ab9f1bd1305754aa2f564704f38ff57627e)
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