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