merge the formfield patch from ooo-build
[ooovba.git] / basic / source / classes / sbxmod.cxx
blobd05cf818c7f0402f7b409dcc0cbd7d1661c45a4c
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: sbxmod.cxx,v $
10 * $Revision: 1.44.10.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_basic.hxx"
34 #include <list>
36 #include <vos/macros.hxx>
37 #include <vcl/svapp.hxx>
38 #include <tools/stream.hxx>
39 #include <svtools/brdcst.hxx>
40 #include <tools/shl.hxx>
41 #include <basic/sbx.hxx>
42 #include "sb.hxx"
43 #include <sbjsmeth.hxx>
44 #include "sbjsmod.hxx"
45 #include "sbintern.hxx"
46 #include "image.hxx"
47 #include "opcodes.hxx"
48 #include "runtime.hxx"
49 #include "token.hxx"
50 #include "sbunoobj.hxx"
53 //#include <basic/hilight.hxx>
54 #include <svtools/syntaxhighlight.hxx>
56 #include <basic/basrdll.hxx>
57 #include <vos/mutex.hxx>
58 #include <basic/sbobjmod.hxx>
59 #include <com/sun/star/lang/XServiceInfo.hpp>
62 // for the bsearch
63 #ifdef WNT
64 #define CDECL _cdecl
65 #endif
66 #if defined(UNX) || defined(OS2)
67 #define CDECL
68 #endif
69 #ifdef UNX
70 #include <sys/resource.h>
71 #endif
73 #include <stdio.h>
75 #include <comphelper/processfactory.hxx>
76 #include <com/sun/star/script/XLibraryContainer.hpp>
77 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
78 #include <com/sun/star/awt/XDialogProvider.hpp>
79 #include <com/sun/star/awt/XTopWindow.hpp>
80 #include <com/sun/star/awt/XControl.hpp>
81 #include <cppuhelper/implbase1.hxx>
82 #include <comphelper/anytostring.hxx>
83 #include <com/sun/star/document/XVbaMethodParameter.hpp> //liuchen 2009-7-21
84 extern void unoToSbxValue( SbxVariable* pVar, const ::com::sun::star::uno::Any& aValue ); //liuchen 2009-7-21
85 extern ::com::sun::star::uno::Any sbxToUnoValue( SbxVariable* pVar ); //liuchen 2009-7-21
87 #include <com/sun/star/frame/XDesktop.hpp>
88 #include <vcl/svapp.hxx>
89 using namespace ::com::sun::star;
91 TYPEINIT1(SbModule,SbxObject)
92 TYPEINIT1(SbMethod,SbxMethod)
93 TYPEINIT1(SbProperty,SbxProperty)
94 TYPEINIT1(SbProcedureProperty,SbxProperty)
95 TYPEINIT1(SbJScriptModule,SbModule)
96 TYPEINIT1(SbJScriptMethod,SbMethod)
97 TYPEINIT1(SbObjModule,SbModule)
98 TYPEINIT1(SbUserFormModule,SbObjModule)
100 SV_DECL_VARARR(SbiBreakpoints,USHORT,4,4)
101 SV_IMPL_VARARR(SbiBreakpoints,USHORT)
104 SV_IMPL_VARARR(HighlightPortions, HighlightPortion)
106 class AsyncQuitHandler
108 AsyncQuitHandler() {}
109 AsyncQuitHandler( const AsyncQuitHandler&);
110 public:
111 static AsyncQuitHandler& instance()
113 static AsyncQuitHandler dInst;
114 return dInst;
117 void QuitApplication()
119 uno::Reference< lang::XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
120 if ( xFactory.is() )
122 uno::Reference< frame::XDesktop > xDeskTop( xFactory->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop") ) ), uno::UNO_QUERY );
123 if ( xDeskTop.is() )
124 xDeskTop->terminate();
127 DECL_LINK( OnAsyncQuit, void* );
130 IMPL_LINK( AsyncQuitHandler, OnAsyncQuit, void*, /*pNull*/ )
132 QuitApplication();
133 return 0L;
136 bool UnlockControllerHack( StarBASIC* pBasic )
138 bool bRes = false;
139 if ( pBasic && pBasic->IsDocBasic() )
141 uno::Any aUnoVar;
142 ::rtl::OUString sVarName( ::rtl::OUString::createFromAscii( "ThisComponent" ) );
143 SbUnoObject* pGlobs = dynamic_cast<SbUnoObject*>( pBasic->Find( sVarName, SbxCLASS_DONTCARE ) );
144 if ( pGlobs )
145 aUnoVar = pGlobs->getUnoAny();
146 uno::Reference< frame::XModel > xModel( aUnoVar, uno::UNO_QUERY);
147 if ( xModel.is() )
151 xModel->unlockControllers();
152 bRes = true;
154 catch( uno::Exception& )
159 return bRes;
161 /////////////////////////////////////////////////////////////////////////////
163 // Ein BASIC-Modul hat EXTSEARCH gesetzt, damit die im Modul enthaltenen
164 // Elemente von anderen Modulen aus gefunden werden koennen.
166 SbModule::SbModule( const String& rName, bool bVBACompat )
167 : SbxObject( String( RTL_CONSTASCII_USTRINGPARAM("StarBASICModule") ) ),
168 pImage( NULL ), pBreaks( NULL ), pClassData( NULL ), mbVBACompat( bVBACompat ), pDocObject( NULL ), bIsProxyModule( false )
170 SetName( rName );
171 SetFlag( SBX_EXTSEARCH | SBX_GBLSEARCH );
172 SetModuleType( com::sun::star::script::ModuleType::Normal );
175 SbModule::~SbModule()
177 if( pImage )
178 delete pImage;
179 if( pBreaks )
180 delete pBreaks;
181 if( pClassData )
182 delete pClassData;
185 BOOL SbModule::IsCompiled() const
187 return BOOL( pImage != 0 );
190 const SbxObject* SbModule::FindType( String aTypeName ) const
192 return pImage ? pImage->FindType( aTypeName ) : NULL;
196 // Aus dem Codegenerator: Loeschen des Images und Invalidieren der Entries
198 void SbModule::StartDefinitions()
200 delete pImage; pImage = NULL;
201 if( pClassData )
202 pClassData->clear();
204 // Methoden und Properties bleiben erhalten, sind jedoch ungueltig
205 // schliesslich sind ja u.U. die Infos belegt
206 USHORT i;
207 for( i = 0; i < pMethods->Count(); i++ )
209 SbMethod* p = PTR_CAST(SbMethod,pMethods->Get( i ) );
210 if( p )
211 p->bInvalid = TRUE;
213 for( i = 0; i < pProps->Count(); )
215 SbProperty* p = PTR_CAST(SbProperty,pProps->Get( i ) );
216 if( p )
217 pProps->Remove( i );
218 else
219 i++;
223 // Methode anfordern/anlegen
225 SbMethod* SbModule::GetMethod( const String& rName, SbxDataType t )
227 SbxVariable* p = pMethods->Find( rName, SbxCLASS_METHOD );
228 SbMethod* pMeth = p ? PTR_CAST(SbMethod,p) : NULL;
229 if( p && !pMeth )
230 pMethods->Remove( p );
231 if( !pMeth )
233 pMeth = new SbMethod( rName, t, this );
234 pMeth->SetParent( this );
235 pMeth->SetFlags( SBX_READ );
236 pMethods->Put( pMeth, pMethods->Count() );
237 StartListening( pMeth->GetBroadcaster(), TRUE );
239 // Per Default ist die Methode GUELTIG, da sie auch vom Compiler
240 // (Codegenerator) erzeugt werden kann
241 pMeth->bInvalid = FALSE;
242 pMeth->ResetFlag( SBX_FIXED );
243 pMeth->SetFlag( SBX_WRITE );
244 pMeth->SetType( t );
245 pMeth->ResetFlag( SBX_WRITE );
246 if( t != SbxVARIANT )
247 pMeth->SetFlag( SBX_FIXED );
248 return pMeth;
251 // Property anfordern/anlegen
253 SbProperty* SbModule::GetProperty( const String& rName, SbxDataType t )
255 SbxVariable* p = pProps->Find( rName, SbxCLASS_PROPERTY );
256 SbProperty* pProp = p ? PTR_CAST(SbProperty,p) : NULL;
257 if( p && !pProp )
258 pProps->Remove( p );
259 if( !pProp )
261 pProp = new SbProperty( rName, t, this );
262 pProp->SetFlag( SBX_READWRITE );
263 pProp->SetParent( this );
264 pProps->Put( pProp, pProps->Count() );
265 StartListening( pProp->GetBroadcaster(), TRUE );
267 return pProp;
270 SbProcedureProperty* SbModule::GetProcedureProperty
271 ( const String& rName, SbxDataType t )
273 SbxVariable* p = pProps->Find( rName, SbxCLASS_PROPERTY );
274 SbProcedureProperty* pProp = p ? PTR_CAST(SbProcedureProperty,p) : NULL;
275 if( p && !pProp )
276 pProps->Remove( p );
277 if( !pProp )
279 pProp = new SbProcedureProperty( rName, t );
280 pProp->SetFlag( SBX_READWRITE );
281 pProp->SetParent( this );
282 pProps->Put( pProp, pProps->Count() );
283 StartListening( pProp->GetBroadcaster(), TRUE );
285 return pProp;
288 SbIfaceMapperMethod* SbModule::GetIfaceMapperMethod
289 ( const String& rName, SbMethod* pImplMeth )
291 SbxVariable* p = pMethods->Find( rName, SbxCLASS_METHOD );
292 SbIfaceMapperMethod* pMapperMethod = p ? PTR_CAST(SbIfaceMapperMethod,p) : NULL;
293 if( p && !pMapperMethod )
294 pMethods->Remove( p );
295 if( !pMapperMethod )
297 pMapperMethod = new SbIfaceMapperMethod( rName, pImplMeth );
298 pMapperMethod->SetParent( this );
299 pMapperMethod->SetFlags( SBX_READ );
300 pMethods->Put( pMapperMethod, pMethods->Count() );
302 pMapperMethod->bInvalid = FALSE;
303 return pMapperMethod;
306 SbIfaceMapperMethod::~SbIfaceMapperMethod()
310 TYPEINIT1(SbIfaceMapperMethod,SbMethod)
313 // Aus dem Codegenerator: Ungueltige Eintraege entfernen
315 void SbModule::EndDefinitions( BOOL bNewState )
317 for( USHORT i = 0; i < pMethods->Count(); )
319 SbMethod* p = PTR_CAST(SbMethod,pMethods->Get( i ) );
320 if( p )
322 if( p->bInvalid )
323 pMethods->Remove( p );
324 else
326 p->bInvalid = bNewState;
327 i++;
330 else
331 i++;
333 SetModified( TRUE );
336 void SbModule::Clear()
338 delete pImage; pImage = NULL;
339 if( pClassData )
340 pClassData->clear();
341 SbxObject::Clear();
345 SbxVariable* SbModule::Find( const XubString& rName, SbxClassType t )
347 // make sure a search in an uninstatiated class module will fail
348 SbxVariable* pRes = SbxObject::Find( rName, t );
349 if ( bIsProxyModule )
350 return NULL;
351 if( !pRes && pImage )
353 SbiInstance* pInst = pINST;
354 if( pInst && pInst->IsCompatibility() )
356 // Put enum types as objects into module,
357 // allows MyEnum.First notation
358 SbxArrayRef xArray = pImage->GetEnums();
359 if( xArray.Is() )
361 SbxVariable* pEnumVar = xArray->Find( rName, SbxCLASS_DONTCARE );
362 SbxObject* pEnumObject = PTR_CAST( SbxObject, pEnumVar );
363 if( pEnumObject )
365 bool bPrivate = pEnumObject->IsSet( SBX_PRIVATE );
366 String aEnumName = pEnumObject->GetName();
368 pRes = new SbxVariable( SbxOBJECT );
369 pRes->SetName( aEnumName );
370 pRes->SetParent( this );
371 pRes->SetFlag( SBX_READ );
372 if( bPrivate )
373 pRes->SetFlag( SBX_PRIVATE );
374 pRes->PutObject( pEnumObject );
379 return pRes;
382 const ::rtl::OUString& SbModule::GetSource32() const
384 return aOUSource;
387 const String& SbModule::GetSource() const
389 static String aRetStr;
390 aRetStr = aOUSource;
391 return aRetStr;
394 // Parent und BASIC sind eins!
396 void SbModule::SetParent( SbxObject* p )
398 // #118083: Assertion is not valid any more
399 // DBG_ASSERT( !p || p->IsA( TYPE(StarBASIC) ), "SbModules nur in BASIC eintragen" );
400 pParent = p;
403 void SbModule::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
404 const SfxHint& rHint, const TypeId& rHintType )
406 const SbxHint* pHint = PTR_CAST(SbxHint,&rHint);
407 if( pHint )
409 SbxVariable* pVar = pHint->GetVar();
410 SbProperty* pProp = PTR_CAST(SbProperty,pVar);
411 SbMethod* pMeth = PTR_CAST(SbMethod,pVar);
412 SbProcedureProperty* pProcProperty = PTR_CAST( SbProcedureProperty, pVar );
413 if( pProcProperty )
415 if( pHint->GetId() == SBX_HINT_DATAWANTED )
417 String aProcName;
418 aProcName.AppendAscii( "Property Get " );
419 aProcName += pProcProperty->GetName();
421 SbxVariable* pPropMeth = Find( aProcName, SbxCLASS_METHOD );
422 if( pPropMeth )
424 // Setup parameters
425 pPropMeth->SetParameters( pVar->GetParameters() );
427 SbxValues aVals;
428 aVals.eType = SbxVARIANT;
429 pPropMeth->Get( aVals );
430 pVar->Put( aVals );
433 else if( pHint->GetId() == SBX_HINT_DATACHANGED )
435 SbxVariable* pPropMeth = NULL;
437 bool bSet = pProcProperty->isSet();
438 if( bSet )
440 pProcProperty->setSet( false );
442 String aProcName;
443 aProcName.AppendAscii( "Property Set " );
444 aProcName += pProcProperty->GetName();
445 pPropMeth = Find( aProcName, SbxCLASS_METHOD );
447 if( !pPropMeth ) // Let
449 String aProcName;
450 aProcName.AppendAscii( "Property Let " );
451 aProcName += pProcProperty->GetName();
452 pPropMeth = Find( aProcName, SbxCLASS_METHOD );
455 if( pPropMeth )
457 // Setup parameters
458 SbxArrayRef xArray = new SbxArray;
459 xArray->Put( pPropMeth, 0 ); // Method as parameter 0
460 xArray->Put( pVar, 1 );
461 pPropMeth->SetParameters( xArray );
463 SbxValues aVals;
464 pPropMeth->Get( aVals );
465 pPropMeth->SetParameters( NULL );
470 if( pProp )
472 if( pProp->GetModule() != this )
473 SetError( SbxERR_BAD_ACTION );
475 else if( pMeth )
477 if( pHint->GetId() == SBX_HINT_DATAWANTED )
479 if( pMeth->bInvalid && !Compile() )
480 // Auto-Compile hat nicht geklappt!
481 StarBASIC::Error( SbERR_BAD_PROP_VALUE );
482 else
484 // Aufruf eines Unterprogramms
485 SbModule* pOld = pMOD;
486 pMOD = this;
487 Run( (SbMethod*) pVar );
488 pMOD = pOld;
492 else
493 SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
497 // Das Setzen der Source macht das Image ungueltig
498 // und scant die Methoden-Definitionen neu ein
500 void SbModule::SetSource( const String& r )
502 SetSource32( r );
505 void SbModule::SetSource32( const ::rtl::OUString& r )
507 aOUSource = r;
508 StartDefinitions();
509 SbiTokenizer aTok( r );
510 aTok.SetCompatible( IsVBACompat() );
511 while( !aTok.IsEof() )
513 SbiToken eEndTok = NIL;
515 // Suchen nach SUB oder FUNCTION
516 SbiToken eLastTok = NIL;
517 while( !aTok.IsEof() )
519 // #32385: Nicht bei declare
520 SbiToken eCurTok = aTok.Next();
521 if( eLastTok != DECLARE )
523 if( eCurTok == SUB )
525 eEndTok = ENDSUB; break;
527 if( eCurTok == FUNCTION )
529 eEndTok = ENDFUNC; break;
531 if( eCurTok == PROPERTY )
533 eEndTok = ENDPROPERTY; break;
536 eLastTok = eCurTok;
538 // Definition der Methode
539 SbMethod* pMeth = NULL;
540 if( eEndTok != NIL )
542 USHORT nLine1 = aTok.GetLine();
543 if( aTok.Next() == SYMBOL )
545 String aName_( aTok.GetSym() );
546 SbxDataType t = aTok.GetType();
547 if( t == SbxVARIANT && eEndTok == ENDSUB )
548 t = SbxVOID;
549 pMeth = GetMethod( aName_, t );
550 pMeth->nLine1 = pMeth->nLine2 = nLine1;
551 // Die Methode ist erst mal GUELTIG
552 pMeth->bInvalid = FALSE;
554 else
555 eEndTok = NIL;
557 // Skip bis END SUB/END FUNCTION
558 if( eEndTok != NIL )
560 while( !aTok.IsEof() )
562 if( aTok.Next() == eEndTok )
564 pMeth->nLine2 = aTok.GetLine();
565 break;
568 if( aTok.IsEof() )
569 pMeth->nLine2 = aTok.GetLine();
572 EndDefinitions( TRUE );
575 void SbModule::SetComment( const String& r )
577 aComment = r;
578 SetModified( TRUE );
581 SbMethod* SbModule::GetFunctionForLine( USHORT nLine )
583 for( USHORT i = 0; i < pMethods->Count(); i++ )
585 SbMethod* p = (SbMethod*) pMethods->Get( i );
586 if( p->GetSbxId() == SBXID_BASICMETHOD )
588 if( nLine >= p->nLine1 && nLine <= p->nLine2 )
589 return p;
592 return NULL;
595 // Ausstrahlen eines Hints an alle Basics
597 static void _SendHint( SbxObject* pObj, ULONG nId, SbMethod* p )
599 // Selbst ein BASIC?
600 if( pObj->IsA( TYPE(StarBASIC) ) && pObj->IsBroadcaster() )
601 pObj->GetBroadcaster().Broadcast( SbxHint( nId, p ) );
602 // Dann die Unterobjekte fragen
603 SbxArray* pObjs = pObj->GetObjects();
604 for( USHORT i = 0; i < pObjs->Count(); i++ )
606 SbxVariable* pVar = pObjs->Get( i );
607 if( pVar->IsA( TYPE(SbxObject) ) )
608 _SendHint( PTR_CAST(SbxObject,pVar), nId, p );
612 static void SendHint( SbxObject* pObj, ULONG nId, SbMethod* p )
614 while( pObj->GetParent() )
615 pObj = pObj->GetParent();
616 _SendHint( pObj, nId, p );
619 // #57841 Uno-Objekte, die in RTL-Funktionen gehalten werden,
620 // beim Programm-Ende freigeben, damit nichts gehalten wird.
621 void ClearUnoObjectsInRTL_Impl_Rek( StarBASIC* pBasic )
623 // return-Wert von CreateUnoService loeschen
624 static String aName( RTL_CONSTASCII_USTRINGPARAM("CreateUnoService") );
625 SbxVariable* pVar = pBasic->GetRtl()->Find( aName, SbxCLASS_METHOD );
626 if( pVar )
627 pVar->SbxValue::Clear();
629 // return-Wert von CreateUnoDialog loeschen
630 static String aName2( RTL_CONSTASCII_USTRINGPARAM("CreateUnoDialog") );
631 pVar = pBasic->GetRtl()->Find( aName2, SbxCLASS_METHOD );
632 if( pVar )
633 pVar->SbxValue::Clear();
635 // return-Wert von CDec loeschen
636 static String aName3( RTL_CONSTASCII_USTRINGPARAM("CDec") );
637 pVar = pBasic->GetRtl()->Find( aName3, SbxCLASS_METHOD );
638 if( pVar )
639 pVar->SbxValue::Clear();
641 // return-Wert von CreateObject loeschen
642 static String aName4( RTL_CONSTASCII_USTRINGPARAM("CreateObject") );
643 pVar = pBasic->GetRtl()->Find( aName4, SbxCLASS_METHOD );
644 if( pVar )
645 pVar->SbxValue::Clear();
647 // Ueber alle Sub-Basics gehen
648 SbxArray* pObjs = pBasic->GetObjects();
649 USHORT nCount = pObjs->Count();
650 for( USHORT i = 0 ; i < nCount ; i++ )
652 SbxVariable* pObjVar = pObjs->Get( i );
653 StarBASIC* pSubBasic = PTR_CAST( StarBASIC, pObjVar );
654 if( pSubBasic )
655 ClearUnoObjectsInRTL_Impl_Rek( pSubBasic );
659 void ClearUnoObjectsInRTL_Impl( StarBASIC* pBasic )
661 // #67781 Rueckgabewerte der Uno-Methoden loeschen
662 clearUnoMethods();
663 clearUnoServiceCtors();
665 ClearUnoObjectsInRTL_Impl_Rek( pBasic );
667 // Oberstes Basic suchen
668 SbxObject* p = pBasic;
669 while( p->GetParent() )
670 p = p->GetParent();
671 if( ((StarBASIC*)p) != pBasic )
672 ClearUnoObjectsInRTL_Impl_Rek( (StarBASIC*)p );
674 bool SbModule::IsVBACompat()
676 return mbVBACompat;
679 void SbModule::SetVBACompat( bool bCompat )
681 mbVBACompat = bCompat;
683 // Ausfuehren eines BASIC-Unterprogramms
684 USHORT SbModule::Run( SbMethod* pMeth )
686 OSL_TRACE("About to run %s, vba compatmode is %d", rtl::OUStringToOString( pMeth->GetName(), RTL_TEXTENCODING_UTF8 ).getStr(), mbVBACompat );
687 static USHORT nMaxCallLevel = 0;
688 static String aMSOMacroRuntimeLibName = String::CreateFromAscii( "Launcher" );
689 static String aMSOMacroRuntimeAppSymbol = String::CreateFromAscii( "Application" );
691 USHORT nRes = 0;
692 BOOL bDelInst = BOOL( pINST == NULL );
693 bool bQuit = false;
695 StarBASICRef xBasic;
696 if( bDelInst )
698 // #32779: Basic waehrend der Ausfuehrung festhalten
699 xBasic = (StarBASIC*) GetParent();
701 pINST = new SbiInstance( (StarBASIC*) GetParent() );
703 // Launcher problem
704 // i80726 The Find below will genarate an error in Testtool so we reset it unless there was one before already
705 BOOL bWasError = SbxBase::GetError() != 0;
706 SbxVariable* pMSOMacroRuntimeLibVar = Find( aMSOMacroRuntimeLibName, SbxCLASS_OBJECT );
707 if ( !bWasError && (SbxBase::GetError() == SbxERR_PROC_UNDEFINED) )
708 SbxBase::ResetError();
709 if( pMSOMacroRuntimeLibVar )
711 StarBASIC* pMSOMacroRuntimeLib = PTR_CAST(StarBASIC,pMSOMacroRuntimeLibVar);
712 if( pMSOMacroRuntimeLib )
714 USHORT nGblFlag = pMSOMacroRuntimeLib->GetFlags() & SBX_GBLSEARCH;
715 pMSOMacroRuntimeLib->ResetFlag( SBX_GBLSEARCH );
716 SbxVariable* pAppSymbol = pMSOMacroRuntimeLib->Find( aMSOMacroRuntimeAppSymbol, SbxCLASS_METHOD );
717 pMSOMacroRuntimeLib->SetFlag( nGblFlag );
718 if( pAppSymbol )
720 pMSOMacroRuntimeLib->SetFlag( SBX_EXTSEARCH ); // Could have been disabled before
721 GetSbData()->pMSOMacroRuntimLib = pMSOMacroRuntimeLib;
726 // Error-Stack loeschen
727 SbErrorStack*& rErrStack = GetSbData()->pErrStack;
728 delete rErrStack;
729 rErrStack = NULL;
731 if( nMaxCallLevel == 0 )
733 #ifdef UNX
734 struct rlimit rl;
735 getrlimit ( RLIMIT_STACK, &rl );
736 // printf( "RLIMIT_STACK = %ld\n", rl.rlim_cur );
737 #endif
738 #if defined LINUX
739 // Empiric value, 900 = needed bytes/Basic call level
740 // for Linux including 10% safety margin
741 nMaxCallLevel = rl.rlim_cur / 900;
742 #elif defined SOLARIS
743 // Empiric value, 1650 = needed bytes/Basic call level
744 // for Solaris including 10% safety margin
745 nMaxCallLevel = rl.rlim_cur / 1650;
746 #elif defined WIN32
747 nMaxCallLevel = 5800;
748 #else
749 nMaxCallLevel = MAXRECURSION;
750 #endif
754 // Rekursion zu tief?
755 if( ++pINST->nCallLvl <= nMaxCallLevel )
757 // Globale Variable in allen Mods definieren
758 GlobalRunInit( /* bBasicStart = */ bDelInst );
760 // Trat ein Compiler-Fehler auf? Dann starten wir nicht
761 if( GetSbData()->bGlobalInitErr == FALSE )
763 if( bDelInst )
765 SendHint( GetParent(), SBX_HINT_BASICSTART, pMeth );
767 // 16.10.96: #31460 Neues Konzept fuer StepInto/Over/Out
768 // Erklaerung siehe runtime.cxx bei SbiInstance::CalcBreakCallLevel()
769 // BreakCallLevel ermitteln
770 pINST->CalcBreakCallLevel( pMeth->GetDebugFlags() );
773 SbModule* pOldMod = pMOD;
774 pMOD = this;
775 SbiRuntime* pRt = new SbiRuntime( this, pMeth, pMeth->nStart );
776 pRt->pNext = pINST->pRun;
777 if( pRt->pNext )
778 pRt->pNext->block();
779 pINST->pRun = pRt;
780 if ( mbVBACompat )
782 pINST->EnableCompatibility( TRUE );
783 //pRt->SetVBAEnabled( true ); // can we get rid of this
785 while( pRt->Step() ) {}
786 if( pRt->pNext )
787 pRt->pNext->unblock();
789 // #63710 Durch ein anderes Thread-Handling bei Events kann es passieren,
790 // dass show-Aufruf an einem Dialog zurueckkehrt (durch schliessen des
791 // Dialogs per UI), BEVOR ein per Event ausgeloester weitergehender Call,
792 // der in Basic weiter oben im Stack steht und auf einen Basic-Breakpoint
793 // gelaufen ist, zurueckkehrt. Dann wird unten die Instanz zerstoert und
794 // wenn das noch im Call stehende Basic weiterlaeuft, gibt es einen GPF.
795 // Daher muss hier gewartet werden, bis andere Call zurueckkehrt.
796 if( bDelInst )
798 // Hier mit 1 statt 0 vergleichen, da vor nCallLvl--
799 while( pINST->nCallLvl != 1 )
800 GetpApp()->Yield();
803 nRes = TRUE;
804 pINST->pRun = pRt->pNext;
805 pINST->nCallLvl--; // Call-Level wieder runter
807 // Gibt es eine uebergeordnete Runtime-Instanz?
808 // Dann SbDEBUG_BREAK uebernehmen, wenn gesetzt
809 SbiRuntime* pRtNext = pRt->pNext;
810 if( pRtNext && (pRt->GetDebugFlags() & SbDEBUG_BREAK) )
811 pRtNext->SetDebugFlags( SbDEBUG_BREAK );
813 delete pRt;
814 pMOD = pOldMod;
815 if ( pINST->nCallLvl == 0 && IsVBACompat() )
817 // VBA always ensure screenupdating is enabled after completing
818 StarBASIC* pBasic = PTR_CAST(StarBASIC,GetParent());
819 if ( pBasic && pBasic->IsDocBasic() )
821 UnlockControllerHack( pBasic );
824 if( bDelInst )
826 // #57841 Uno-Objekte, die in RTL-Funktionen gehalten werden,
827 // beim Programm-Ende freigeben, damit nichts gehalten wird.
828 ClearUnoObjectsInRTL_Impl( xBasic );
830 DBG_ASSERT(pINST->nCallLvl==0,"BASIC-Call-Level > 0");
831 delete pINST, pINST = NULL, bDelInst = FALSE;
833 // #i30690
834 vos::OGuard aSolarGuard( Application::GetSolarMutex() );
835 SendHint( GetParent(), SBX_HINT_BASICSTOP, pMeth );
837 GlobalRunDeInit();
840 else
841 pINST->nCallLvl--; // Call-Level wieder runter
843 else
845 pINST->nCallLvl--; // Call-Level wieder runter
846 StarBASIC::FatalError( SbERR_STACK_OVERFLOW );
849 // VBA always ensure screenupdating is enabled after completing
850 StarBASIC* pBasic = PTR_CAST(StarBASIC,GetParent());
851 if ( pBasic && pBasic->IsDocBasic() && !pINST )
852 UnlockControllerHack( pBasic );
853 if( bDelInst )
855 // #57841 Uno-Objekte, die in RTL-Funktionen gehalten werden,
856 // beim Programm-Ende freigeben, damit nichts gehalten wird.
857 ClearUnoObjectsInRTL_Impl( xBasic );
859 delete pINST;
860 pINST = NULL;
862 if ( pBasic && pBasic->IsDocBasic() && pBasic->IsQuitApplication() && !pINST )
863 bQuit = true;
865 if ( bQuit )
867 //QuitApplicationHack();
868 Application::PostUserEvent( LINK( &AsyncQuitHandler::instance(), AsyncQuitHandler, OnAsyncQuit ), NULL );
871 return nRes;
874 // Ausfuehren der Init-Methode eines Moduls nach dem Laden
875 // oder der Compilation
877 void SbModule::RunInit()
879 if( pImage
880 && !pImage->bInit
881 && pImage->GetFlag( SBIMG_INITCODE ) )
883 // Flag setzen, dass RunInit aktiv ist (Testtool)
884 GetSbData()->bRunInit = TRUE;
886 // BOOL bDelInst = BOOL( pINST == NULL );
887 // if( bDelInst )
888 // pINST = new SbiInstance( (StarBASIC*) GetParent() );
889 SbModule* pOldMod = pMOD;
890 pMOD = this;
891 // Der Init-Code beginnt immer hier
892 SbiRuntime* pRt = new SbiRuntime( this, NULL, 0 );
893 pRt->pNext = pINST->pRun;
894 pINST->pRun = pRt;
895 while( pRt->Step() ) {}
896 pINST->pRun = pRt->pNext;
897 delete pRt;
898 pMOD = pOldMod;
899 // if( bDelInst )
900 // delete pINST, pINST = NULL;
901 pImage->bInit = TRUE;
902 pImage->bFirstInit = FALSE;
904 // RunInit ist nicht mehr aktiv
905 GetSbData()->bRunInit = FALSE;
909 // Mit private/dim deklarierte Variablen loeschen
911 void SbModule::AddVarName( const String& aName )
913 // see if the name is added allready
914 std::vector< String >::iterator it_end = mModuleVariableNames.end();
915 for ( std::vector< String >::iterator it = mModuleVariableNames.begin(); it != it_end; ++it )
917 if ( aName == *it )
918 return;
920 mModuleVariableNames.push_back( aName );
923 void SbModule::RemoveVars()
925 std::vector< String >::iterator it_end = mModuleVariableNames.end();
926 for ( std::vector< String >::iterator it = mModuleVariableNames.begin(); it != it_end; ++it )
928 // We don't want a Find being called in a derived class ( e.g.
929 // SbUserform because it could trigger say an initialise event
930 // which would cause basic to be re-run in the middle of the init ( and remember RemoveVars is called from compile and we don't want code to run as part of the compile )
931 SbxVariableRef p = SbModule::Find( *it, SbxCLASS_PROPERTY );
932 if( p.Is() )
933 Remove (p);
937 void SbModule::ClearPrivateVars()
939 for( USHORT i = 0 ; i < pProps->Count() ; i++ )
941 SbProperty* p = PTR_CAST(SbProperty,pProps->Get( i ) );
942 if( p )
944 // Arrays nicht loeschen, sondern nur deren Inhalt
945 if( p->GetType() & SbxARRAY )
947 SbxArray* pArray = PTR_CAST(SbxArray,p->GetObject());
948 if( pArray )
950 for( USHORT j = 0 ; j < pArray->Count() ; j++ )
952 SbxVariable* pj = PTR_CAST(SbxVariable,pArray->Get( j ));
953 pj->SbxValue::Clear();
955 USHORT nFlags = pj->GetFlags();
956 pj->SetFlags( (nFlags | SBX_WRITE) & (~SBX_FIXED) );
957 pj->PutEmpty();
958 pj->SetFlags( nFlags );
963 else
965 p->SbxValue::Clear();
967 USHORT nFlags = p->GetFlags();
968 p->SetFlags( (nFlags | SBX_WRITE) & (~SBX_FIXED) );
969 p->PutEmpty();
970 p->SetFlags( nFlags );
977 // Zunaechst in dieses Modul, um 358-faehig zu bleiben
978 // (Branch in sb.cxx vermeiden)
979 void StarBASIC::ClearAllModuleVars( void )
981 // Eigene Module initialisieren
982 for ( USHORT nMod = 0; nMod < pModules->Count(); nMod++ )
984 SbModule* pModule = (SbModule*)pModules->Get( nMod );
985 // Nur initialisieren, wenn der Startcode schon ausgefuehrt wurde
986 if( pModule->pImage && pModule->pImage->bInit )
987 pModule->ClearPrivateVars();
990 /* #88042 This code can delete already used public vars during runtime!
991 // Alle Objekte ueberpruefen, ob es sich um ein Basic handelt
992 // Wenn ja, auch dort initialisieren
993 for ( USHORT nObj = 0; nObj < pObjs->Count(); nObj++ )
995 SbxVariable* pVar = pObjs->Get( nObj );
996 StarBASIC* pBasic = PTR_CAST(StarBASIC,pVar);
997 if( pBasic )
998 pBasic->ClearAllModuleVars();
1003 // Ausfuehren des Init-Codes aller Module
1004 void SbModule::GlobalRunInit( BOOL bBasicStart )
1006 // Wenn kein Basic-Start, nur initialisieren, wenn Modul uninitialisiert
1007 if( !bBasicStart )
1008 if( !(pImage && !pImage->bInit) )
1009 return;
1011 // GlobalInitErr-Flag fuer Compiler-Error initialisieren
1012 // Anhand dieses Flags kann in SbModule::Run() nach dem Aufruf
1013 // von GlobalRunInit festgestellt werden, ob beim initialisieren
1014 // der Module ein Fehler auftrat. Dann wird nicht gestartet.
1015 GetSbData()->bGlobalInitErr = FALSE;
1017 // Parent vom Modul ist ein Basic
1018 StarBASIC *pBasic = PTR_CAST(StarBASIC,GetParent());
1019 if( pBasic )
1021 pBasic->InitAllModules();
1023 SbxObject* pParent_ = pBasic->GetParent();
1024 if( pParent_ )
1026 StarBASIC * pParentBasic = PTR_CAST(StarBASIC,pParent_);
1027 if( pParentBasic )
1029 pParentBasic->InitAllModules( pBasic );
1031 // #109018 Parent can also have a parent (library in doc)
1032 SbxObject* pParentParent = pParentBasic->GetParent();
1033 if( pParentParent )
1035 StarBASIC * pParentParentBasic = PTR_CAST(StarBASIC,pParentParent);
1036 if( pParentParentBasic )
1037 pParentParentBasic->InitAllModules( pParentBasic );
1044 void SbModule::GlobalRunDeInit( void )
1046 StarBASIC *pBasic = PTR_CAST(StarBASIC,GetParent());
1047 if( pBasic )
1049 pBasic->DeInitAllModules();
1051 SbxObject* pParent_ = pBasic->GetParent();
1052 if( pParent_ )
1053 pBasic = PTR_CAST(StarBASIC,pParent_);
1054 if( pBasic )
1055 pBasic->DeInitAllModules();
1059 // Suche nach dem naechsten STMNT-Befehl im Code. Wird vom STMNT-
1060 // Opcode verwendet, um die Endspalte zu setzen.
1062 const BYTE* SbModule::FindNextStmnt( const BYTE* p, USHORT& nLine, USHORT& nCol ) const
1064 return FindNextStmnt( p, nLine, nCol, FALSE );
1067 const BYTE* SbModule::FindNextStmnt( const BYTE* p, USHORT& nLine, USHORT& nCol,
1068 BOOL bFollowJumps, const SbiImage* pImg ) const
1070 UINT32 nPC = (UINT32) ( p - (const BYTE*) pImage->GetCode() );
1071 while( nPC < pImage->GetCodeSize() )
1073 SbiOpcode eOp = (SbiOpcode ) ( *p++ );
1074 nPC++;
1075 if( bFollowJumps && eOp == _JUMP && pImg )
1077 DBG_ASSERT( pImg, "FindNextStmnt: pImg==NULL with FollowJumps option" );
1078 UINT32 nOp1 = *p++; nOp1 |= *p++ << 8;
1079 nOp1 |= *p++ << 16; nOp1 |= *p++ << 24;
1080 p = (const BYTE*) pImg->GetCode() + nOp1;
1082 else if( eOp >= SbOP1_START && eOp <= SbOP1_END )
1083 p += 4, nPC += 4;
1084 else if( eOp == _STMNT )
1086 UINT32 nl, nc;
1087 nl = *p++; nl |= *p++ << 8;
1088 nl |= *p++ << 16 ; nl |= *p++ << 24;
1089 nc = *p++; nc |= *p++ << 8;
1090 nc |= *p++ << 16 ; nc |= *p++ << 24;
1091 nLine = (USHORT)nl; nCol = (USHORT)nc;
1092 return p;
1094 else if( eOp >= SbOP2_START && eOp <= SbOP2_END )
1095 p += 8, nPC += 8;
1096 else if( !( eOp >= SbOP0_START && eOp <= SbOP0_END ) )
1098 StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
1099 break;
1102 return NULL;
1105 // Testen, ob eine Zeile STMNT-Opcodes enthaelt
1107 BOOL SbModule::IsBreakable( USHORT nLine ) const
1109 if( !pImage )
1110 return FALSE;
1111 const BYTE* p = (const BYTE* ) pImage->GetCode();
1112 USHORT nl, nc;
1113 while( ( p = FindNextStmnt( p, nl, nc ) ) != NULL )
1114 if( nl == nLine )
1115 return TRUE;
1116 return FALSE;
1119 USHORT SbModule::GetBPCount() const
1121 return pBreaks ? pBreaks->Count() : 0;
1124 USHORT SbModule::GetBP( USHORT n ) const
1126 if( pBreaks && n < pBreaks->Count() )
1127 return pBreaks->GetObject( n );
1128 else
1129 return 0;
1132 BOOL SbModule::IsBP( USHORT nLine ) const
1134 if( pBreaks )
1136 const USHORT* p = pBreaks->GetData();
1137 USHORT n = pBreaks->Count();
1138 for( USHORT i = 0; i < n; i++, p++ )
1140 USHORT b = *p;
1141 if( b == nLine )
1142 return TRUE;
1143 if( b < nLine )
1144 break;
1147 return FALSE;
1150 BOOL SbModule::SetBP( USHORT nLine )
1152 if( !IsBreakable( nLine ) )
1153 return FALSE;
1154 if( !pBreaks )
1155 pBreaks = new SbiBreakpoints;
1156 const USHORT* p = pBreaks->GetData();
1157 USHORT n = pBreaks->Count();
1158 USHORT i;
1159 for( i = 0; i < n; i++, p++ )
1161 USHORT b = *p;
1162 if( b == nLine )
1163 return TRUE;
1164 if( b < nLine )
1165 break;
1167 pBreaks->Insert( &nLine, 1, i );
1169 // #38568: Zur Laufzeit auch hier SbDEBUG_BREAK setzen
1170 if( pINST && pINST->pRun )
1171 pINST->pRun->SetDebugFlags( SbDEBUG_BREAK );
1173 return IsBreakable( nLine );
1176 BOOL SbModule::ClearBP( USHORT nLine )
1178 BOOL bRes = FALSE;
1179 if( pBreaks )
1181 const USHORT* p = pBreaks->GetData();
1182 USHORT n = pBreaks->Count();
1183 for( USHORT i = 0; i < n; i++, p++ )
1185 USHORT b = *p;
1186 if( b == nLine )
1188 pBreaks->Remove( i, 1 ); bRes = TRUE; break;
1190 if( b < nLine )
1191 break;
1193 if( !pBreaks->Count() )
1194 delete pBreaks, pBreaks = NULL;
1196 return bRes;
1199 void SbModule::ClearAllBP()
1201 delete pBreaks; pBreaks = NULL;
1204 void
1205 SbModule::fixUpMethodStart( bool bCvtToLegacy, SbiImage* pImg ) const
1207 if ( !pImg )
1208 pImg = pImage;
1209 for( UINT32 i = 0; i < pMethods->Count(); i++ )
1211 SbMethod* pMeth = PTR_CAST(SbMethod,pMethods->Get( (USHORT)i ) );
1212 if( pMeth )
1214 //fixup method start positions
1215 if ( bCvtToLegacy )
1216 pMeth->nStart = pImg->CalcLegacyOffset( pMeth->nStart );
1217 else
1218 pMeth->nStart = pImg->CalcNewOffset( (USHORT)pMeth->nStart );
1224 BOOL SbModule::LoadData( SvStream& rStrm, USHORT nVer )
1226 Clear();
1227 if( !SbxObject::LoadData( rStrm, 1 ) )
1228 return FALSE;
1229 // Sicherheitshalber...
1230 SetFlag( SBX_EXTSEARCH | SBX_GBLSEARCH );
1231 BYTE bImage;
1232 rStrm >> bImage;
1233 if( bImage )
1235 SbiImage* p = new SbiImage;
1236 UINT32 nImgVer = 0;
1238 if( !p->Load( rStrm, nImgVer ) )
1240 delete p;
1241 return FALSE;
1243 // If the image is in old format, we fix up the method start offsets
1244 if ( nImgVer < B_EXT_IMG_VERSION )
1246 fixUpMethodStart( false, p );
1247 p->ReleaseLegacyBuffer();
1249 aComment = p->aComment;
1250 SetName( p->aName );
1251 if( p->GetCodeSize() )
1253 aOUSource = p->aOUSource;
1254 // Alte Version: Image weg
1255 if( nVer == 1 )
1257 SetSource32( p->aOUSource );
1258 delete p;
1260 else
1261 pImage = p;
1263 else
1265 SetSource32( p->aOUSource );
1266 delete p;
1269 return TRUE;
1272 BOOL SbModule::StoreData( SvStream& rStrm ) const
1274 BOOL bFixup = ( pImage && !pImage->ExceedsLegacyLimits() );
1275 if ( bFixup )
1276 fixUpMethodStart( true );
1277 BOOL bRet = SbxObject::StoreData( rStrm );
1278 if ( !bRet )
1279 return FALSE;
1281 if( pImage )
1283 pImage->aOUSource = aOUSource;
1284 pImage->aComment = aComment;
1285 pImage->aName = GetName();
1286 rStrm << (BYTE) 1;
1287 // # PCode is saved only for legacy formats only
1288 // It should be noted that it probably isn't necessary
1289 // It would be better not to store the image ( more flexible with
1290 // formats )
1291 bool bRes = pImage->Save( rStrm, B_LEGACYVERSION );
1292 if ( bFixup )
1293 fixUpMethodStart( false ); // restore method starts
1294 return bRes;
1297 else
1299 SbiImage aImg;
1300 aImg.aOUSource = aOUSource;
1301 aImg.aComment = aComment;
1302 aImg.aName = GetName();
1303 rStrm << (BYTE) 1;
1304 return aImg.Save( rStrm );
1308 BOOL SbModule::ExceedsLegacyModuleSize()
1310 if ( !IsCompiled() )
1311 Compile();
1312 if ( pImage && pImage->ExceedsLegacyLimits() )
1313 return true;
1314 return false;
1317 class ErrorHdlResetter
1319 Link mErrHandler;
1320 bool mbError;
1321 public:
1322 ErrorHdlResetter() : mbError( false )
1324 // save error handler
1325 mErrHandler = StarBASIC::GetGlobalErrorHdl();
1326 // set new error handler
1327 StarBASIC::SetGlobalErrorHdl( LINK( this, ErrorHdlResetter, BasicErrorHdl ) );
1329 ~ErrorHdlResetter()
1331 // restore error handler
1332 StarBASIC::SetGlobalErrorHdl(mErrHandler);
1334 DECL_LINK( BasicErrorHdl, StarBASIC * );
1335 bool HasError() { return mbError; }
1337 IMPL_LINK( ErrorHdlResetter, BasicErrorHdl, StarBASIC *, /*pBasic*/)
1339 mbError = true;
1340 return 0;
1343 bool SbModule::HasExeCode()
1346 ErrorHdlResetter aGblErrHdl;
1347 // And empty Image always has the Global Chain set up
1348 static const unsigned char pEmptyImage[] = { 0x45, 0x0 , 0x0, 0x0, 0x0 };
1349 // lets be stricter for the moment than VBA
1351 bool bRes = false;
1352 if ( !IsCompiled() )
1353 Compile();
1354 if ( pImage && !( pImage->GetCodeSize() == 5 && ( memcmp( pImage->GetCode(), pEmptyImage, pImage->GetCodeSize() ) == 0 ) )
1355 || aGblErrHdl.HasError() )
1356 bRes = true;
1357 return bRes;
1360 // Store only image, no source
1361 BOOL SbModule::StoreBinaryData( SvStream& rStrm )
1363 return StoreBinaryData( rStrm, 0 );
1366 BOOL SbModule::StoreBinaryData( SvStream& rStrm, USHORT nVer )
1368 BOOL bRet = Compile();
1369 if( bRet )
1371 BOOL bFixup = ( !nVer && !pImage->ExceedsLegacyLimits() );// save in old image format, fix up method starts
1373 if ( bFixup ) // save in old image format, fix up method starts
1374 fixUpMethodStart( true );
1375 bRet = SbxObject::StoreData( rStrm );
1376 if( bRet )
1378 pImage->aOUSource = ::rtl::OUString();
1379 pImage->aComment = aComment;
1380 pImage->aName = GetName();
1382 rStrm << (BYTE) 1;
1383 if ( nVer )
1384 bRet = pImage->Save( rStrm, B_EXT_IMG_VERSION );
1385 else
1386 bRet = pImage->Save( rStrm, B_LEGACYVERSION );
1387 if ( bFixup )
1388 fixUpMethodStart( false ); // restore method starts
1390 pImage->aOUSource = aOUSource;
1393 return bRet;
1396 // Called for >= OO 1.0 passwd protected libraries only
1399 BOOL SbModule::LoadBinaryData( SvStream& rStrm )
1401 ::rtl::OUString aKeepSource = aOUSource;
1402 bool bRet = LoadData( rStrm, 2 );
1403 LoadCompleted();
1404 aOUSource = aKeepSource;
1405 return bRet;
1408 BOOL SbModule::LoadCompleted()
1410 SbxArray* p = GetMethods();
1411 USHORT i;
1412 for( i = 0; i < p->Count(); i++ )
1414 SbMethod* q = PTR_CAST(SbMethod,p->Get( i ) );
1415 if( q )
1416 q->pMod = this;
1418 p = GetProperties();
1419 for( i = 0; i < p->Count(); i++ )
1421 SbProperty* q = PTR_CAST(SbProperty,p->Get( i ) );
1422 if( q )
1423 q->pMod = this;
1425 return TRUE;
1428 /////////////////////////////////////////////////////////////////////////
1429 // Implementation SbJScriptModule (Basic-Modul fuer JavaScript-Sourcen)
1430 SbJScriptModule::SbJScriptModule( const String& rName )
1431 :SbModule( rName )
1435 BOOL SbJScriptModule::LoadData( SvStream& rStrm, USHORT nVer )
1437 (void)nVer;
1439 Clear();
1440 if( !SbxObject::LoadData( rStrm, 1 ) )
1441 return FALSE;
1443 // Source-String holen
1444 String aTmp;
1445 rStrm.ReadByteString( aTmp, gsl_getSystemTextEncoding() );
1446 aOUSource = aTmp;
1447 //rStrm >> aSource;
1448 return TRUE;
1451 BOOL SbJScriptModule::StoreData( SvStream& rStrm ) const
1453 if( !SbxObject::StoreData( rStrm ) )
1454 return FALSE;
1456 // Source-String schreiben
1457 String aTmp = aOUSource;
1458 rStrm.WriteByteString( aTmp, gsl_getSystemTextEncoding() );
1459 //rStrm << aSource;
1460 return TRUE;
1464 /////////////////////////////////////////////////////////////////////////
1466 SbMethod::SbMethod( const String& r, SbxDataType t, SbModule* p )
1467 : SbxMethod( r, t ), pMod( p )
1469 bInvalid = TRUE;
1470 nStart =
1471 nDebugFlags =
1472 nLine1 =
1473 nLine2 = 0;
1474 refStatics = new SbxArray;
1475 mCaller = 0;
1476 // AB: 2.7.1996: HACK wegen 'Referenz kann nicht gesichert werden'
1477 SetFlag( SBX_NO_MODIFY );
1480 SbMethod::SbMethod( const SbMethod& r )
1481 : SvRefBase( r ), SbxMethod( r )
1483 pMod = r.pMod;
1484 bInvalid = r.bInvalid;
1485 nStart = r.nStart;
1486 nDebugFlags = r.nDebugFlags;
1487 nLine1 = r.nLine1;
1488 nLine2 = r.nLine2;
1489 refStatics = r.refStatics;
1490 mCaller = r.mCaller;
1491 SetFlag( SBX_NO_MODIFY );
1494 SbMethod::~SbMethod()
1498 SbxArray* SbMethod::GetLocals()
1500 if( pINST )
1501 return pINST->GetLocals( this );
1502 else
1503 return NULL;
1506 void SbMethod::ClearStatics()
1508 refStatics = new SbxArray;
1511 SbxArray* SbMethod::GetStatics()
1513 return refStatics;
1516 BOOL SbMethod::LoadData( SvStream& rStrm, USHORT nVer )
1518 if( !SbxMethod::LoadData( rStrm, 1 ) )
1519 return FALSE;
1520 INT16 n;
1521 rStrm >> n;
1522 INT16 nTempStart = (INT16)nStart;
1523 // nDebugFlags = n; // AB 16.1.96: Nicht mehr uebernehmen
1524 if( nVer == 2 )
1525 rStrm >> nLine1 >> nLine2 >> nTempStart >> bInvalid;
1526 // AB: 2.7.1996: HACK wegen 'Referenz kann nicht gesichert werden'
1527 SetFlag( SBX_NO_MODIFY );
1528 nStart = nTempStart;
1529 return TRUE;
1532 BOOL SbMethod::StoreData( SvStream& rStrm ) const
1534 if( !SbxMethod::StoreData( rStrm ) )
1535 return FALSE;
1536 rStrm << (INT16) nDebugFlags
1537 << (INT16) nLine1
1538 << (INT16) nLine2
1539 << (INT16) nStart
1540 << (BYTE) bInvalid;
1541 return TRUE;
1544 void SbMethod::GetLineRange( USHORT& l1, USHORT& l2 )
1546 l1 = nLine1; l2 = nLine2;
1549 // Kann spaeter mal weg
1551 SbxInfo* SbMethod::GetInfo()
1553 return pInfo;
1556 // Schnittstelle zum Ausfuehren einer Methode aus den Applikationen
1557 // #34191# Mit speziellem RefCounting, damit das Basic nicht durch CloseDocument()
1558 // abgeschossen werden kann. Rueckgabewert wird als String geliefert.
1559 ErrCode SbMethod::Call( SbxValue* pRet, SbxVariable* pCaller )
1561 if ( pCaller )
1563 OSL_TRACE("SbMethod::Call Have been passed a caller 0x%x", pCaller );
1564 mCaller = pCaller;
1566 // RefCount vom Modul hochzaehlen
1567 SbModule* pMod_ = (SbModule*)GetParent();
1568 pMod_->AddRef();
1570 // RefCount vom Basic hochzaehlen
1571 StarBASIC* pBasic = (StarBASIC*)pMod_->GetParent();
1572 pBasic->AddRef();
1574 // Values anlegen, um Return-Wert zu erhalten
1575 SbxValues aVals;
1576 aVals.eType = SbxVARIANT;
1578 // #104083: Compile BEFORE get
1579 if( bInvalid && !pMod_->Compile() )
1580 StarBASIC::Error( SbERR_BAD_PROP_VALUE );
1582 Get( aVals );
1583 if ( pRet )
1584 pRet->Put( aVals );
1586 // Gab es einen Error
1587 ErrCode nErr = SbxBase::GetError();
1588 SbxBase::ResetError();
1590 // Objekte freigeben
1591 pMod_->ReleaseRef();
1592 pBasic->ReleaseRef();
1593 mCaller = 0;
1594 return nErr;
1598 // #100883 Own Broadcast for SbMethod
1599 void SbMethod::Broadcast( ULONG nHintId )
1601 if( pCst && !IsSet( SBX_NO_BROADCAST ) && StaticIsEnabledBroadcasting() )
1603 // Da die Methode von aussen aufrufbar ist, hier noch einmal
1604 // die Berechtigung testen
1605 if( nHintId & SBX_HINT_DATAWANTED )
1606 if( !CanRead() )
1607 return;
1608 if( nHintId & SBX_HINT_DATACHANGED )
1609 if( !CanWrite() )
1610 return;
1612 if( pMod && !pMod->IsCompiled() )
1613 pMod->Compile();
1615 // Block broadcasts while creating new method
1616 SfxBroadcaster* pSave = pCst;
1617 pCst = NULL;
1618 SbMethod* pThisCopy = new SbMethod( *this );
1619 SbMethodRef xHolder = pThisCopy;
1620 if( mpPar.Is() )
1622 // this, als Element 0 eintragen, aber den Parent nicht umsetzen!
1623 if( GetType() != SbxVOID )
1624 mpPar->PutDirect( pThisCopy, 0 );
1625 SetParameters( NULL );
1628 pCst = pSave;
1629 pSave->Broadcast( SbxHint( nHintId, pThisCopy ) );
1631 USHORT nSaveFlags = GetFlags();
1632 SetFlag( SBX_READWRITE );
1633 pCst = NULL;
1634 Put( pThisCopy->GetValues_Impl() );
1635 pCst = pSave;
1636 SetFlags( nSaveFlags );
1640 /////////////////////////////////////////////////////////////////////////
1642 // Implementation SbJScriptMethod (Method-Klasse als Wrapper fuer JavaScript-Funktionen)
1644 SbJScriptMethod::SbJScriptMethod( const String& r, SbxDataType t, SbModule* p )
1645 : SbMethod( r, t, p )
1649 SbJScriptMethod::~SbJScriptMethod()
1653 /////////////////////////////////////////////////////////////////////////
1654 SbObjModule::SbObjModule( const com::sun::star::script::ModuleInfo& mInfo, bool bIsVbaCompatible )
1655 : SbModule( mInfo.ModuleName, bIsVbaCompatible )
1657 SetModuleType( mInfo.ModuleType );
1658 if ( mInfo.ModuleType == script::ModuleType::Form )
1660 SetClassName( rtl::OUString::createFromAscii( "Form" ) );
1662 else if ( mInfo.ModuleObject.is() )
1663 SetUnoObject( uno::makeAny( mInfo.ModuleObject ) );
1665 void
1666 SbObjModule::SetUnoObject( const uno::Any& aObj ) throw ( uno::RuntimeException )
1668 SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,(SbxVariable*)pDocObject);
1669 if ( pUnoObj && pUnoObj->getUnoAny() == aObj ) // object is equal, nothing to do
1670 return;
1671 pDocObject = new SbUnoObject( GetName(), uno::makeAny( aObj ) );
1673 com::sun::star::uno::Reference< com::sun::star::lang::XServiceInfo > xServiceInfo( aObj, com::sun::star::uno::UNO_QUERY_THROW );
1674 if( xServiceInfo->supportsService( rtl::OUString::createFromAscii( "ooo.vba.excel.Worksheet" ) ) )
1676 SetClassName( rtl::OUString::createFromAscii( "Worksheet" ) );
1678 else if( xServiceInfo->supportsService( rtl::OUString::createFromAscii( "ooo.vba.excel.Workbook" ) ) )
1680 SetClassName( rtl::OUString::createFromAscii( "Workbook" ) );
1684 SbxVariable*
1685 SbObjModule::GetObject()
1687 return pDocObject;
1689 SbxVariable*
1690 SbObjModule::Find( const XubString& rName, SbxClassType t )
1692 //OSL_TRACE("SbObjectModule find for %s", rtl::OUStringToOString( rName, RTL_TEXTENCODING_UTF8 ).getStr() );
1693 SbxVariable* pVar = NULL;
1694 if ( !pVar && pDocObject)
1695 pVar = pDocObject->Find( rName, t );
1696 if ( !pVar )
1697 pVar = SbModule::Find( rName, t );
1698 return pVar;
1701 typedef ::cppu::WeakImplHelper1< awt::XTopWindowListener > EventListener_BASE;
1703 class FormObjEventListenerImpl : public EventListener_BASE
1705 SbUserFormModule* mpUserForm;
1706 uno::Reference< lang::XComponent > mxComponent;
1707 bool mbDisposed;
1708 sal_Bool mbOpened;
1709 sal_Bool mbActivated;
1710 sal_Bool mbShowing;
1711 FormObjEventListenerImpl(); // not defined
1712 FormObjEventListenerImpl(const FormObjEventListenerImpl&); // not defined
1713 public:
1714 FormObjEventListenerImpl( SbUserFormModule* pUserForm, const uno::Reference< lang::XComponent >& xComponent ) : mpUserForm( pUserForm ), mxComponent( xComponent) , mbDisposed( false ), mbOpened( sal_False ), mbActivated( sal_False ), mbShowing( sal_False )
1716 if ( mxComponent.is() );
1718 uno::Reference< awt::XTopWindow > xList( mxComponent, uno::UNO_QUERY_THROW );;
1719 //uno::Reference< awt::XWindow > xList( mxComponent, uno::UNO_QUERY_THROW );;
1720 OSL_TRACE("*********** Registering the listener");
1721 xList->addTopWindowListener( this );
1725 ~FormObjEventListenerImpl()
1727 removeListener();
1729 sal_Bool isShowing() { return mbShowing; }
1730 void removeListener()
1734 if ( mxComponent.is() && !mbDisposed )
1736 uno::Reference< awt::XTopWindow > xList( mxComponent, uno::UNO_QUERY_THROW );;
1737 OSL_TRACE("*********** Removing the listener");
1738 xList->removeTopWindowListener( this );
1739 mxComponent = NULL;
1742 catch( uno::Exception& ) {}
1744 virtual void SAL_CALL windowOpened( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException)
1746 if ( mpUserForm )
1748 mbOpened = sal_True;
1749 mbShowing = sal_True;
1750 if ( mbActivated )
1752 mbOpened = mbActivated = sal_False;
1753 mpUserForm->triggerActivateEvent();
1758 //liuchen 2009-7-21, support Excel VBA Form_QueryClose event
1759 virtual void SAL_CALL windowClosing( const lang::EventObject& e ) throw (uno::RuntimeException)
1761 uno::Reference< awt::XDialog > xDialog( e.Source, uno::UNO_QUERY );
1762 if ( xDialog.is() )
1764 uno::Reference< awt::XControl > xControl( xDialog, uno::UNO_QUERY );
1765 if ( xControl->getPeer().is() )
1767 uno::Reference< document::XVbaMethodParameter > xVbaMethodParameter( xControl->getPeer(), uno::UNO_QUERY );
1768 if ( xVbaMethodParameter.is() )
1770 sal_Int8 nCancel = 0;
1771 sal_Int8 nCloseMode = 0;
1773 Sequence< Any > aParams;
1774 aParams.realloc(2);
1775 aParams[0] <<= nCancel;
1776 aParams[1] <<= nCloseMode;
1778 mpUserForm->triggerMethod( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Userform_QueryClose") ),
1779 aParams);
1780 xVbaMethodParameter->setVbaMethodParameter( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Cancel")), aParams[0]);
1781 return;
1787 mpUserForm->triggerMethod( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Userform_QueryClose") ) );
1789 //liuchen 2009-7-21
1791 virtual void SAL_CALL windowClosed( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException) { mbOpened = sal_False; mbShowing = sal_False; }
1792 virtual void SAL_CALL windowMinimized( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException) {}
1793 virtual void SAL_CALL windowNormalized( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException){}
1794 virtual void SAL_CALL windowActivated( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException)
1796 if ( mpUserForm )
1798 mbActivated = sal_True;
1799 if ( mbOpened )
1801 mbOpened = mbActivated = sal_False;
1802 mpUserForm->triggerActivateEvent();
1807 virtual void SAL_CALL windowDeactivated( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException)
1809 if ( mpUserForm )
1810 mpUserForm->triggerDeActivateEvent();
1814 virtual void SAL_CALL disposing( const lang::EventObject& Source ) throw (uno::RuntimeException)
1816 OSL_TRACE("** Userform/Dialog disposing");
1817 mbDisposed = true;
1818 uno::Any aSource;
1819 aSource <<= Source;
1820 mxComponent = NULL;
1821 if ( mpUserForm )
1822 mpUserForm->ResetApiObj();
1826 SbUserFormModule::SbUserFormModule( const com::sun::star::script::ModuleInfo& mInfo, bool bIsCompat )
1827 :SbObjModule( mInfo, bIsCompat ), mbInit( false )
1829 m_xModel.set( mInfo.ModuleObject, uno::UNO_QUERY_THROW );
1832 void SbUserFormModule::ResetApiObj()
1834 if ( m_xDialog.is() ) // probably someone close the dialog window
1836 triggerTerminateEvent();
1838 pDocObject = NULL;
1839 m_xDialog = NULL;
1842 void SbUserFormModule::triggerMethod( const String& aMethodToRun )
1844 Sequence< Any > aArguments;
1845 triggerMethod( aMethodToRun, aArguments );
1847 void SbUserFormModule::triggerMethod( const String& aMethodToRun, Sequence< Any >& aArguments)
1849 OSL_TRACE("*** trigger %s ***", rtl::OUStringToOString( aMethodToRun, RTL_TEXTENCODING_UTF8 ).getStr() );
1850 // Search method
1851 SbxVariable* pMeth = SbObjModule::Find( aMethodToRun, SbxCLASS_METHOD );
1852 if( pMeth )
1854 //liuchen 2009-7-21, support Excel VBA UserForm_QueryClose event with parameters
1855 if ( aArguments.getLength() > 0 ) // Setup parameters
1857 SbxArrayRef xArray = new SbxArray;
1858 xArray->Put( pMeth, 0 ); // Method as parameter 0
1860 for ( sal_Int32 i = 0; i < aArguments.getLength(); ++i )
1862 SbxVariableRef xSbxVar = new SbxVariable( SbxVARIANT );
1863 unoToSbxValue( static_cast< SbxVariable* >( xSbxVar ), aArguments[i] );
1864 xArray->Put( xSbxVar, static_cast< USHORT >( i ) + 1 );
1866 // Enable passing by ref
1867 if ( xSbxVar->GetType() != SbxVARIANT )
1868 xSbxVar->SetFlag( SBX_FIXED );
1870 pMeth->SetParameters( xArray );
1872 SbxValues aVals;
1873 pMeth->Get( aVals );
1875 for ( sal_Int32 i = 0; i < aArguments.getLength(); ++i )
1877 aArguments[i] = sbxToUnoValue( xArray->Get( static_cast< USHORT >(i) + 1) );
1879 pMeth->SetParameters( NULL );
1881 else
1882 //liuchen 2009-7-21
1884 SbxValues aVals;
1885 pMeth->Get( aVals );
1890 void SbUserFormModule::triggerActivateEvent( void )
1892 OSL_TRACE("**** entering SbUserFormModule::triggerActivate");
1893 triggerMethod( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("UserForm_activate") ) );
1894 OSL_TRACE("**** leaving SbUserFormModule::triggerActivate");
1897 void SbUserFormModule::triggerDeActivateEvent( void )
1899 OSL_TRACE("**** SbUserFormModule::triggerDeActivate");
1900 triggerMethod( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Userform_DeActivate") ) );
1903 void SbUserFormModule::triggerInitializeEvent( void )
1906 if ( mbInit )
1907 return;
1908 OSL_TRACE("**** SbUserFormModule::triggerInitializeEvent");
1909 static String aInitMethodName( RTL_CONSTASCII_USTRINGPARAM("Userform_Initialize") );
1910 triggerMethod( aInitMethodName );
1911 mbInit = true;
1914 void SbUserFormModule::triggerTerminateEvent( void )
1916 OSL_TRACE("**** SbUserFormModule::triggerTerminateEvent");
1917 static String aTermMethodName( RTL_CONSTASCII_USTRINGPARAM("Userform_Terminate") );
1918 triggerMethod( aTermMethodName );
1919 mbInit=false;
1922 void SbUserFormModule::load()
1924 OSL_TRACE("** load() ");
1925 // forces a load
1926 if ( !pDocObject )
1927 InitObject();
1930 //liuchen 2009-7-21 change to accmordate VBA's beheavior
1931 void SbUserFormModule::Unload()
1933 OSL_TRACE("** Unload() ");
1935 sal_Int8 nCancel = 0;
1936 sal_Int8 nCloseMode = 1;
1938 Sequence< Any > aParams;
1939 aParams.realloc(2);
1940 aParams[0] <<= nCancel;
1941 aParams[1] <<= nCloseMode;
1943 triggerMethod( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Userform_QueryClose") ), aParams);
1945 aParams[0] >>= nCancel;
1946 if (nCancel == 1)
1948 return;
1951 if ( m_xDialog.is() )
1953 triggerTerminateEvent();
1955 // Search method
1956 SbxVariable* pMeth = SbObjModule::Find( String( RTL_CONSTASCII_USTRINGPARAM( "UnloadObject" ) ), SbxCLASS_METHOD );
1957 if( pMeth )
1959 OSL_TRACE("Attempting too run the UnloadObjectMethod");
1960 m_xDialog = NULL; //release ref to the uno object
1961 SbxValues aVals;
1962 FormObjEventListenerImpl* pFormListener = dynamic_cast< FormObjEventListenerImpl* >( m_DialogListener.get() );
1963 bool bWaitForDispose = true; // assume dialog is showing
1964 if ( pFormListener )
1966 bWaitForDispose = pFormListener->isShowing();
1967 OSL_TRACE("Showing %d", bWaitForDispose );
1969 pMeth->Get( aVals);
1970 if ( !bWaitForDispose )
1972 // we've either already got a dispose or we'er never going to get one
1973 ResetApiObj();
1974 } // else wait for dispose
1975 OSL_TRACE("UnloadObject completed ( we hope )");
1978 //liuchen
1980 void SbUserFormModule::InitObject()
1985 String aHook( RTL_CONSTASCII_USTRINGPARAM( "VBAGlobals" ) );
1986 SbUnoObject* pGlobs = (SbUnoObject*)GetParent()->Find( aHook, SbxCLASS_DONTCARE );
1987 if ( m_xModel.is() && pGlobs )
1990 uno::Reference< lang::XMultiServiceFactory > xVBAFactory( pGlobs->getUnoAny(), uno::UNO_QUERY_THROW );
1991 uno::Reference< lang::XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
1992 uno::Sequence< uno::Any > aArgs(1);
1993 aArgs[ 0 ] <<= m_xModel;
1994 rtl::OUString sDialogUrl( RTL_CONSTASCII_USTRINGPARAM("vnd.sun.star.script:" ) );
1995 rtl::OUString sProjectName( RTL_CONSTASCII_USTRINGPARAM("Standard") );
1996 if ( this->GetParent()->GetName().Len() )
1997 sProjectName = this->GetParent()->GetName();
1998 sDialogUrl = sDialogUrl.concat( sProjectName ).concat( rtl::OUString( '.') ).concat( GetName() ).concat( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("?location=document") ) );
2000 uno::Reference< awt::XDialogProvider > xProvider( xFactory->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.DialogProvider")), aArgs ), uno::UNO_QUERY_THROW );
2001 m_xDialog = xProvider->createDialog( sDialogUrl );
2003 // create vba api object
2004 aArgs.realloc( 3 );
2005 aArgs[ 0 ] = uno::Any();
2006 aArgs[ 1 ] <<= m_xDialog;
2007 aArgs[ 2 ] <<= m_xModel;
2008 pDocObject = new SbUnoObject( GetName(), uno::makeAny( xVBAFactory->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.msforms.UserForm")), aArgs ) ) );
2009 uno::Reference< lang::XComponent > xComponent( aArgs[ 1 ], uno::UNO_QUERY_THROW );
2010 // remove old listener if it exists
2011 FormObjEventListenerImpl* pFormListener = dynamic_cast< FormObjEventListenerImpl* >( m_DialogListener.get() );
2012 if ( pFormListener )
2013 pFormListener->removeListener();
2014 m_DialogListener = new FormObjEventListenerImpl( this, xComponent );
2016 triggerInitializeEvent();
2019 catch( uno::Exception& e )
2025 SbxVariable*
2026 SbUserFormModule::Find( const XubString& rName, SbxClassType t )
2028 if ( !pDocObject && !GetSbData()->bRunInit && pINST )
2029 InitObject();
2030 return SbObjModule::Find( rName, t );
2032 /////////////////////////////////////////////////////////////////////////
2034 SbProperty::SbProperty( const String& r, SbxDataType t, SbModule* p )
2035 : SbxProperty( r, t ), pMod( p )
2037 bInvalid = FALSE;
2040 SbProperty::~SbProperty()
2043 /////////////////////////////////////////////////////////////////////////
2045 SbProcedureProperty::~SbProcedureProperty()