blob: 0a1c9a796d6e74d9b1bc7e51955c71da881e2d7d [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_basic.hxx"
#include <tools/shl.hxx>
#include <tools/stream.hxx>
#include <basic/sbx.hxx>
#include <basic/sbxfac.hxx>
#include <basic/sbxbase.hxx>
// AppData-Struktur fuer SBX:
SV_IMPL_PTRARR(SbxParams,SbxParamInfo*);
SV_IMPL_PTRARR(SbxFacs,SbxFactory*);
TYPEINIT0(SbxBase)
// SBX-Daten anfordern oder ggf. anlegen
// wir legen den Bereich einfach an und verzichten auf die Freigabe!
SbxAppData* GetSbxData_Impl()
{
SbxAppData** ppData = (SbxAppData**) ::GetAppData( SHL_SBX );
SbxAppData* p = *ppData;
if( !p )
p = *ppData = new SbxAppData;
return p;
}
SbxAppData::~SbxAppData()
{
if( pBasicFormater )
delete pBasicFormater;
}
//////////////////////////////// SbxBase /////////////////////////////////
DBG_NAME(SbxBase);
SbxBase::SbxBase()
{
DBG_CTOR( SbxBase, 0 );
nFlags = SBX_READWRITE;
}
SbxBase::SbxBase( const SbxBase& r )
: SvRefBase( r )
{
DBG_CTOR( SbxBase, 0 );
nFlags = r.nFlags;
}
SbxBase::~SbxBase()
{
DBG_DTOR(SbxBase,0);
}
SbxBase& SbxBase::operator=( const SbxBase& r )
{
DBG_CHKTHIS( SbxBase, 0 );
nFlags = r.nFlags;
return *this;
}
SbxDataType SbxBase::GetType() const
{
DBG_CHKTHIS( SbxBase, 0 );
return SbxEMPTY;
}
SbxClassType SbxBase::GetClass() const
{
DBG_CHKTHIS( SbxBase, 0 );
return SbxCLASS_DONTCARE;
}
void SbxBase::Clear()
{
DBG_CHKTHIS( SbxBase, 0 );
}
sal_Bool SbxBase::IsFixed() const
{
DBG_CHKTHIS( SbxBase, 0 );
return IsSet( SBX_FIXED );
}
void SbxBase::SetModified( sal_Bool b )
{
DBG_CHKTHIS( SbxBase, 0 );
if( IsSet( SBX_NO_MODIFY ) )
return;
if( b )
SetFlag( SBX_MODIFIED );
else
ResetFlag( SBX_MODIFIED );
}
SbxError SbxBase::GetError()
{
return GetSbxData_Impl()->eSbxError;
}
void SbxBase::SetError( SbxError e )
{
SbxAppData* p = GetSbxData_Impl();
if( e && p->eSbxError == SbxERR_OK )
p->eSbxError = e;
}
sal_Bool SbxBase::IsError()
{
return sal_Bool( GetSbxData_Impl()->eSbxError != SbxERR_OK );
}
void SbxBase::ResetError()
{
GetSbxData_Impl()->eSbxError = SbxERR_OK;
}
void SbxBase::AddFactory( SbxFactory* pFac )
{
SbxAppData* p = GetSbxData_Impl();
const SbxFactory* pTemp = pFac;
// AB, 6.3.96: HandleLast-Flag beruecksichtigen
sal_uInt16 nPos = p->aFacs.Count(); // Einfuege-Position
if( !pFac->IsHandleLast() ) // Nur, wenn nicht selbst HandleLast
{
// Neue Factory vor Factories mit HandleLast einordnen
while( nPos > 0 &&
(static_cast<SbxFactory*>(p->aFacs.GetObject( nPos-1 )))->IsHandleLast() )
nPos--;
}
p->aFacs.Insert( pTemp, nPos );
}
void SbxBase::RemoveFactory( SbxFactory* pFac )
{
SbxAppData* p = GetSbxData_Impl();
for( sal_uInt16 i = 0; i < p->aFacs.Count(); i++ )
{
if( p->aFacs.GetObject( i ) == pFac )
{
p->aFacs.Remove( i, 1 ); break;
}
}
}
SbxBase* SbxBase::Create( sal_uInt16 nSbxId, sal_uInt32 nCreator )
{
// #91626: Hack to skip old Basic dialogs
// Problem: There does not exist a factory any more,
// so we have to create a dummy SbxVariable instead
if( nSbxId == 0x65 ) // Dialog Id
return new SbxVariable;
XubString aEmptyStr;
if( nCreator == SBXCR_SBX )
switch( nSbxId )
{
case SBXID_VALUE: return new SbxValue;
case SBXID_VARIABLE: return new SbxVariable;
case SBXID_ARRAY: return new SbxArray;
case SBXID_DIMARRAY: return new SbxDimArray;
case SBXID_OBJECT: return new SbxObject( aEmptyStr );
case SBXID_COLLECTION: return new SbxCollection( aEmptyStr );
case SBXID_FIXCOLLECTION:
return new SbxStdCollection( aEmptyStr, aEmptyStr );
case SBXID_METHOD: return new SbxMethod( aEmptyStr, SbxEMPTY );
case SBXID_PROPERTY: return new SbxProperty( aEmptyStr, SbxEMPTY );
}
// Unbekanter Typ: ber die Factories gehen!
SbxAppData* p = GetSbxData_Impl();
SbxBase* pNew = NULL;
for( sal_uInt16 i = 0; i < p->aFacs.Count(); i++ )
{
SbxFactory* pFac = p->aFacs.GetObject( i );
pNew = pFac->Create( nSbxId, nCreator );
if( pNew )
break;
}
#ifdef DBG_UTIL
if( !pNew )
{
ByteString aMsg( "SBX: Keine Factory fuer SBX-ID " );
aMsg += ByteString::CreateFromInt32(nSbxId);
DbgError( aMsg.GetBuffer() );
}
#endif
return pNew;
}
SbxObject* SbxBase::CreateObject( const XubString& rClass )
{
SbxAppData* p = GetSbxData_Impl();
SbxObject* pNew = NULL;
for( sal_uInt16 i = 0; i < p->aFacs.Count(); i++ )
{
pNew = p->aFacs.GetObject( i )->CreateObject( rClass );
if( pNew )
break;
}
#ifdef DBG_UTIL
if( !pNew )
{
ByteString aMsg( "SBX: Keine Factory fuer Objektklasse " );
ByteString aClassStr( (const UniString&)rClass, RTL_TEXTENCODING_ASCII_US );
aMsg += aClassStr;
DbgError( (const char*)aMsg.GetBuffer() );
}
#endif
return pNew;
}
static sal_Bool bStaticEnableBroadcasting = sal_True;
// Sbx-Loesung als Ersatz fuer SfxBroadcaster::Enable()
void SbxBase::StaticEnableBroadcasting( sal_Bool bEnable )
{
bStaticEnableBroadcasting = bEnable;
}
sal_Bool SbxBase::StaticIsEnabledBroadcasting( void )
{
return bStaticEnableBroadcasting;
}
SbxBase* SbxBase::Load( SvStream& rStrm )
{
sal_uInt16 nSbxId, nFlags, nVer;
sal_uInt32 nCreator, nSize;
rStrm >> nCreator >> nSbxId >> nFlags >> nVer;
// Eine Dummheit meinerseits korrigieren:
if( nFlags & SBX_RESERVED )
nFlags = ( nFlags & ~SBX_RESERVED ) | SBX_GBLSEARCH;
sal_uIntPtr nOldPos = rStrm.Tell();
rStrm >> nSize;
SbxBase* p = Create( nSbxId, nCreator );
if( p )
{
p->nFlags = nFlags;
if( p->LoadData( rStrm, nVer ) )
{
sal_uIntPtr nNewPos = rStrm.Tell();
nOldPos += nSize;
DBG_ASSERT( nOldPos >= nNewPos, "SBX: Zu viele Daten eingelesen" );
if( nOldPos != nNewPos )
rStrm.Seek( nOldPos );
if( !p->LoadCompleted() )
{
// Loeschen des Objekts
SbxBaseRef aRef( p );
p = NULL;
}
}
else
{
rStrm.SetError( SVSTREAM_FILEFORMAT_ERROR );
// Loeschen des Objekts
SbxBaseRef aRef( p );
p = NULL;
}
}
else
rStrm.SetError( SVSTREAM_FILEFORMAT_ERROR );
return p;
}
// Sbx-Objekt im Stream ueberspringen
void SbxBase::Skip( SvStream& rStrm )
{
sal_uInt16 nSbxId, nFlags, nVer;
sal_uInt32 nCreator, nSize;
rStrm >> nCreator >> nSbxId >> nFlags >> nVer;
sal_uIntPtr nStartPos = rStrm.Tell();
rStrm >> nSize;
rStrm.Seek( nStartPos + nSize );
}
sal_Bool SbxBase::Store( SvStream& rStrm )
{
DBG_CHKTHIS( SbxBase, 0 );
if( !( nFlags & SBX_DONTSTORE ) )
{
rStrm << (sal_uInt32) GetCreator()
<< (sal_uInt16) GetSbxId()
<< (sal_uInt16) GetFlags()
<< (sal_uInt16) GetVersion();
sal_uIntPtr nOldPos = rStrm.Tell();
rStrm << (sal_uInt32) 0L;
sal_Bool bRes = StoreData( rStrm );
sal_uIntPtr nNewPos = rStrm.Tell();
rStrm.Seek( nOldPos );
rStrm << (sal_uInt32) ( nNewPos - nOldPos );
rStrm.Seek( nNewPos );
if( rStrm.GetError() != SVSTREAM_OK )
bRes = sal_False;
if( bRes )
bRes = StoreCompleted();
return bRes;
}
else
return sal_True;
}
sal_Bool SbxBase::LoadData( SvStream&, sal_uInt16 )
{
DBG_CHKTHIS( SbxBase, 0 );
return sal_False;
}
sal_Bool SbxBase::StoreData( SvStream& ) const
{
DBG_CHKTHIS( SbxBase, 0 );
return sal_False;
}
sal_Bool SbxBase::LoadPrivateData( SvStream&, sal_uInt16 )
{
DBG_CHKTHIS( SbxBase, 0 );
return sal_True;
}
sal_Bool SbxBase::StorePrivateData( SvStream& ) const
{
DBG_CHKTHIS( SbxBase, 0 );
return sal_True;
}
sal_Bool SbxBase::LoadCompleted()
{
DBG_CHKTHIS( SbxBase, 0 );
return sal_True;
}
sal_Bool SbxBase::StoreCompleted()
{
DBG_CHKTHIS( SbxBase, 0 );
return sal_True;
}
//////////////////////////////// SbxFactory ////////////////////////////////
SbxBase* SbxFactory::Create( sal_uInt16, sal_uInt32 )
{
return NULL;
}
SbxObject* SbxFactory::CreateObject( const XubString& )
{
return NULL;
}
///////////////////////////////// SbxInfo //////////////////////////////////
SbxInfo::~SbxInfo()
{}
void SbxInfo::AddParam
( const XubString& rName, SbxDataType eType, sal_uInt16 nFlags )
{
const SbxParamInfo* p = new SbxParamInfo( rName, eType, nFlags );
aParams.Insert( p, aParams.Count() );
}
void SbxInfo::AddParam( const SbxParamInfo& r )
{
const SbxParamInfo* p = new SbxParamInfo
( r.aName, r.eType, r.nFlags, r.aTypeRef );
aParams.Insert( p, aParams.Count() );
}
const SbxParamInfo* SbxInfo::GetParam( sal_uInt16 n ) const
{
if( n < 1 || n > aParams.Count() )
return NULL;
else
return aParams.GetObject( n-1 );
}
sal_Bool SbxInfo::LoadData( SvStream& rStrm, sal_uInt16 nVer )
{
aParams.Remove( 0, aParams.Count() );
sal_uInt16 nParam;
rStrm.ReadByteString( aComment, RTL_TEXTENCODING_ASCII_US );
rStrm.ReadByteString( aHelpFile, RTL_TEXTENCODING_ASCII_US );
rStrm >> nHelpId >> nParam;
while( nParam-- )
{
XubString aName;
sal_uInt16 nType, nFlags;
sal_uInt32 nUserData = 0;
rStrm.ReadByteString( aName, RTL_TEXTENCODING_ASCII_US );
rStrm >> nType >> nFlags;
if( nVer > 1 )
rStrm >> nUserData;
AddParam( aName, (SbxDataType) nType, nFlags );
SbxParamInfo* p = aParams.GetObject( aParams.Count() - 1 );
p->nUserData = nUserData;
}
return sal_True;
}
sal_Bool SbxInfo::StoreData( SvStream& rStrm ) const
{
rStrm.WriteByteString( aComment, RTL_TEXTENCODING_ASCII_US );
rStrm.WriteByteString( aHelpFile, RTL_TEXTENCODING_ASCII_US );
rStrm << nHelpId << aParams.Count();
for( sal_uInt16 i = 0; i < aParams.Count(); i++ )
{
SbxParamInfo* p = aParams.GetObject( i );
rStrm.WriteByteString( p->aName, RTL_TEXTENCODING_ASCII_US );
rStrm << (sal_uInt16) p->eType
<< (sal_uInt16) p->nFlags
<< (sal_uInt32) p->nUserData;
}
return sal_True;
}