summaryrefslogtreecommitdiff
path: root/basic
diff options
context:
space:
mode:
Diffstat (limited to 'basic')
-rw-r--r--basic/source/sbx/sbxvar.cxx608
1 files changed, 608 insertions, 0 deletions
diff --git a/basic/source/sbx/sbxvar.cxx b/basic/source/sbx/sbxvar.cxx
new file mode 100644
index 000000000000..a040d2706f7e
--- /dev/null
+++ b/basic/source/sbx/sbxvar.cxx
@@ -0,0 +1,608 @@
+/*************************************************************************
+ *
+ * $RCSfile: sbxvar.cxx,v $
+ *
+ * $Revision: 1.2 $
+ *
+ * last change: $Author: obo $ $Date: 2005-04-13 09:27:02 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (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.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+
+#ifndef _STREAM_HXX //autogen
+#include <tools/stream.hxx>
+#endif
+#include "svtools/brdcst.hxx"
+
+#include "sbx.hxx"
+#include "sbxbase.hxx"
+#include "sbxres.hxx"
+#include "sbxconv.hxx"
+#include <math.h>
+#include <ctype.h>
+
+///////////////////////////// SbxVariable //////////////////////////////
+
+TYPEINIT1(SbxVariable,SbxValue)
+TYPEINIT1(SbxHint,SfxSimpleHint)
+
+extern UINT32 nVarCreator; // in SBXBASE.CXX, fuer LoadData()
+#ifdef DBG_UTIL
+static ULONG nVar = 0;
+#endif
+
+///////////////////////////// Konstruktoren //////////////////////////////
+
+SbxVariable::SbxVariable() : SbxValue()
+{
+ pCst = NULL;
+ pParent = NULL;
+ nUserData = 0;
+ nHash = 0;
+#ifdef DBG_UTIL
+ DbgOutf( "SbxVariable::Ctor %lx=%ld", (void*)this, ++nVar );
+ GetSbxData_Impl()->aVars.Insert( this, LIST_APPEND );
+#endif
+}
+
+SbxVariable::SbxVariable( const SbxVariable& r )
+ : SbxValue( r ), pPar( r.pPar ), pInfo( r.pInfo )
+{
+ pCst = NULL;
+ if( r.CanRead() )
+ {
+ pParent = r.pParent;
+ nUserData = r.nUserData;
+ aName = r.aName;
+ nHash = r.nHash;
+ }
+ else
+ {
+ pParent = NULL;
+ nUserData = 0;
+ nHash = 0;
+ }
+#ifdef DBG_UTIL
+ static sal_Char const aCellsStr[] = "Cells";
+ if ( aName.EqualsAscii( aCellsStr ) )
+ aName.AssignAscii( aCellsStr, sizeof( aCellsStr )-1 );
+ DbgOutf( "SbxVariable::Ctor %lx=%ld", (void*)this, ++nVar );
+ GetSbxData_Impl()->aVars.Insert( this, LIST_APPEND );
+#endif
+}
+
+SbxVariable::SbxVariable( SbxDataType t, void* p ) : SbxValue( t, p )
+{
+ pCst = NULL;
+ pParent = NULL;
+ nUserData = 0;
+ nHash = 0;
+#ifdef DBG_UTIL
+ DbgOutf( "SbxVariable::Ctor %lx=%ld", (void*)this, ++nVar );
+ GetSbxData_Impl()->aVars.Insert( this, LIST_APPEND );
+#endif
+}
+
+SbxVariable::~SbxVariable()
+{
+#ifdef DBG_UTIL
+ ByteString aBStr( (const UniString&)aName, RTL_TEXTENCODING_ASCII_US );
+ DbgOutf( "SbxVariable::Dtor %lx (%s)", (void*)this, aBStr.GetBuffer() );
+ static sal_Char const aCellsStr[] = "Cells";
+ if ( aName.EqualsAscii( aCellsStr ) )
+ aName.AssignAscii( aCellsStr, sizeof( aCellsStr )-1 );
+ GetSbxData_Impl()->aVars.Remove( this );
+#endif
+ delete pCst;
+}
+
+////////////////////////////// Broadcasting //////////////////////////////
+
+SfxBroadcaster& SbxVariable::GetBroadcaster()
+{
+ if( !pCst )
+ pCst = new SfxBroadcaster;
+ return *pCst;
+}
+
+// Eines Tages kann man vielleicht den Parameter 0 schleifen,
+// dann entfaellt die Kopiererei...
+
+void SbxVariable::Broadcast( ULONG nHintId )
+{
+#if SUPD >= 507
+ if( pCst && !IsSet( SBX_NO_BROADCAST ) && StaticIsEnabledBroadcasting() )
+#else
+ if( pCst && !IsSet( SBX_NO_BROADCAST ) )
+#endif
+ {
+ // Da die Methode von aussen aufrufbar ist, hier noch einmal
+ // die Berechtigung testen
+ if( nHintId & SBX_HINT_DATAWANTED )
+ if( !CanRead() )
+ return;
+ if( nHintId & SBX_HINT_DATACHANGED )
+ if( !CanWrite() )
+ return;
+ // Weitere Broadcasts verhindern
+ SfxBroadcaster* pSave = pCst;
+ pCst = NULL;
+ USHORT nSaveFlags = GetFlags();
+ SetFlag( SBX_READWRITE );
+ if( pPar.Is() )
+ // this, als Element 0 eintragen, aber den Parent nicht umsetzen!
+ pPar->GetRef( 0 ) = this;
+ pSave->Broadcast( SbxHint( nHintId, this ) );
+ delete pCst; // wer weiss schon, auf welche Gedanken mancher kommt?
+ pCst = pSave;
+ SetFlags( nSaveFlags );
+ }
+}
+
+SbxInfo* SbxVariable::GetInfo()
+{
+ if( !pInfo )
+ {
+ Broadcast( SBX_HINT_INFOWANTED );
+ if( pInfo.Is() )
+ SetModified( TRUE );
+ }
+ return pInfo;
+}
+
+/////////////////////////// Name der Variablen ///////////////////////////
+
+void SbxVariable::SetName( const XubString& rName )
+{
+ aName = rName;
+ nHash = MakeHashCode( rName );
+}
+
+const XubString& SbxVariable::GetName( SbxNameType t ) const
+{
+ static char cSuffixes[] = " %&!#@ $";
+ if( t == SbxNAME_NONE )
+ return aName;
+ // Parameter-Infos anfordern (nicht fuer Objekte)
+ ((SbxVariable*)this)->GetInfo();
+ // Nix anfuegen, wenn einfache Property (keine leeren Klammern)
+ if( !pInfo
+ || ( !pInfo->aParams.Count() && GetClass() == SbxCLASS_PROPERTY ) )
+ return aName;
+ xub_Unicode cType = ' ';
+ XubString aTmp( aName );
+ // Kurzer Typ? Dann holen, evtl. ist dieser 0.
+ short et = GetType();
+ if( t == SbxNAME_SHORT_TYPES )
+ {
+ if( et <= SbxSTRING )
+ cType = cSuffixes[ et ];
+ if( cType != ' ' )
+ aTmp += cType;
+ }
+ aTmp += '(';
+ for( USHORT i = 0; i < pInfo->aParams.Count(); i++ )
+ {
+ const SbxParamInfo* q = pInfo->aParams.GetObject( i );
+ short nt = q->eType & 0x0FFF;
+ if( i )
+ aTmp += ',';
+ if( q->nFlags & SBX_OPTIONAL )
+ aTmp += SbxRes( STRING_OPTIONAL );
+ if( q->eType & SbxBYREF )
+ aTmp += SbxRes( STRING_BYREF );
+ aTmp += q->aName;
+ cType = ' ';
+ // Kurzer Typ? Dann holen, evtl. ist dieser 0.
+ if( t == SbxNAME_SHORT_TYPES )
+ {
+ if( nt <= SbxSTRING )
+ cType = cSuffixes[ nt ];
+ }
+ if( cType != ' ' )
+ {
+ aTmp += cType;
+ if( q->eType & SbxARRAY )
+ aTmp.AppendAscii( "()" );
+ }
+ else
+ {
+ if( q->eType & SbxARRAY )
+ aTmp.AppendAscii( "()" );
+ // langer Typ?
+ if( t != SbxNAME_SHORT )
+ {
+ aTmp += SbxRes( STRING_AS );
+ if( nt < 32 )
+ aTmp += SbxRes( STRING_TYPES + nt );
+ else
+ aTmp += SbxRes( STRING_ANY );
+ }
+ }
+ }
+ aTmp += ')';
+ // Langer Typ? Dann holen
+ if( t == SbxNAME_LONG_TYPES && et != SbxEMPTY )
+ {
+ aTmp += SbxRes( STRING_AS );
+ if( et < 32 )
+ aTmp += SbxRes( STRING_TYPES + et );
+ else
+ aTmp += SbxRes( STRING_ANY );
+ }
+ ((SbxVariable*) this)->aPic = aTmp;
+ return aPic;
+}
+
+// Einen simplen Hashcode erzeugen: Es werden die ersten 6 Zeichen gewertet.
+
+USHORT SbxVariable::MakeHashCode( const XubString& rName )
+{
+ USHORT n = 0;
+ USHORT nLen = rName.Len();
+ if( nLen > 6 )
+ nLen = 6;
+ const xub_Unicode* p = rName.GetBuffer();
+ while( nLen-- )
+ {
+ BYTE c = (BYTE)*p;
+ p++;
+ // Falls wir ein Schweinezeichen haben, abbrechen!!
+ if( c >= 0x80 )
+ return 0;
+ n = ( n << 3 ) + toupper( c );
+ }
+ return n;
+}
+
+////////////////////////////// Operatoren ////////////////////////////////
+
+SbxVariable& SbxVariable::operator=( const SbxVariable& r )
+{
+ SbxValue::operator=( r );
+ return *this;
+}
+
+//////////////////////////////// Konversion ////////////////////////////////
+
+SbxDataType SbxVariable::GetType() const
+{
+ if( aData.eType == SbxOBJECT )
+ return aData.pObj ? aData.pObj->GetType() : SbxOBJECT;
+ else if( aData.eType == SbxVARIANT )
+ return aData.pObj ? aData.pObj->GetType() : SbxVARIANT;
+ else
+ return aData.eType;
+}
+
+SbxClassType SbxVariable::GetClass() const
+{
+ return SbxCLASS_VARIABLE;
+}
+
+void SbxVariable::SetModified( BOOL b )
+{
+ if( IsSet( SBX_NO_MODIFY ) )
+ return;
+ SbxBase::SetModified( b );
+ if( pParent && pParent != this ) //??? HotFix: Rekursion raus MM
+ pParent->SetModified( b );
+}
+
+void SbxVariable::SetParent( SbxObject* p )
+{
+#ifdef DBG_UTIL
+ // wird der Parent eines SbxObjects gesetzt?
+ if ( p && ISA(SbxObject) )
+ {
+ // dann mu\s dieses auch Child vom neuen Parent sein
+ BOOL bFound = FALSE;
+ SbxArray *pChilds = p->GetObjects();
+ if ( pChilds )
+ {
+ for ( USHORT nIdx = 0; !bFound && nIdx < pChilds->Count(); ++nIdx )
+ bFound = ( this == pChilds->Get(nIdx) );
+ }
+ if ( !bFound )
+ {
+ String aMsg = String::CreateFromAscii( "dangling: [" );
+ aMsg += GetName();
+ aMsg.AppendAscii( "].SetParent([" );
+ aMsg += p->GetName();
+ aMsg.AppendAscii( "])" );
+ ByteString aBStr( (const UniString&)aMsg, RTL_TEXTENCODING_ASCII_US );
+ DbgOut( aBStr.GetBuffer(), DBG_OUT_WARNING, __FILE__, __LINE__);
+ }
+ }
+#endif
+
+ pParent = p;
+}
+
+////////////////////////////// Laden/Speichern /////////////////////////////
+
+BOOL SbxVariable::LoadData( SvStream& rStrm, USHORT nVer )
+{
+ UINT16 nType;
+ BYTE cMark;
+ rStrm >> cMark;
+ if( cMark == 0xFF )
+ {
+ if( !SbxValue::LoadData( rStrm, nVer ) )
+ return FALSE;
+ rStrm.ReadByteString( aName, RTL_TEXTENCODING_ASCII_US );
+ rStrm >> nUserData;
+ }
+ else
+ {
+ rStrm.SeekRel( -1L );
+ rStrm >> nType;
+ rStrm.ReadByteString( aName, RTL_TEXTENCODING_ASCII_US );
+ rStrm >> nUserData;
+ // Korrektur: Alte Methoden haben statt SbxNULL jetzt SbxEMPTY
+ if( nType == SbxNULL && GetClass() == SbxCLASS_METHOD )
+ nType = SbxEMPTY;
+ SbxValues aTmp;
+ XubString aVal;
+ aTmp.eType = aData.eType = (SbxDataType) nType;
+ aTmp.pString = &aVal;
+ switch( nType )
+ {
+ case SbxBOOL:
+ case SbxERROR:
+ case SbxINTEGER:
+ rStrm >> aTmp.nInteger; break;
+ case SbxLONG:
+ rStrm >> aTmp.nLong; break;
+ case SbxSINGLE:
+ {
+ // Floats als ASCII
+ rStrm.ReadByteString( aVal, RTL_TEXTENCODING_ASCII_US );
+ double d;
+ SbxDataType t;
+ if( ImpScan( aVal, d, t, NULL ) != SbxERR_OK || t == SbxDOUBLE )
+ {
+ aTmp.nSingle = 0;
+ return FALSE;
+ }
+ aTmp.nSingle = (float) d;
+ break;
+ }
+ case SbxDATE:
+ case SbxDOUBLE:
+ {
+ // Floats als ASCII
+ rStrm.ReadByteString( aVal, RTL_TEXTENCODING_ASCII_US );
+ SbxDataType t;
+ if( ImpScan( aVal, aTmp.nDouble, t, NULL ) != SbxERR_OK )
+ {
+ aTmp.nDouble = 0;
+ return FALSE;
+ }
+ break;
+ }
+ case SbxSTRING:
+ rStrm.ReadByteString( aVal, RTL_TEXTENCODING_ASCII_US );
+ break;
+ case SbxEMPTY:
+ case SbxNULL:
+ break;
+ default:
+ aData.eType = SbxNULL;
+ DBG_ASSERT( !this, "Nicht unterstuetzer Datentyp geladen" );
+ return FALSE;
+ }
+ // Wert putten
+ if( nType != SbxNULL && nType != SbxEMPTY && !Put( aTmp ) )
+ return FALSE;
+ }
+ rStrm >> cMark;
+ // cMark ist auch eine Versionsnummer!
+ // 1: initial version
+ // 2: mit nUserData
+ if( cMark )
+ {
+ if( cMark > 2 )
+ return FALSE;
+ pInfo = new SbxInfo;
+ pInfo->LoadData( rStrm, (USHORT) cMark );
+ }
+ // Privatdaten nur laden, wenn es eine SbxVariable ist
+ if( GetClass() == SbxCLASS_VARIABLE && !LoadPrivateData( rStrm, nVer ) )
+ return FALSE;
+ ((SbxVariable*) this)->Broadcast( SBX_HINT_DATACHANGED );
+ nHash = MakeHashCode( aName );
+ SetModified( TRUE );
+ return TRUE;
+}
+
+BOOL SbxVariable::StoreData( SvStream& rStrm ) const
+{
+ rStrm << (BYTE) 0xFF; // Marker
+ BOOL bValStore;
+ if( this->IsA( TYPE(SbxMethod) ) )
+ {
+ // #50200 Verhindern, dass Objekte, die zur Laufzeit als Return-Wert
+ // in der Methode als Value gespeichert sind, mit gespeichert werden
+ SbxVariable* pThis = (SbxVariable*)this;
+ USHORT nSaveFlags = GetFlags();
+ pThis->SetFlag( SBX_WRITE );
+ pThis->SbxValue::Clear();
+ pThis->SetFlags( nSaveFlags );
+
+ // Damit die Methode in keinem Fall ausgefuehrt wird!
+ // CAST, um const zu umgehen!
+ pThis->SetFlag( SBX_NO_BROADCAST );
+ bValStore = SbxValue::StoreData( rStrm );
+ pThis->ResetFlag( SBX_NO_BROADCAST );
+ }
+ else
+ bValStore = SbxValue::StoreData( rStrm );
+ if( !bValStore )
+ return FALSE;
+ // if( !SbxValue::StoreData( rStrm ) )
+ // return FALSE;
+ rStrm.WriteByteString( aName, RTL_TEXTENCODING_ASCII_US );
+ rStrm << nUserData;
+ if( pInfo.Is() )
+ {
+ rStrm << (BYTE) 2; // Version 2: mit UserData!
+ pInfo->StoreData( rStrm );
+ }
+ else
+ rStrm << (BYTE) 0;
+ // Privatdaten nur speichern, wenn es eine SbxVariable ist
+ if( GetClass() == SbxCLASS_VARIABLE )
+ return StorePrivateData( rStrm );
+ else
+ return TRUE;
+}
+
+////////////////////////////// SbxInfo ///////////////////////////////////
+
+SbxInfo::SbxInfo() : aHelpFile(), nHelpId( 0 ), aParams()
+{}
+
+SbxInfo::SbxInfo( const String& r, UINT32 n )
+ : aHelpFile( r ), nHelpId( n ), aParams()
+{}
+
+////////////////////////////// SbxAlias //////////////////////////////////
+
+SbxAlias::SbxAlias( const XubString& rName, SbxVariable* p )
+ : SbxVariable(), xAlias( p )
+{
+ SetName( rName );
+ SetFlags( p->GetFlags() );
+ SetFlag( SBX_DONTSTORE );
+ aData.eType = p->GetType();
+ StartListening( p->GetBroadcaster() );
+}
+
+SbxAlias::SbxAlias( const SbxAlias& r )
+ : SbxVariable( r ), xAlias( r.xAlias )
+{}
+
+SbxAlias& SbxAlias::operator=( const SbxAlias& r )
+{
+ xAlias = r.xAlias;
+ return *this;
+}
+
+SbxAlias::~SbxAlias()
+{
+ if( xAlias.Is() )
+ EndListening( xAlias->GetBroadcaster() );
+}
+
+void SbxAlias::Broadcast( ULONG nHt )
+{
+#if SUPD >= 507
+ if( xAlias.Is() && StaticIsEnabledBroadcasting() )
+#else
+ if( xAlias.Is() )
+#endif
+ {
+ xAlias->SetParameters( GetParameters() );
+ if( nHt == SBX_HINT_DATAWANTED )
+ SbxVariable::operator=( *xAlias );
+ else if( nHt == SBX_HINT_DATACHANGED || nHt == SBX_HINT_CONVERTED )
+ *xAlias = *this;
+ else if( nHt == SBX_HINT_INFOWANTED )
+ {
+ xAlias->Broadcast( nHt );
+ pInfo = xAlias->GetInfo();
+ }
+ }
+}
+
+void SbxAlias::SFX_NOTIFY( SfxBroadcaster&, const TypeId&,
+ const SfxHint& rHint, const TypeId& )
+{
+ const SbxHint* p = PTR_CAST(SbxHint,&rHint);
+ if( p && p->GetId() == SBX_HINT_DYING )
+ {
+ xAlias.Clear();
+ // Alias loeschen?
+ if( pParent )
+ pParent->Remove( this );
+ }
+}
+
+void SbxVariable::Dump( SvStream& rStrm, BOOL bFill )
+{
+ ByteString aBNameStr( (const UniString&)GetName( SbxNAME_SHORT_TYPES ), RTL_TEXTENCODING_ASCII_US );
+ rStrm << "Variable( "
+ << ByteString::CreateFromInt64( (ULONG) this ).GetBuffer() << "=="
+ << aBNameStr.GetBuffer();
+ ByteString aBParentNameStr( (const UniString&)GetParent()->GetName(), RTL_TEXTENCODING_ASCII_US );
+ if ( GetParent() )
+ rStrm << " in parent '" << aBParentNameStr.GetBuffer() << "'";
+ else
+ rStrm << " no parent";
+ rStrm << " ) ";
+
+ // bei Object-Vars auch das Object ausgeben
+ if ( GetValues_Impl().eType == SbxOBJECT &&
+ GetValues_Impl().pObj &&
+ GetValues_Impl().pObj != this &&
+ GetValues_Impl().pObj != GetParent() )
+ {
+ rStrm << " contains ";
+ ((SbxObject*) GetValues_Impl().pObj)->Dump( rStrm, bFill );
+ }
+ else
+ rStrm << endl;
+}
+