summaryrefslogtreecommitdiff
path: root/basic/source/sbx
diff options
context:
space:
mode:
Diffstat (limited to 'basic/source/sbx')
-rw-r--r--basic/source/sbx/format.src85
-rw-r--r--basic/source/sbx/makefile.mk78
-rw-r--r--basic/source/sbx/sbxarray.cxx858
-rw-r--r--basic/source/sbx/sbxbase.cxx464
-rw-r--r--basic/source/sbx/sbxbool.cxx249
-rw-r--r--basic/source/sbx/sbxbyte.cxx331
-rw-r--r--basic/source/sbx/sbxchar.cxx321
-rw-r--r--basic/source/sbx/sbxcoll.cxx303
-rw-r--r--basic/source/sbx/sbxconv.hxx154
-rw-r--r--basic/source/sbx/sbxcurr.cxx397
-rw-r--r--basic/source/sbx/sbxdate.cxx416
-rw-r--r--basic/source/sbx/sbxdbl.cxx308
-rw-r--r--basic/source/sbx/sbxdec.cxx799
-rw-r--r--basic/source/sbx/sbxdec.hxx124
-rw-r--r--basic/source/sbx/sbxexec.cxx401
-rw-r--r--basic/source/sbx/sbxform.cxx1170
-rw-r--r--basic/source/sbx/sbxint.cxx965
-rw-r--r--basic/source/sbx/sbxlng.cxx343
-rw-r--r--basic/source/sbx/sbxmstrm.cxx42
-rw-r--r--basic/source/sbx/sbxobj.cxx1067
-rw-r--r--basic/source/sbx/sbxres.cxx93
-rw-r--r--basic/source/sbx/sbxres.hxx90
-rw-r--r--basic/source/sbx/sbxscan.cxx968
-rw-r--r--basic/source/sbx/sbxsng.cxx361
-rw-r--r--basic/source/sbx/sbxstr.cxx315
-rw-r--r--basic/source/sbx/sbxuint.cxx333
-rw-r--r--basic/source/sbx/sbxulng.cxx323
-rw-r--r--basic/source/sbx/sbxvals.cxx112
-rw-r--r--basic/source/sbx/sbxvalue.cxx1862
-rw-r--r--basic/source/sbx/sbxvar.cxx646
30 files changed, 13978 insertions, 0 deletions
diff --git a/basic/source/sbx/format.src b/basic/source/sbx/format.src
new file mode 100644
index 000000000000..7c0e8d102aef
--- /dev/null
+++ b/basic/source/sbx/format.src
@@ -0,0 +1,85 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "svtools/svtools.hrc"
+
+String STR_BASICKEY_FORMAT_ON
+{
+ Text [ en-US ] = "On" ;
+};
+String STR_BASICKEY_FORMAT_OFF
+{
+ Text [ en-US ] = "Off" ;
+};
+String STR_BASICKEY_FORMAT_TRUE
+{
+ Text [ en-US ] = "True" ;
+};
+String STR_BASICKEY_FORMAT_FALSE
+{
+ Text [ en-US ] = "False" ;
+};
+String STR_BASICKEY_FORMAT_YES
+{
+ Text [ en-US ] = "Yes" ;
+};
+String STR_BASICKEY_FORMAT_NO
+{
+ Text [ en-US ] = "No" ;
+};
+String STR_BASICKEY_FORMAT_CURRENCY
+{
+ Text [ en-US ] = "@0.00 $;@(0.00 $)" ;
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/basic/source/sbx/makefile.mk b/basic/source/sbx/makefile.mk
new file mode 100644
index 000000000000..cc20080cbe9c
--- /dev/null
+++ b/basic/source/sbx/makefile.mk
@@ -0,0 +1,78 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=basic
+TARGET=sbx
+
+# --- Settings -----------------------------------------------------------
+
+.INCLUDE : settings.mk
+
+
+# --- Allgemein -----------------------------------------------------------
+
+SRS1NAME=$(TARGET)
+SRC1FILES= format.src
+
+SLOFILES= \
+ $(EXCEPTIONSFILES) \
+ $(SLO)$/sbxbase.obj \
+ $(SLO)$/sbxbool.obj \
+ $(SLO)$/sbxbyte.obj \
+ $(SLO)$/sbxchar.obj \
+ $(SLO)$/sbxcoll.obj \
+ $(SLO)$/sbxcurr.obj \
+ $(SLO)$/sbxdec.obj \
+ $(SLO)$/sbxform.obj \
+ $(SLO)$/sbxint.obj \
+ $(SLO)$/sbxlng.obj \
+ $(SLO)$/sbxmstrm.obj \
+ $(SLO)$/sbxobj.obj \
+ $(SLO)$/sbxres.obj \
+ $(SLO)$/sbxsng.obj \
+ $(SLO)$/sbxuint.obj \
+ $(SLO)$/sbxulng.obj \
+ $(SLO)$/sbxvals.obj \
+ $(SLO)$/sbxvar.obj
+
+
+EXCEPTIONSFILES= \
+ $(SLO)$/sbxarray.obj \
+ $(SLO)$/sbxdate.obj \
+ $(SLO)$/sbxdbl.obj \
+ $(SLO)$/sbxexec.obj \
+ $(SLO)$/sbxscan.obj \
+ $(SLO)$/sbxstr.obj \
+ $(SLO)$/sbxvalue.obj \
+
+# --- Targets -------------------------------------------------------------
+
+.INCLUDE : target.mk
+
+
diff --git a/basic/source/sbx/sbxarray.cxx b/basic/source/sbx/sbxarray.cxx
new file mode 100644
index 000000000000..200c10018cde
--- /dev/null
+++ b/basic/source/sbx/sbxarray.cxx
@@ -0,0 +1,858 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+#include <tools/stream.hxx>
+#include <basic/sbx.hxx>
+#include "runtime.hxx"
+#include <vector>
+using namespace std;
+
+struct SbxDim { // an array-dimension:
+ SbxDim* pNext; // Link
+ INT32 nLbound, nUbound; // Limitations
+ INT32 nSize; // Number of elements
+};
+
+class SbxVarEntry : public SbxVariableRef {
+public:
+ XubString* pAlias;
+ SbxVarEntry() : SbxVariableRef(), pAlias( NULL ) {}
+ ~SbxVarEntry() { delete pAlias; }
+};
+
+typedef SbxVarEntry* SbxVarEntryPtr;
+typedef vector< SbxVarEntryPtr > SbxVarEntryPtrVector;
+class SbxVarRefs : public SbxVarEntryPtrVector
+{
+public:
+ SbxVarRefs( void ) {}
+};
+
+
+TYPEINIT1(SbxArray,SbxBase)
+TYPEINIT1(SbxDimArray,SbxArray)
+
+//////////////////////////////////////////////////////////////////////////
+//
+// SbxArray
+//
+//////////////////////////////////////////////////////////////////////////
+
+SbxArray::SbxArray( SbxDataType t ) : SbxBase()
+{
+ pData = new SbxVarRefs;
+ eType = t;
+ if( t != SbxVARIANT )
+ SetFlag( SBX_FIXED );
+}
+
+SbxArray::SbxArray( const SbxArray& rArray ) :
+ SvRefBase( rArray ), SbxBase()
+{
+ pData = new SbxVarRefs;
+ if( rArray.eType != SbxVARIANT )
+ SetFlag( SBX_FIXED );
+ *this = rArray;
+}
+
+SbxArray& SbxArray::operator=( const SbxArray& rArray )
+{
+ if( &rArray != this )
+ {
+ eType = rArray.eType;
+ Clear();
+ SbxVarRefs* pSrc = rArray.pData;
+ for( UINT32 i = 0; i < pSrc->size(); i++ )
+ {
+ SbxVarEntryPtr pSrcRef = (*pSrc)[i];
+ const SbxVariable* pSrc_ = *pSrcRef;
+ if( !pSrc_ )
+ continue;
+ SbxVarEntryPtr pDstRef = new SbxVarEntry;
+ *((SbxVariableRef*) pDstRef) = *((SbxVariableRef*) pSrcRef);
+ if( pSrcRef->pAlias )
+ pDstRef->pAlias = new XubString( *pSrcRef->pAlias );
+ if( eType != SbxVARIANT )
+ // Convert no objects
+ if( eType != SbxOBJECT || pSrc_->GetClass() != SbxCLASS_OBJECT )
+ ((SbxVariable*) pSrc_)->Convert( eType );
+ pData->push_back( pDstRef );
+ }
+ }
+ return *this;
+}
+
+SbxArray::~SbxArray()
+{
+ Clear();
+ delete pData;
+}
+
+SbxDataType SbxArray::GetType() const
+{
+ return (SbxDataType) ( eType | SbxARRAY );
+}
+
+SbxClassType SbxArray::GetClass() const
+{
+ return SbxCLASS_ARRAY;
+}
+
+void SbxArray::Clear()
+{
+ UINT32 nSize = pData->size();
+ for( UINT32 i = 0 ; i < nSize ; i++ )
+ {
+ SbxVarEntry* pEntry = (*pData)[i];
+ delete pEntry;
+ }
+ pData->clear();
+}
+
+UINT32 SbxArray::Count32() const
+{
+ return pData->size();
+}
+
+USHORT SbxArray::Count() const
+{
+ UINT32 nCount = pData->size();
+ DBG_ASSERT( nCount <= SBX_MAXINDEX, "SBX: Array-Index > SBX_MAXINDEX" );
+ return (USHORT)nCount;
+}
+
+SbxVariableRef& SbxArray::GetRef32( UINT32 nIdx )
+{
+ // If necessary extend the array
+ DBG_ASSERT( nIdx <= SBX_MAXINDEX32, "SBX: Array-Index > SBX_MAXINDEX32" );
+ // Very Hot Fix
+ if( nIdx > SBX_MAXINDEX32 )
+ {
+ SetError( SbxERR_BOUNDS );
+ nIdx = 0;
+ }
+ while( pData->size() <= nIdx )
+ {
+ const SbxVarEntryPtr p = new SbxVarEntry;
+ pData->push_back( p );
+ }
+ return *((*pData)[nIdx]);
+}
+
+SbxVariableRef& SbxArray::GetRef( USHORT nIdx )
+{
+ // If necessary extend the array
+ DBG_ASSERT( nIdx <= SBX_MAXINDEX, "SBX: Array-Index > SBX_MAXINDEX" );
+ // Very Hot Fix
+ if( nIdx > SBX_MAXINDEX )
+ {
+ SetError( SbxERR_BOUNDS );
+ nIdx = 0;
+ }
+ while( pData->size() <= nIdx )
+ {
+ const SbxVarEntryPtr p = new SbxVarEntry;
+ pData->push_back( p );
+ }
+ return *((*pData)[nIdx]);
+}
+
+SbxVariable* SbxArray::Get32( UINT32 nIdx )
+{
+ if( !CanRead() )
+ {
+ SetError( SbxERR_PROP_WRITEONLY );
+ return NULL;
+ }
+ SbxVariableRef& rRef = GetRef32( nIdx );
+
+ if ( !rRef.Is() )
+ rRef = new SbxVariable( eType );
+#ifdef DBG_UTIL
+ else
+ DBG_CHKOBJ( rRef, SbxBase, 0 );
+#endif
+
+ return rRef;
+}
+
+SbxVariable* SbxArray::Get( USHORT nIdx )
+{
+ if( !CanRead() )
+ {
+ SetError( SbxERR_PROP_WRITEONLY );
+ return NULL;
+ }
+ SbxVariableRef& rRef = GetRef( nIdx );
+
+ if ( !rRef.Is() )
+ rRef = new SbxVariable( eType );
+#ifdef DBG_UTIL
+ else
+ DBG_CHKOBJ( rRef, SbxBase, 0 );
+#endif
+
+ return rRef;
+}
+
+void SbxArray::Put32( SbxVariable* pVar, UINT32 nIdx )
+{
+ if( !CanWrite() )
+ SetError( SbxERR_PROP_READONLY );
+ else
+ {
+ if( pVar )
+ if( eType != SbxVARIANT )
+ // Convert no objects
+ if( eType != SbxOBJECT || pVar->GetClass() != SbxCLASS_OBJECT )
+ pVar->Convert( eType );
+ SbxVariableRef& rRef = GetRef32( nIdx );
+ if( (SbxVariable*) rRef != pVar )
+ {
+ rRef = pVar;
+ SetFlag( SBX_MODIFIED );
+ }
+ }
+}
+
+void SbxArray::Put( SbxVariable* pVar, USHORT nIdx )
+{
+ if( !CanWrite() )
+ SetError( SbxERR_PROP_READONLY );
+ else
+ {
+ if( pVar )
+ if( eType != SbxVARIANT )
+ // Convert no objects
+ if( eType != SbxOBJECT || pVar->GetClass() != SbxCLASS_OBJECT )
+ pVar->Convert( eType );
+ SbxVariableRef& rRef = GetRef( nIdx );
+ if( (SbxVariable*) rRef != pVar )
+ {
+ rRef = pVar;
+ SetFlag( SBX_MODIFIED );
+ }
+ }
+}
+
+const XubString& SbxArray::GetAlias( USHORT nIdx )
+{
+ if( !CanRead() )
+ {
+ SetError( SbxERR_PROP_WRITEONLY );
+ return String::EmptyString();
+ }
+ SbxVarEntry& rRef = (SbxVarEntry&) GetRef( nIdx );
+
+ if ( !rRef.pAlias )
+ return String::EmptyString();
+#ifdef DBG_UTIL
+ else
+ DBG_CHKOBJ( rRef, SbxBase, 0 );
+#endif
+
+ return *rRef.pAlias;
+}
+
+void SbxArray::PutAlias( const XubString& rAlias, USHORT nIdx )
+{
+ if( !CanWrite() )
+ SetError( SbxERR_PROP_READONLY );
+ else
+ {
+ SbxVarEntry& rRef = (SbxVarEntry&) GetRef( nIdx );
+ if( !rRef.pAlias )
+ rRef.pAlias = new XubString( rAlias );
+ else
+ *rRef.pAlias = rAlias;
+ }
+}
+
+void SbxArray::Insert32( SbxVariable* pVar, UINT32 nIdx )
+{
+ DBG_ASSERT( pData->size() <= SBX_MAXINDEX32, "SBX: Array wird zu gross" );
+ if( pData->size() > SBX_MAXINDEX32 )
+ return;
+ SbxVarEntryPtr p = new SbxVarEntry;
+ *((SbxVariableRef*) p) = pVar;
+ SbxVarEntryPtrVector::size_type nSize = pData->size();
+ if( nIdx > nSize )
+ nIdx = nSize;
+ if( eType != SbxVARIANT && pVar )
+ (*p)->Convert( eType );
+ if( nIdx == nSize )
+ {
+ pData->push_back( p );
+ }
+ else
+ {
+ pData->insert( pData->begin() + nIdx, p );
+ }
+ SetFlag( SBX_MODIFIED );
+}
+
+void SbxArray::Insert( SbxVariable* pVar, USHORT nIdx )
+{
+ DBG_ASSERT( pData->size() <= 0x3FF0, "SBX: Array wird zu gross" );
+ if( pData->size() > 0x3FF0 )
+ return;
+ Insert32( pVar, nIdx );
+}
+
+void SbxArray::Remove32( UINT32 nIdx )
+{
+ if( nIdx < pData->size() )
+ {
+ SbxVariableRef* pRef = (*pData)[nIdx];
+ pData->erase( pData->begin() + nIdx );
+ delete pRef;
+ SetFlag( SBX_MODIFIED );
+ }
+}
+
+void SbxArray::Remove( USHORT nIdx )
+{
+ if( nIdx < pData->size() )
+ {
+ SbxVariableRef* pRef = (*pData)[nIdx];
+ pData->erase( pData->begin() + nIdx );
+ delete pRef;
+ SetFlag( SBX_MODIFIED );
+ }
+}
+
+void SbxArray::Remove( SbxVariable* pVar )
+{
+ if( pVar )
+ {
+ for( UINT32 i = 0; i < pData->size(); i++ )
+ {
+ SbxVariableRef* pRef = (*pData)[i];
+ // SbxVariableRef* pRef = pData->GetObject( i );
+ if( *pRef == pVar )
+ {
+ Remove32( i ); break;
+ }
+ }
+ }
+}
+
+// Taking over of the data from the passed array, at which
+// the variable of the same name will be overwritten.
+
+void SbxArray::Merge( SbxArray* p )
+{
+ if( p )
+ {
+ UINT32 nSize = p->Count();
+ for( UINT32 i = 0; i < nSize; i++ )
+ {
+ SbxVarEntryPtr pRef1 = (*(p->pData))[i];
+ // Is the element by name already inside?
+ // Then overwrite!
+ SbxVariable* pVar = *pRef1;
+ if( pVar )
+ {
+ XubString aName = pVar->GetName();
+ USHORT nHash = pVar->GetHashCode();
+ for( UINT32 j = 0; j < pData->size(); j++ )
+ {
+ SbxVariableRef* pRef2 = (*pData)[j];
+ if( (*pRef2)->GetHashCode() == nHash
+ && (*pRef2)->GetName().EqualsIgnoreCaseAscii( aName ) )
+ {
+ *pRef2 = pVar; pRef1 = NULL;
+ break;
+ }
+ }
+ if( pRef1 )
+ {
+ SbxVarEntryPtr pRef = new SbxVarEntry;
+ const SbxVarEntryPtr pTemp = pRef;
+ pData->push_back( pTemp );
+ *((SbxVariableRef*) pRef) = *((SbxVariableRef*) pRef1);
+ if( pRef1->pAlias )
+ pRef->pAlias = new XubString( *pRef1->pAlias );
+ }
+ }
+ }
+ }
+}
+
+// Search of an element via the user data. If the element is
+// object, it will also be scanned.
+
+SbxVariable* SbxArray::FindUserData( UINT32 nData )
+{
+ SbxVariable* p = NULL;
+ for( UINT32 i = 0; i < pData->size(); i++ )
+ {
+ SbxVariableRef* pRef = (*pData)[i];
+ SbxVariable* pVar = *pRef;
+ if( pVar )
+ {
+ if( pVar->IsVisible() && pVar->GetUserData() == nData )
+ {
+ p = pVar;
+ p->ResetFlag( SBX_EXTFOUND );
+ break; // JSM 1995-10-06
+ }
+ // Did we have an array/object with extended search?
+ else if( pVar->IsSet( SBX_EXTSEARCH ) )
+ {
+ switch( pVar->GetClass() )
+ {
+ case SbxCLASS_OBJECT:
+ {
+ // Objects are not allowed to scan their parent.
+ USHORT nOld = pVar->GetFlags();
+ pVar->ResetFlag( SBX_GBLSEARCH );
+ p = ((SbxObject*) pVar)->FindUserData( nData );
+ pVar->SetFlags( nOld );
+ break;
+ }
+ case SbxCLASS_ARRAY:
+ p = ((SbxArray*) pVar)->FindUserData( nData );
+ break;
+ default: break;
+ }
+ if( p )
+ {
+ p->SetFlag( SBX_EXTFOUND );
+ break;
+ }
+ }
+ }
+ }
+ return p;
+}
+
+// Search of an element by his name and type. If an element is an object,
+// it will also be scanned..
+
+SbxVariable* SbxArray::Find( const XubString& rName, SbxClassType t )
+{
+ SbxVariable* p = NULL;
+ UINT32 nCount = pData->size();
+ if( !nCount )
+ return NULL;
+ BOOL bExtSearch = IsSet( SBX_EXTSEARCH );
+ USHORT nHash = SbxVariable::MakeHashCode( rName );
+ for( UINT32 i = 0; i < nCount; i++ )
+ {
+ SbxVariableRef* pRef = (*pData)[i];
+ SbxVariable* pVar = *pRef;
+ if( pVar && pVar->IsVisible() )
+ {
+ // The very secure search works as well, if there is no hashcode!
+ USHORT nVarHash = pVar->GetHashCode();
+ if( ( !nVarHash || nVarHash == nHash )
+ && ( t == SbxCLASS_DONTCARE || pVar->GetClass() == t )
+ && ( pVar->GetName().EqualsIgnoreCaseAscii( rName ) ) )
+ {
+ p = pVar;
+ p->ResetFlag( SBX_EXTFOUND );
+ break;
+ }
+ // Did we have an array/object with extended search?
+ else if( bExtSearch && pVar->IsSet( SBX_EXTSEARCH ) )
+ {
+ switch( pVar->GetClass() )
+ {
+ case SbxCLASS_OBJECT:
+ {
+ // Objects are not allowed to scan their parent.
+ USHORT nOld = pVar->GetFlags();
+ pVar->ResetFlag( SBX_GBLSEARCH );
+ p = ((SbxObject*) pVar)->Find( rName, t );
+ pVar->SetFlags( nOld );
+ break;
+ }
+ case SbxCLASS_ARRAY:
+ p = ((SbxArray*) pVar)->Find( rName, t );
+ break;
+ default: break;
+ }
+ if( p )
+ {
+ p->SetFlag( SBX_EXTFOUND );
+ break;
+ }
+ }
+ }
+ }
+ return p;
+}
+
+BOOL SbxArray::LoadData( SvStream& rStrm, USHORT nVer )
+{
+ UINT16 nElem;
+ Clear();
+ BOOL bRes = TRUE;
+ USHORT f = nFlags;
+ nFlags |= SBX_WRITE;
+ rStrm >> nElem;
+ nElem &= 0x7FFF;
+ for( UINT32 n = 0; n < nElem; n++ )
+ {
+ UINT16 nIdx;
+ rStrm >> nIdx;
+ SbxVariable* pVar = (SbxVariable*) Load( rStrm );
+ if( pVar )
+ {
+ SbxVariableRef& rRef = GetRef( nIdx );
+ rRef = pVar;
+ }
+ else
+ {
+ bRes = FALSE; break;
+ }
+ }
+ if( bRes )
+ bRes = LoadPrivateData( rStrm, nVer );
+ nFlags = f;
+ return bRes;
+}
+
+BOOL SbxArray::StoreData( SvStream& rStrm ) const
+{
+ UINT32 nElem = 0;
+ UINT32 n;
+ // Which elements are even defined?
+ for( n = 0; n < pData->size(); n++ )
+ {
+ SbxVariableRef* pRef = (*pData)[n];
+ SbxVariable* p = *pRef;
+ if( p && !( p->GetFlags() & SBX_DONTSTORE ) )
+ nElem++;
+ }
+ rStrm << (UINT16) nElem;
+ for( n = 0; n < pData->size(); n++ )
+ {
+ SbxVariableRef* pRef = (*pData)[n];
+ SbxVariable* p = *pRef;
+ if( p && !( p->GetFlags() & SBX_DONTSTORE ) )
+ {
+ rStrm << (UINT16) n;
+ if( !p->Store( rStrm ) )
+ return FALSE;
+ }
+ }
+ return StorePrivateData( rStrm );
+}
+
+// #100883 Method to set method directly to parameter array
+void SbxArray::PutDirect( SbxVariable* pVar, UINT32 nIdx )
+{
+ SbxVariableRef& rRef = GetRef32( nIdx );
+ rRef = pVar;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//
+// SbxArray
+//
+//////////////////////////////////////////////////////////////////////////
+
+SbxDimArray::SbxDimArray( SbxDataType t ) : SbxArray( t ), mbHasFixedSize( false )
+{
+ pFirst = pLast = NULL;
+ nDim = 0;
+}
+
+SbxDimArray::SbxDimArray( const SbxDimArray& rArray )
+ : SvRefBase( rArray ), SbxArray( rArray.eType )
+{
+ pFirst = pLast = NULL;
+ nDim = 0;
+ *this = rArray;
+}
+
+SbxDimArray& SbxDimArray::operator=( const SbxDimArray& rArray )
+{
+ if( &rArray != this )
+ {
+ SbxArray::operator=( (const SbxArray&) rArray );
+ SbxDim* p = rArray.pFirst;
+ while( p )
+ {
+ AddDim32( p->nLbound, p->nUbound );
+ p = p->pNext;
+ }
+ this->mbHasFixedSize = rArray.mbHasFixedSize;
+ }
+ return *this;
+}
+
+SbxDimArray::~SbxDimArray()
+{
+ Clear();
+}
+
+void SbxDimArray::Clear()
+{
+ SbxDim* p = pFirst;
+ while( p )
+ {
+ SbxDim* q = p->pNext;
+ delete p;
+ p = q;
+ }
+ pFirst = pLast = NULL;
+ nDim = 0;
+}
+
+// Add a dimension
+
+void SbxDimArray::AddDimImpl32( INT32 lb, INT32 ub, BOOL bAllowSize0 )
+{
+ SbxError eRes = SbxERR_OK;
+ if( ub < lb && !bAllowSize0 )
+ {
+ eRes = SbxERR_BOUNDS;
+ ub = lb;
+ }
+ SbxDim* p = new SbxDim;
+ p->nLbound = lb;
+ p->nUbound = ub;
+ p->nSize = ub - lb + 1;
+ p->pNext = NULL;
+ if( !pFirst )
+ pFirst = pLast = p;
+ else
+ pLast->pNext = p, pLast = p;
+ nDim++;
+ if( eRes )
+ SetError( eRes );
+}
+
+void SbxDimArray::AddDim( short lb, short ub )
+{
+ AddDimImpl32( lb, ub, FALSE );
+}
+
+void SbxDimArray::unoAddDim( short lb, short ub )
+{
+ AddDimImpl32( lb, ub, TRUE );
+}
+
+void SbxDimArray::AddDim32( INT32 lb, INT32 ub )
+{
+ AddDimImpl32( lb, ub, FALSE );
+}
+
+void SbxDimArray::unoAddDim32( INT32 lb, INT32 ub )
+{
+ AddDimImpl32( lb, ub, TRUE );
+}
+
+
+// Readout dimension data
+
+BOOL SbxDimArray::GetDim32( INT32 n, INT32& rlb, INT32& rub ) const
+{
+ if( n < 1 || n > nDim )
+ {
+ SetError( SbxERR_BOUNDS ); rub = rlb = 0; return FALSE;
+ }
+ SbxDim* p = pFirst;
+ while( --n )
+ p = p->pNext;
+ rub = p->nUbound;
+ rlb = p->nLbound;
+ return TRUE;
+}
+
+BOOL SbxDimArray::GetDim( short n, short& rlb, short& rub ) const
+{
+ INT32 rlb32, rub32;
+ BOOL bRet = GetDim32( n, rlb32, rub32 );
+ if( bRet )
+ {
+ if( rlb32 < -SBX_MAXINDEX || rub32 > SBX_MAXINDEX )
+ {
+ SetError( SbxERR_BOUNDS );
+ return FALSE;
+ }
+ rub = (short)rub32;
+ rlb = (short)rlb32;
+ }
+ return bRet;
+}
+
+// Element-Ptr with the help of an index list
+
+UINT32 SbxDimArray::Offset32( const INT32* pIdx )
+{
+ UINT32 nPos = 0;
+ for( SbxDim* p = pFirst; p; p = p->pNext )
+ {
+ INT32 nIdx = *pIdx++;
+ if( nIdx < p->nLbound || nIdx > p->nUbound )
+ {
+ nPos = (UINT32)SBX_MAXINDEX32 + 1; break;
+ }
+ nPos = nPos * p->nSize + nIdx - p->nLbound;
+ }
+ if( nDim == 0 || nPos > SBX_MAXINDEX32 )
+ {
+ SetError( SbxERR_BOUNDS ); nPos = 0;
+ }
+ return nPos;
+}
+
+USHORT SbxDimArray::Offset( const short* pIdx )
+{
+ long nPos = 0;
+ for( SbxDim* p = pFirst; p; p = p->pNext )
+ {
+ short nIdx = *pIdx++;
+ if( nIdx < p->nLbound || nIdx > p->nUbound )
+ {
+ nPos = SBX_MAXINDEX + 1; break;
+ }
+ nPos = nPos * p->nSize + nIdx - p->nLbound;
+ }
+ if( nDim == 0 || nPos > SBX_MAXINDEX )
+ {
+ SetError( SbxERR_BOUNDS ); nPos = 0;
+ }
+ return (USHORT) nPos;
+}
+
+SbxVariableRef& SbxDimArray::GetRef( const short* pIdx )
+{
+ return SbxArray::GetRef( Offset( pIdx ) );
+}
+
+SbxVariable* SbxDimArray::Get( const short* pIdx )
+{
+ return SbxArray::Get( Offset( pIdx ) );
+}
+
+void SbxDimArray::Put( SbxVariable* p, const short* pIdx )
+{
+ SbxArray::Put( p, Offset( pIdx ) );
+}
+
+SbxVariableRef& SbxDimArray::GetRef32( const INT32* pIdx )
+{
+ return SbxArray::GetRef32( Offset32( pIdx ) );
+}
+
+SbxVariable* SbxDimArray::Get32( const INT32* pIdx )
+{
+ return SbxArray::Get32( Offset32( pIdx ) );
+}
+
+void SbxDimArray::Put32( SbxVariable* p, const INT32* pIdx )
+{
+ SbxArray::Put32( p, Offset32( pIdx ) );
+}
+
+
+// Element-Number with the help of Parameter-Array
+
+UINT32 SbxDimArray::Offset32( SbxArray* pPar )
+{
+ if( nDim == 0 || !pPar || ( ( nDim != ( pPar->Count() - 1 ) ) && SbiRuntime::isVBAEnabled() ) )
+ {
+ SetError( SbxERR_BOUNDS ); return 0;
+ }
+ UINT32 nPos = 0;
+ USHORT nOff = 1; // Non element 0!
+ for( SbxDim* p = pFirst; p && !IsError(); p = p->pNext )
+ {
+ INT32 nIdx = pPar->Get( nOff++ )->GetLong();
+ if( nIdx < p->nLbound || nIdx > p->nUbound )
+ {
+ nPos = (UINT32) SBX_MAXINDEX32+1; break;
+ }
+ nPos = nPos * p->nSize + nIdx - p->nLbound;
+ }
+ if( nPos > (UINT32) SBX_MAXINDEX32 )
+ {
+ SetError( SbxERR_BOUNDS ); nPos = 0;
+ }
+ return nPos;
+}
+
+USHORT SbxDimArray::Offset( SbxArray* pPar )
+{
+ UINT32 nPos = Offset32( pPar );
+ if( nPos > (long) SBX_MAXINDEX )
+ {
+ SetError( SbxERR_BOUNDS ); nPos = 0;
+ }
+ return (USHORT) nPos;
+}
+
+SbxVariableRef& SbxDimArray::GetRef( SbxArray* pPar )
+{
+ return SbxArray::GetRef32( Offset32( pPar ) );
+}
+
+SbxVariable* SbxDimArray::Get( SbxArray* pPar )
+{
+ return SbxArray::Get32( Offset32( pPar ) );
+}
+
+void SbxDimArray::Put( SbxVariable* p, SbxArray* pPar )
+{
+ SbxArray::Put32( p, Offset32( pPar ) );
+}
+
+BOOL SbxDimArray::LoadData( SvStream& rStrm, USHORT nVer )
+{
+ short nDimension;
+ rStrm >> nDimension;
+ for( short i = 0; i < nDimension && rStrm.GetError() == SVSTREAM_OK; i++ )
+ {
+ INT16 lb, ub;
+ rStrm >> lb >> ub;
+ AddDim( lb, ub );
+ }
+ return SbxArray::LoadData( rStrm, nVer );
+}
+
+BOOL SbxDimArray::StoreData( SvStream& rStrm ) const
+{
+ rStrm << (INT16) nDim;
+ for( short i = 0; i < nDim; i++ )
+ {
+ short lb, ub;
+ GetDim( i, lb, ub );
+ rStrm << (INT16) lb << (INT16) ub;
+ }
+ return SbxArray::StoreData( rStrm );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxbase.cxx b/basic/source/sbx/sbxbase.cxx
new file mode 100644
index 000000000000..f96c39730db1
--- /dev/null
+++ b/basic/source/sbx/sbxbase.cxx
@@ -0,0 +1,464 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 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-Structure for SBX:
+
+SV_IMPL_PTRARR(SbxParams,SbxParamInfo*);
+SV_IMPL_PTRARR(SbxFacs,SbxFactory*);
+
+TYPEINIT0(SbxBase)
+
+// Request SBX-Data or if necessary create them
+// we just create the area and waive the release!
+
+SbxAppData* GetSbxData_Impl()
+{
+#ifndef DOS
+ SbxAppData** ppData = (SbxAppData**) ::GetAppData( SHL_SBX );
+ SbxAppData* p = *ppData;
+ if( !p )
+ p = *ppData = new SbxAppData;
+ return p;
+#else
+ SbxAppData** ppData;
+ SbxAppData* p;
+ p = *ppData = new SbxAppData;
+ return p;
+#endif
+}
+
+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 );
+}
+
+BOOL SbxBase::IsFixed() const
+{
+ DBG_CHKTHIS( SbxBase, 0 );
+ return IsSet( SBX_FIXED );
+}
+
+void SbxBase::SetModified( 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;
+}
+
+BOOL SbxBase::IsError()
+{
+ return 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;
+
+ // From 1996-03-06: take the HandleLast-Flag into account
+ USHORT nPos = p->aFacs.Count(); // Insert-Position
+ if( !pFac->IsHandleLast() ) // Only if not self HandleLast
+ {
+ // Rank new factory in front of factories with HandleLast
+ 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( USHORT i = 0; i < p->aFacs.Count(); i++ )
+ {
+ if( p->aFacs.GetObject( i ) == pFac )
+ {
+ p->aFacs.Remove( i, 1 ); break;
+ }
+ }
+}
+
+
+SbxBase* SbxBase::Create( UINT16 nSbxId, 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 );
+ }
+ // Unknown type: go over the factories!
+ SbxAppData* p = GetSbxData_Impl();
+ SbxBase* pNew = NULL;
+ for( USHORT 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( USHORT 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 BOOL bStaticEnableBroadcasting = TRUE;
+
+// Sbx-Solution in exchange for SfxBroadcaster::Enable()
+void SbxBase::StaticEnableBroadcasting( BOOL bEnable )
+{
+ bStaticEnableBroadcasting = bEnable;
+}
+
+BOOL SbxBase::StaticIsEnabledBroadcasting( void )
+{
+ return bStaticEnableBroadcasting;
+}
+
+
+SbxBase* SbxBase::Load( SvStream& rStrm )
+{
+ UINT16 nSbxId, nFlags, nVer;
+ UINT32 nCreator, nSize;
+ rStrm >> nCreator >> nSbxId >> nFlags >> nVer;
+
+ // Correcting a foolishness of mine:
+ if( nFlags & SBX_RESERVED )
+ nFlags = ( nFlags & ~SBX_RESERVED ) | SBX_GBLSEARCH;
+
+ ULONG nOldPos = rStrm.Tell();
+ rStrm >> nSize;
+ SbxBase* p = Create( nSbxId, nCreator );
+ if( p )
+ {
+ p->nFlags = nFlags;
+ if( p->LoadData( rStrm, nVer ) )
+ {
+ ULONG nNewPos = rStrm.Tell();
+ nOldPos += nSize;
+ DBG_ASSERT( nOldPos >= nNewPos, "SBX: Zu viele Daten eingelesen" );
+ if( nOldPos != nNewPos )
+ rStrm.Seek( nOldPos );
+ if( !p->LoadCompleted() )
+ {
+ // Deleting of the object
+ SbxBaseRef aRef( p );
+ p = NULL;
+ }
+ }
+ else
+ {
+ rStrm.SetError( SVSTREAM_FILEFORMAT_ERROR );
+ // Deleting of the object
+ SbxBaseRef aRef( p );
+ p = NULL;
+ }
+ }
+ else
+ rStrm.SetError( SVSTREAM_FILEFORMAT_ERROR );
+ return p;
+}
+
+// Skip the Sbx-Object inside the stream
+void SbxBase::Skip( SvStream& rStrm )
+{
+ UINT16 nSbxId, nFlags, nVer;
+ UINT32 nCreator, nSize;
+ rStrm >> nCreator >> nSbxId >> nFlags >> nVer;
+
+ ULONG nStartPos = rStrm.Tell();
+ rStrm >> nSize;
+
+ rStrm.Seek( nStartPos + nSize );
+}
+
+BOOL SbxBase::Store( SvStream& rStrm )
+{
+ DBG_CHKTHIS( SbxBase, 0 );
+ if( !( nFlags & SBX_DONTSTORE ) )
+ {
+ rStrm << (UINT32) GetCreator()
+ << (UINT16) GetSbxId()
+ << (UINT16) GetFlags()
+ << (UINT16) GetVersion();
+ ULONG nOldPos = rStrm.Tell();
+ rStrm << (UINT32) 0L;
+ BOOL bRes = StoreData( rStrm );
+ ULONG nNewPos = rStrm.Tell();
+ rStrm.Seek( nOldPos );
+ rStrm << (UINT32) ( nNewPos - nOldPos );
+ rStrm.Seek( nNewPos );
+ if( rStrm.GetError() != SVSTREAM_OK )
+ bRes = FALSE;
+ if( bRes )
+ bRes = StoreCompleted();
+ return bRes;
+ }
+ else
+ return TRUE;
+}
+
+BOOL SbxBase::LoadData( SvStream&, USHORT )
+{
+ DBG_CHKTHIS( SbxBase, 0 );
+ return FALSE;
+}
+
+BOOL SbxBase::StoreData( SvStream& ) const
+{
+ DBG_CHKTHIS( SbxBase, 0 );
+ return FALSE;
+}
+
+BOOL SbxBase::LoadPrivateData( SvStream&, USHORT )
+{
+ DBG_CHKTHIS( SbxBase, 0 );
+ return TRUE;
+}
+
+BOOL SbxBase::StorePrivateData( SvStream& ) const
+{
+ DBG_CHKTHIS( SbxBase, 0 );
+ return TRUE;
+}
+
+BOOL SbxBase::LoadCompleted()
+{
+ DBG_CHKTHIS( SbxBase, 0 );
+ return TRUE;
+}
+
+BOOL SbxBase::StoreCompleted()
+{
+ DBG_CHKTHIS( SbxBase, 0 );
+ return TRUE;
+}
+
+//////////////////////////////// SbxFactory ////////////////////////////////
+
+SbxBase* SbxFactory::Create( UINT16, UINT32 )
+{
+ return NULL;
+}
+
+SbxObject* SbxFactory::CreateObject( const XubString& )
+{
+ return NULL;
+}
+
+///////////////////////////////// SbxInfo //////////////////////////////////
+
+SbxInfo::~SbxInfo()
+{}
+
+void SbxInfo::AddParam
+ ( const XubString& rName, SbxDataType eType, USHORT 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( USHORT n ) const
+{
+ if( n < 1 || n > aParams.Count() )
+ return NULL;
+ else
+ return aParams.GetObject( n-1 );
+}
+
+BOOL SbxInfo::LoadData( SvStream& rStrm, USHORT nVer )
+{
+ aParams.Remove( 0, aParams.Count() );
+ UINT16 nParam;
+ rStrm.ReadByteString( aComment, RTL_TEXTENCODING_ASCII_US );
+ rStrm.ReadByteString( aHelpFile, RTL_TEXTENCODING_ASCII_US );
+ rStrm >> nHelpId >> nParam;
+ while( nParam-- )
+ {
+ XubString aName;
+ UINT16 nType, nFlags;
+ 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 TRUE;
+}
+
+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( USHORT i = 0; i < aParams.Count(); i++ )
+ {
+ SbxParamInfo* p = aParams.GetObject( i );
+ rStrm.WriteByteString( p->aName, RTL_TEXTENCODING_ASCII_US );
+ rStrm << (UINT16) p->eType
+ << (UINT16) p->nFlags
+ << (UINT32) p->nUserData;
+ }
+ return TRUE;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxbool.cxx b/basic/source/sbx/sbxbool.cxx
new file mode 100644
index 000000000000..1f7d510e4890
--- /dev/null
+++ b/basic/source/sbx/sbxbool.cxx
@@ -0,0 +1,249 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+#include <tools/errcode.hxx>
+#include <basic/sbx.hxx>
+#include "sbxconv.hxx"
+#include "sbxres.hxx"
+
+enum SbxBOOL ImpGetBool( const SbxValues* p )
+{
+ enum SbxBOOL nRes;
+ switch( +p->eType )
+ {
+ case SbxNULL:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ case SbxEMPTY:
+ nRes = SbxFALSE; break;
+ case SbxCHAR:
+ nRes = p->nChar ? SbxTRUE : SbxFALSE; break;
+ case SbxBYTE:
+ nRes = p->nByte ? SbxTRUE : SbxFALSE; break;
+ case SbxINTEGER:
+ case SbxBOOL:
+ nRes = p->nInteger ? SbxTRUE : SbxFALSE; break;
+ case SbxERROR:
+ case SbxUSHORT:
+ nRes = p->nUShort ? SbxTRUE : SbxFALSE; break;
+ case SbxLONG:
+ nRes = p->nLong ? SbxTRUE : SbxFALSE; break;
+ case SbxULONG:
+ nRes = p->nULong ? SbxTRUE : SbxFALSE; break;
+ case SbxSINGLE:
+ nRes = p->nSingle ? SbxTRUE : SbxFALSE; break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ nRes = p->nDouble ? SbxTRUE : SbxFALSE; break;
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ {
+ double dVal = 0.0;
+ if( p->pDecimal )
+ p->pDecimal->getDouble( dVal );
+ nRes = dVal ? SbxTRUE : SbxFALSE;
+ }
+ break;
+ case SbxSALINT64:
+ nRes = p->nInt64 ? SbxTRUE : SbxFALSE; break;
+ case SbxSALUINT64:
+ nRes = p->uInt64 ? SbxTRUE : SbxFALSE; break;
+ case SbxULONG64:
+ nRes = !!p->nULong64 ? SbxTRUE : SbxFALSE; break;
+ case SbxLONG64:
+ case SbxCURRENCY:
+ nRes = !!p->nLong64 ? SbxTRUE : SbxFALSE; break;
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+ nRes = SbxFALSE;
+ if ( p->pOUString )
+ {
+ if( p->pOUString->equalsIgnoreAsciiCase( SbxRes( STRING_TRUE ) ) )
+ nRes = SbxTRUE;
+ else if( !p->pOUString->equalsIgnoreAsciiCase( SbxRes( STRING_FALSE ) ) )
+ {
+ // Jetzt kann es noch in eine Zahl konvertierbar sein
+ BOOL bError = TRUE;
+ double n;
+ SbxDataType t;
+ USHORT nLen = 0;
+ if( ImpScan( *p->pOUString, n, t, &nLen ) == SbxERR_OK )
+ {
+ if( nLen == p->pOUString->getLength() )
+ {
+ bError = FALSE;
+ if( n != 0.0 )
+ nRes = SbxTRUE;
+ }
+ }
+ if( bError )
+ SbxBase::SetError( SbxERR_CONVERSION );
+ }
+ }
+ break;
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ nRes = pVal->GetBool() ? SbxTRUE : SbxFALSE;
+ else
+ {
+ SbxBase::SetError( SbxERR_NO_OBJECT ); nRes = SbxFALSE;
+ }
+ break;
+ }
+
+ case SbxBYREF | SbxCHAR:
+ nRes = *p->pChar ? SbxTRUE : SbxFALSE; break;
+ case SbxBYREF | SbxBYTE:
+ nRes = *p->pByte ? SbxTRUE : SbxFALSE; break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ nRes = *p->pInteger ? SbxTRUE : SbxFALSE; break;
+ case SbxBYREF | SbxLONG:
+ nRes = *p->pLong ? SbxTRUE : SbxFALSE; break;
+ case SbxBYREF | SbxULONG:
+ nRes = *p->pULong ? SbxTRUE : SbxFALSE; break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ nRes = *p->pUShort ? SbxTRUE : SbxFALSE; break;
+ case SbxBYREF | SbxSINGLE:
+ nRes = ( *p->pSingle != 0 ) ? SbxTRUE : SbxFALSE; break;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ nRes = ( *p->pDouble != 0 ) ? SbxTRUE : SbxFALSE; break;
+ case SbxBYREF | SbxSALINT64:
+ nRes = ( *p->pnInt64 ) ? SbxTRUE : SbxFALSE; break;
+ case SbxBYREF | SbxSALUINT64:
+ nRes = ( *p->puInt64 ) ? SbxTRUE : SbxFALSE; break;
+ case SbxBYREF | SbxULONG64:
+ nRes = !!*p->pULong64 ? SbxTRUE : SbxFALSE; break;
+ case SbxBYREF | SbxLONG64:
+ case SbxBYREF | SbxCURRENCY:
+ nRes = !!*p->pLong64 ? SbxTRUE : SbxFALSE; break;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION ); nRes = SbxFALSE;
+ }
+ return nRes;
+}
+
+void ImpPutBool( SbxValues* p, INT16 n )
+{
+ if( n )
+ n = SbxTRUE;
+ switch( +p->eType )
+ {
+ case SbxCHAR:
+ p->nChar = (xub_Unicode) n; break;
+ case SbxUINT:
+ p->nByte = (BYTE) n; break;
+ case SbxINTEGER:
+ case SbxBOOL:
+ p->nInteger = n; break;
+ case SbxLONG:
+ p->nLong = n; break;
+ case SbxULONG:
+ p->nULong = (UINT32) n; break;
+ case SbxERROR:
+ case SbxUSHORT:
+ p->nUShort = (UINT16) n; break;
+ case SbxSINGLE:
+ p->nSingle = n; break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ p->nDouble = n; break;
+ case SbxSALINT64:
+ p->nInt64 = n; break;
+ case SbxSALUINT64:
+ p->uInt64 = n; break;
+ case SbxULONG64:
+ p->nULong64.Set( (UINT32)n ); break;
+ case SbxLONG64:
+ case SbxCURRENCY:
+ p->nLong64.Set( (INT32)n ); break;
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ ImpCreateDecimal( p )->setInt( (INT16)n );
+ break;
+
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+ if ( !p->pOUString )
+ p->pOUString = new ::rtl::OUString( SbxRes( n ? STRING_TRUE : STRING_FALSE ) );
+ else
+ *p->pOUString = SbxRes( n ? STRING_TRUE : STRING_FALSE );
+ break;
+
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ pVal->PutBool( BOOL( n != 0 ) );
+ else
+ SbxBase::SetError( SbxERR_NO_OBJECT );
+ break;
+ }
+ case SbxBYREF | SbxCHAR:
+ *p->pChar = (xub_Unicode) n; break;
+ case SbxBYREF | SbxBYTE:
+ *p->pByte = (BYTE) n; break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ *p->pInteger = (INT16) n; break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ *p->pUShort = (UINT16) n; break;
+ case SbxBYREF | SbxLONG:
+ *p->pLong = n; break;
+ case SbxBYREF | SbxULONG:
+ *p->pULong = (UINT32) n; break;
+ case SbxBYREF | SbxSINGLE:
+ *p->pSingle = n; break;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ *p->pDouble = n; break;
+ case SbxBYREF | SbxSALINT64:
+ *p->pnInt64 = n; break;
+ case SbxBYREF | SbxSALUINT64:
+ *p->puInt64 = n; break;
+ case SbxBYREF | SbxULONG64:
+ p->pULong64->Set( (UINT32)n ); break;
+ case SbxBYREF | SbxLONG64:
+ case SbxBYREF | SbxCURRENCY:
+ p->pLong64->Set( (INT32)n ); break;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxbyte.cxx b/basic/source/sbx/sbxbyte.cxx
new file mode 100644
index 000000000000..0151f59bc0b9
--- /dev/null
+++ b/basic/source/sbx/sbxbyte.cxx
@@ -0,0 +1,331 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+#include <tools/errcode.hxx>
+#include <basic/sbx.hxx>
+#include "sbxconv.hxx"
+
+BYTE ImpGetByte( const SbxValues* p )
+{
+ SbxValues aTmp;
+ BYTE nRes;
+start:
+ switch( +p->eType )
+ {
+ case SbxNULL:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ case SbxEMPTY:
+ nRes = 0; break;
+ case SbxCHAR:
+ if( p->nChar > SbxMAXBYTE )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0;
+ }
+ else
+ nRes = (BYTE) p->nChar;
+ break;
+ case SbxBYTE:
+ nRes = (BYTE) p->nByte; break;
+ case SbxINTEGER:
+ case SbxBOOL:
+ if( p->nInteger > SbxMAXBYTE )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXBYTE;
+ }
+ else if( p->nInteger < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0;
+ }
+ else
+ nRes = (BYTE) p->nInteger;
+ break;
+ case SbxERROR:
+ case SbxUSHORT:
+ if( p->nUShort > (USHORT) SbxMAXBYTE )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXBYTE;
+ }
+ else
+ nRes = (BYTE) p->nUShort;
+ break;
+ case SbxLONG:
+ if( p->nLong > SbxMAXBYTE )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXBYTE;
+ }
+ else if( p->nLong < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0;
+ }
+ else
+ nRes = (BYTE) p->nLong;
+ break;
+ case SbxULONG:
+ if( p->nULong > SbxMAXBYTE )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXBYTE;
+ }
+ else
+ nRes = (BYTE) p->nULong;
+ break;
+ case SbxSALINT64:
+ if( p->nInt64 > SbxMAXBYTE )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXBYTE;
+ }
+ else if( p->nInt64 < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0;
+ }
+ else
+ nRes = (BYTE) p->nInt64;
+ break;
+ case SbxSALUINT64:
+ if( p->uInt64 > SbxMAXBYTE )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXBYTE;
+ }
+ else
+ nRes = (BYTE) p->uInt64;
+ break;
+ case SbxSINGLE:
+ if( p->nSingle > SbxMAXBYTE )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXBYTE;
+ }
+ else if( p->nSingle < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0;
+ }
+ else
+ nRes = (BYTE) ImpRound( p->nSingle );
+ break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ case SbxLONG64:
+ case SbxULONG64:
+ case SbxCURRENCY:
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ {
+ double dVal;
+ if( p->eType == SbxCURRENCY )
+ dVal = ImpCurrencyToDouble( p->nLong64 );
+ else if( p->eType == SbxLONG64 )
+ dVal = ImpINT64ToDouble( p->nLong64 );
+ else if( p->eType == SbxULONG64 )
+ dVal = ImpUINT64ToDouble( p->nULong64 );
+ else if( p->eType == SbxDECIMAL )
+ {
+ dVal = 0.0;
+ if( p->pDecimal )
+ p->pDecimal->getDouble( dVal );
+ }
+ else
+ dVal = p->nDouble;
+
+ if( dVal > SbxMAXBYTE )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXBYTE;
+ }
+ else if( dVal < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0;
+ }
+ else
+ nRes = (BYTE) ImpRound( dVal );
+ break;
+ }
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+ if( !p->pOUString )
+ nRes = 0;
+ else
+ {
+ double d;
+ SbxDataType t;
+ if( ImpScan( *p->pOUString, d, t, NULL ) != SbxERR_OK )
+ nRes = 0;
+ else if( d > SbxMAXBYTE )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXBYTE;
+ }
+ else if( d < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0;
+ }
+ else
+ nRes = (BYTE) ( d + 0.5 );
+ }
+ break;
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ nRes = pVal->GetByte();
+ else
+ {
+ SbxBase::SetError( SbxERR_NO_OBJECT ); nRes = 0;
+ }
+ break;
+ }
+
+ case SbxBYREF | SbxBYTE:
+ nRes = p->nByte; break;
+
+ // from here on will be tested
+ case SbxBYREF | SbxCHAR:
+ aTmp.nChar = *p->pChar; goto ref;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ aTmp.nInteger = *p->pInteger; goto ref;
+ case SbxBYREF | SbxLONG:
+ aTmp.nLong = *p->pLong; goto ref;
+ case SbxBYREF | SbxULONG:
+ aTmp.nULong = *p->pULong; goto ref;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ aTmp.nUShort = *p->pUShort; goto ref;
+ case SbxBYREF | SbxSINGLE:
+ aTmp.nSingle = *p->pSingle; goto ref;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ aTmp.nDouble = *p->pDouble; goto ref;
+ case SbxBYREF | SbxULONG64:
+ aTmp.nULong64 = *p->pULong64; goto ref;
+ case SbxBYREF | SbxLONG64:
+ case SbxBYREF | SbxCURRENCY:
+ aTmp.nLong64 = *p->pLong64; goto ref;
+ case SbxBYREF | SbxSALINT64:
+ aTmp.nInt64 = *p->pnInt64; goto ref;
+ case SbxBYREF | SbxSALUINT64:
+ aTmp.uInt64 = *p->puInt64; goto ref;
+ ref:
+ aTmp.eType = SbxDataType( p->eType & 0x0FFF );
+ p = &aTmp; goto start;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0;
+ }
+ return nRes;
+}
+
+void ImpPutByte( SbxValues* p, BYTE n )
+{
+ switch( +p->eType )
+ {
+ case SbxBYTE:
+ p->nByte = n; break;
+ case SbxINTEGER:
+ case SbxBOOL:
+ p->nInteger = n; break;
+ case SbxERROR:
+ case SbxUSHORT:
+ p->nUShort = n; break;
+ case SbxLONG:
+ p->nLong = n; break;
+ case SbxULONG:
+ p->nULong = n; break;
+ case SbxSINGLE:
+ p->nSingle = n; break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ p->nDouble = n; break;
+ case SbxSALINT64:
+ p->nInt64 = n; break;
+ case SbxSALUINT64:
+ p->uInt64 = n; break;
+ case SbxULONG64:
+ p->nULong64 = ImpDoubleToUINT64( (double)n ); break;
+ case SbxLONG64:
+ p->nLong64 = ImpDoubleToINT64( (double)n ); break;
+ case SbxCURRENCY:
+ p->nLong64 = ImpDoubleToCurrency( (double)n ); break;
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ ImpCreateDecimal( p )->setByte( n );
+ break;
+
+ case SbxCHAR:
+ p->nChar = (xub_Unicode) n; break;
+
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+ if( !p->pOUString )
+ p->pOUString = new ::rtl::OUString;
+ ImpCvtNum( (double) n, 0, *p->pOUString );
+ break;
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ pVal->PutByte( n );
+ else
+ SbxBase::SetError( SbxERR_NO_OBJECT );
+ break;
+ }
+ case SbxBYREF | SbxCHAR:
+ *p->pChar = (xub_Unicode) n; break;
+ case SbxBYREF | SbxBYTE:
+ *p->pByte = n; break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ *p->pInteger = n; break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ *p->pUShort = n; break;
+ case SbxBYREF | SbxLONG:
+ *p->pLong = n; break;
+ case SbxBYREF | SbxULONG:
+ *p->pULong = n; break;
+ case SbxBYREF | SbxSINGLE:
+ *p->pSingle = n; break;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ *p->pDouble = n; break;
+ case SbxBYREF | SbxULONG64:
+ *p->pULong64 = ImpDoubleToUINT64( (double)n ); break;
+ case SbxBYREF | SbxLONG64:
+ *p->pLong64 = ImpDoubleToINT64( (double)n ); break;
+ case SbxBYREF | SbxSALINT64:
+ *p->pnInt64 = n; break;
+ case SbxBYREF | SbxSALUINT64:
+ *p->puInt64 = n; break;
+ case SbxBYREF | SbxCURRENCY:
+ *p->pLong64 = ImpDoubleToCurrency( (double)n ); break;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxchar.cxx b/basic/source/sbx/sbxchar.cxx
new file mode 100644
index 000000000000..ab0aff6579a2
--- /dev/null
+++ b/basic/source/sbx/sbxchar.cxx
@@ -0,0 +1,321 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+#include <tools/errcode.hxx>
+#include <basic/sbx.hxx>
+#include "sbxconv.hxx"
+
+xub_Unicode ImpGetChar( const SbxValues* p )
+{
+ SbxValues aTmp;
+ xub_Unicode nRes = 0;
+start:
+ switch( +p->eType )
+ {
+ case SbxNULL:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ case SbxEMPTY:
+ nRes = 0; break;
+ case SbxCHAR:
+ nRes = p->nChar; break;
+ case SbxBYTE:
+ nRes = (xub_Unicode) p->nByte;
+ break;
+ case SbxINTEGER:
+ case SbxBOOL:
+ if( p->nInteger < SbxMINCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMINCHAR;
+ }
+ else
+ nRes = (xub_Unicode) p->nInteger;
+ break;
+ case SbxERROR:
+ case SbxUSHORT:
+ nRes = (xub_Unicode) p->nUShort;
+ break;
+ case SbxLONG:
+ if( p->nLong > SbxMAXCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXCHAR;
+ }
+ else if( p->nLong < SbxMINCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMINCHAR;
+ }
+ else
+ nRes = (xub_Unicode) p->nLong;
+ break;
+ case SbxULONG:
+ if( p->nULong > SbxMAXCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXCHAR;
+ }
+ else
+ nRes = (xub_Unicode) p->nULong;
+ break;
+ case SbxSALINT64:
+ if( p->nInt64 > SbxMAXCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXCHAR;
+ }
+ else if( p->nInt64 < SbxMINCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMINCHAR;
+ }
+ else
+ nRes = (xub_Unicode) p->nInt64;
+ break;
+ case SbxSALUINT64:
+ if( p->uInt64 > SbxMAXCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXCHAR;
+ }
+ else
+ nRes = (xub_Unicode) p->uInt64;
+ break;
+ case SbxSINGLE:
+ if( p->nSingle > SbxMAXCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXCHAR;
+ }
+ else if( p->nSingle < SbxMINCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMINCHAR;
+ }
+ else
+ nRes = (xub_Unicode) ImpRound( p->nSingle );
+ break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ case SbxLONG64:
+ case SbxULONG64:
+ case SbxCURRENCY:
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ {
+ double dVal;
+ if( p->eType == SbxCURRENCY )
+ dVal = ImpCurrencyToDouble( p->nLong64 );
+ else if( p->eType == SbxLONG64 )
+ dVal = ImpINT64ToDouble( p->nLong64 );
+ else if( p->eType == SbxULONG64 )
+ dVal = ImpUINT64ToDouble( p->nULong64 );
+ else if( p->eType == SbxDECIMAL )
+ {
+ dVal = 0.0;
+ if( p->pDecimal )
+ p->pDecimal->getDouble( dVal );
+ }
+ else
+ dVal = p->nDouble;
+
+ if( dVal > SbxMAXCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXCHAR;
+ }
+ else if( dVal < SbxMINCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMINCHAR;
+ }
+ else
+ nRes = (BYTE) ImpRound( dVal );
+ break;
+ }
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+ if ( p->pOUString )
+ {
+ double d;
+ SbxDataType t;
+ if( ImpScan( *p->pOUString, d, t, NULL ) != SbxERR_OK )
+ nRes = 0;
+ else if( d > SbxMAXCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXCHAR;
+ }
+ else if( d < SbxMINCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMINCHAR;
+ }
+ else
+ nRes = (xub_Unicode) ImpRound( d );
+ }
+ break;
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ nRes = pVal->GetChar();
+ else
+ {
+ SbxBase::SetError( SbxERR_NO_OBJECT ); nRes = 0;
+ }
+ break;
+ }
+
+ case SbxBYREF | SbxCHAR:
+ nRes = *p->pChar; break;
+ // from here on will be tested
+ case SbxBYREF | SbxBYTE:
+ aTmp.nByte = *p->pByte; goto ref;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ aTmp.nInteger = *p->pInteger; goto ref;
+ case SbxBYREF | SbxLONG:
+ aTmp.nLong = *p->pLong; goto ref;
+ case SbxBYREF | SbxULONG:
+ aTmp.nULong = *p->pULong; goto ref;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ aTmp.nUShort = *p->pUShort; goto ref;
+ case SbxBYREF | SbxSINGLE:
+ aTmp.nSingle = *p->pSingle; goto ref;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ aTmp.nDouble = *p->pDouble; goto ref;
+ case SbxBYREF | SbxULONG64:
+ aTmp.nULong64 = *p->pULong64; goto ref;
+ case SbxBYREF | SbxLONG64:
+ case SbxBYREF | SbxCURRENCY:
+ aTmp.nLong64 = *p->pLong64; goto ref;
+ case SbxBYREF | SbxSALINT64:
+ aTmp.nInt64 = *p->pnInt64; goto ref;
+ case SbxBYREF | SbxSALUINT64:
+ aTmp.uInt64 = *p->puInt64; goto ref;
+ ref:
+ aTmp.eType = SbxDataType( p->eType & 0x0FFF );
+ p = &aTmp; goto start;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0;
+ }
+ return nRes;
+}
+
+void ImpPutChar( SbxValues* p, xub_Unicode n )
+{
+ SbxValues aTmp;
+start:
+ switch( +p->eType )
+ {
+ case SbxCHAR:
+ p->nChar = n; break;
+ case SbxINTEGER:
+ case SbxBOOL:
+ p->nInteger = n; break;
+ case SbxLONG:
+ p->nLong = n; break;
+ case SbxSINGLE:
+ p->nSingle = n; break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ p->nDouble = n; break;
+ case SbxSALINT64:
+ p->nInt64 = n; break;
+ case SbxSALUINT64:
+ p->uInt64 = n; break;
+ case SbxULONG64:
+ p->nULong64 = ImpDoubleToUINT64( (double)n ); break;
+ case SbxLONG64:
+ p->nLong64 = ImpDoubleToINT64( (double)n ); break;
+ case SbxCURRENCY:
+ p->nLong64 = ImpDoubleToCurrency( (double)n ); break;
+ case SbxBYREF | SbxDECIMAL:
+ ImpCreateDecimal( p )->setChar( n );
+ break;
+
+ // from here on will be tested
+ case SbxBYTE:
+ aTmp.pByte = &p->nByte; goto direct;
+ case SbxULONG:
+ aTmp.pULong = &p->nULong; goto direct;
+ case SbxERROR:
+ case SbxUSHORT:
+ aTmp.pUShort = &p->nUShort; goto direct;
+ direct:
+ aTmp.eType = SbxDataType( p->eType | SbxBYREF );
+ p = &aTmp; goto start;
+
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+ if ( !p->pOUString )
+ p->pOUString = new ::rtl::OUString( n );
+ else
+ *p->pOUString = ::rtl::OUString( n );
+ break;
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ pVal->PutChar( n );
+ else
+ SbxBase::SetError( SbxERR_NO_OBJECT );
+ break;
+ }
+ case SbxBYREF | SbxCHAR:
+ *p->pChar = n; break;
+ case SbxBYREF | SbxBYTE:
+ *p->pByte = (BYTE) n; break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ *p->pInteger = n; break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ *p->pUShort = (UINT16) n; break;
+ case SbxBYREF | SbxLONG:
+ *p->pLong = (INT32) n; break;
+ case SbxBYREF | SbxULONG:
+ *p->pULong = (UINT32) n; break;
+ case SbxBYREF | SbxSINGLE:
+ *p->pSingle = (float) n; break;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ *p->pDouble = (double) n; break;
+ case SbxBYREF | SbxSALINT64:
+ *p->pnInt64 = n; break;
+ case SbxBYREF | SbxSALUINT64:
+ *p->puInt64 = n; break;
+ case SbxBYREF | SbxULONG64:
+ *p->pULong64 = ImpDoubleToUINT64( (double)n ); break;
+ case SbxBYREF | SbxLONG64:
+ *p->pLong64 = ImpDoubleToINT64( (double)n ); break;
+ case SbxBYREF | SbxCURRENCY:
+ *p->pLong64 = ImpDoubleToCurrency( (double)n ); break;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ }
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxcoll.cxx b/basic/source/sbx/sbxcoll.cxx
new file mode 100644
index 000000000000..5bc2e08f30e7
--- /dev/null
+++ b/basic/source/sbx/sbxcoll.cxx
@@ -0,0 +1,303 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+
+
+#include <tools/stream.hxx>
+
+#include <basic/sbx.hxx>
+#include "sbxres.hxx"
+
+TYPEINIT1(SbxCollection,SbxObject)
+TYPEINIT1(SbxStdCollection,SbxCollection)
+
+static const char* pCount;
+static const char* pAdd;
+static const char* pItem;
+static const char* pRemove;
+static USHORT nCountHash = 0, nAddHash, nItemHash, nRemoveHash;
+
+/////////////////////////////////////////////////////////////////////////
+
+SbxCollection::SbxCollection( const XubString& rClass )
+ : SbxObject( rClass )
+{
+ if( !nCountHash )
+ {
+ pCount = GetSbxRes( STRING_COUNTPROP );
+ pAdd = GetSbxRes( STRING_ADDMETH );
+ pItem = GetSbxRes( STRING_ITEMMETH );
+ pRemove = GetSbxRes( STRING_REMOVEMETH );
+ nCountHash = MakeHashCode( String::CreateFromAscii( pCount ) );
+ nAddHash = MakeHashCode( String::CreateFromAscii( pAdd ) );
+ nItemHash = MakeHashCode( String::CreateFromAscii( pItem ) );
+ nRemoveHash = MakeHashCode( String::CreateFromAscii( pRemove ) );
+ }
+ Initialize();
+ // For Access on itself
+ StartListening( GetBroadcaster(), TRUE );
+}
+
+SbxCollection::SbxCollection( const SbxCollection& rColl )
+ : SvRefBase( rColl ), SbxObject( rColl )
+{}
+
+SbxCollection& SbxCollection::operator=( const SbxCollection& r )
+{
+ if( &r != this )
+ SbxObject::operator=( r );
+ return *this;
+}
+
+SbxCollection::~SbxCollection()
+{}
+
+void SbxCollection::Clear()
+{
+ SbxObject::Clear();
+ Initialize();
+}
+
+void SbxCollection::Initialize()
+{
+ SetType( SbxOBJECT );
+ SetFlag( SBX_FIXED );
+ ResetFlag( SBX_WRITE );
+ SbxVariable* p;
+ p = Make( String::CreateFromAscii( pCount ), SbxCLASS_PROPERTY, SbxINTEGER );
+ p->ResetFlag( SBX_WRITE );
+ p->SetFlag( SBX_DONTSTORE );
+ p = Make( String::CreateFromAscii( pAdd ), SbxCLASS_METHOD, SbxEMPTY );
+ p->SetFlag( SBX_DONTSTORE );
+ p = Make( String::CreateFromAscii( pItem ), SbxCLASS_METHOD, SbxOBJECT );
+ p->SetFlag( SBX_DONTSTORE );
+ p = Make( String::CreateFromAscii( pRemove ), SbxCLASS_METHOD, SbxEMPTY );
+ p->SetFlag( SBX_DONTSTORE );
+}
+
+SbxVariable* SbxCollection::FindUserData( UINT32 nData )
+{
+ if( GetParameters() )
+ {
+ SbxObject* pObj = (SbxObject*) GetObject();
+ return pObj ? pObj->FindUserData( nData ) : NULL;
+ }
+ else
+ return SbxObject::FindUserData( nData );
+}
+
+SbxVariable* SbxCollection::Find( const XubString& rName, SbxClassType t )
+{
+ if( GetParameters() )
+ {
+ SbxObject* pObj = (SbxObject*) GetObject();
+ return pObj ? pObj->Find( rName, t ) : NULL;
+ }
+ else
+ return SbxObject::Find( rName, t );
+}
+
+void SbxCollection::SFX_NOTIFY( SfxBroadcaster& rCst, const TypeId& rId1,
+ const SfxHint& rHint, const TypeId& rId2 )
+{
+ const SbxHint* p = PTR_CAST(SbxHint,&rHint);
+ if( p )
+ {
+ ULONG nId = p->GetId();
+ BOOL bRead = BOOL( nId == SBX_HINT_DATAWANTED );
+ BOOL bWrite = BOOL( nId == SBX_HINT_DATACHANGED );
+ SbxVariable* pVar = p->GetVar();
+ SbxArray* pArg = pVar->GetParameters();
+ if( bRead || bWrite )
+ {
+ XubString aVarName( pVar->GetName() );
+ if( pVar == this )
+ CollItem( pArg );
+ else if( pVar->GetHashCode() == nCountHash
+ && aVarName.EqualsIgnoreCaseAscii( pCount ) )
+ pVar->PutLong( pObjs->Count() );
+ else if( pVar->GetHashCode() == nAddHash
+ && aVarName.EqualsIgnoreCaseAscii( pAdd ) )
+ CollAdd( pArg );
+ else if( pVar->GetHashCode() == nItemHash
+ && aVarName.EqualsIgnoreCaseAscii( pItem ) )
+ CollItem( pArg );
+ else if( pVar->GetHashCode() == nRemoveHash
+ && aVarName.EqualsIgnoreCaseAscii( pRemove ) )
+ CollRemove( pArg );
+ else
+ SbxObject::SFX_NOTIFY( rCst, rId1, rHint, rId2 );
+ return;
+ }
+ }
+ SbxObject::SFX_NOTIFY( rCst, rId1, rHint, rId2 );
+}
+
+// Default: argument is object
+
+void SbxCollection::CollAdd( SbxArray* pPar_ )
+{
+ if( pPar_->Count() != 2 )
+ SetError( SbxERR_WRONG_ARGS );
+ else
+ {
+ SbxBase* pObj = pPar_->Get( 1 )->GetObject();
+ if( !pObj || !( pObj->ISA(SbxObject) ) )
+ SetError( SbxERR_NOTIMP );
+ else
+ Insert( (SbxObject*) pObj );
+ }
+}
+
+// Default: index from 1 or object name
+
+void SbxCollection::CollItem( SbxArray* pPar_ )
+{
+ if( pPar_->Count() != 2 )
+ SetError( SbxERR_WRONG_ARGS );
+ else
+ {
+ SbxVariable* pRes = NULL;
+ SbxVariable* p = pPar_->Get( 1 );
+ if( p->GetType() == SbxSTRING )
+ pRes = Find( p->GetString(), SbxCLASS_OBJECT );
+ else
+ {
+ short n = p->GetInteger();
+ if( n >= 1 && n <= (short) pObjs->Count() )
+ pRes = pObjs->Get( (USHORT) n - 1 );
+ }
+ if( !pRes )
+ SetError( SbxERR_BAD_INDEX );
+ pPar_->Get( 0 )->PutObject( pRes );
+ }
+}
+
+// Default: index from 1
+
+void SbxCollection::CollRemove( SbxArray* pPar_ )
+{
+ if( pPar_->Count() != 2 )
+ SetError( SbxERR_WRONG_ARGS );
+ else
+ {
+ short n = pPar_->Get( 1 )->GetInteger();
+ if( n < 1 || n > (short) pObjs->Count() )
+ SetError( SbxERR_BAD_INDEX );
+ else
+ Remove( pObjs->Get( (USHORT) n - 1 ) );
+ }
+}
+
+BOOL SbxCollection::LoadData( SvStream& rStrm, USHORT nVer )
+{
+ BOOL bRes = SbxObject::LoadData( rStrm, nVer );
+ Initialize();
+ return bRes;
+}
+
+/////////////////////////////////////////////////////////////////////////
+
+SbxStdCollection::SbxStdCollection
+ ( const XubString& rClass, const XubString& rElem, BOOL b )
+ : SbxCollection( rClass ), aElemClass( rElem ),
+ bAddRemoveOk( b )
+{}
+
+SbxStdCollection::SbxStdCollection( const SbxStdCollection& r )
+ : SvRefBase( r ), SbxCollection( r ),
+ aElemClass( r.aElemClass ), bAddRemoveOk( r.bAddRemoveOk )
+{}
+
+SbxStdCollection& SbxStdCollection::operator=( const SbxStdCollection& r )
+{
+ if( &r != this )
+ {
+ if( !r.aElemClass.EqualsIgnoreCaseAscii( aElemClass ) )
+ SetError( SbxERR_CONVERSION );
+ else
+ SbxCollection::operator=( r );
+ }
+ return *this;
+}
+
+SbxStdCollection::~SbxStdCollection()
+{}
+
+// Default: Error, if wrong object
+
+void SbxStdCollection::Insert( SbxVariable* p )
+{
+ SbxObject* pObj = PTR_CAST(SbxObject,p);
+ if( pObj && !pObj->IsClass( aElemClass ) )
+ SetError( SbxERR_BAD_ACTION );
+ else
+ SbxCollection::Insert( p );
+}
+
+void SbxStdCollection::CollAdd( SbxArray* pPar_ )
+{
+ if( !bAddRemoveOk )
+ SetError( SbxERR_BAD_ACTION );
+ else
+ SbxCollection::CollAdd( pPar_ );
+}
+
+void SbxStdCollection::CollRemove( SbxArray* pPar_ )
+{
+ if( !bAddRemoveOk )
+ SetError( SbxERR_BAD_ACTION );
+ else
+ SbxCollection::CollRemove( pPar_ );
+}
+
+BOOL SbxStdCollection::LoadData( SvStream& rStrm, USHORT nVer )
+{
+ BOOL bRes = SbxCollection::LoadData( rStrm, nVer );
+ if( bRes )
+ {
+ rStrm.ReadByteString( aElemClass, RTL_TEXTENCODING_ASCII_US );
+ rStrm >> bAddRemoveOk;
+ }
+ return bRes;
+}
+
+BOOL SbxStdCollection::StoreData( SvStream& rStrm ) const
+{
+ BOOL bRes = SbxCollection::StoreData( rStrm );
+ if( bRes )
+ {
+ rStrm.WriteByteString( aElemClass, RTL_TEXTENCODING_ASCII_US );
+ rStrm << bAddRemoveOk;
+ }
+ return bRes;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxconv.hxx b/basic/source/sbx/sbxconv.hxx
new file mode 100644
index 000000000000..66ce3fb03efb
--- /dev/null
+++ b/basic/source/sbx/sbxconv.hxx
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _SBXCONV_HXX
+#define _SBXCONV_HXX
+
+#include "sbxdec.hxx"
+
+class SbxArray;
+
+// SBXSCAN.CXX
+extern void ImpCvtNum( double nNum, short nPrec, ::rtl::OUString& rRes, BOOL bCoreString=FALSE );
+extern SbxError ImpScan
+ ( const ::rtl::OUString& rSrc, double& nVal, SbxDataType& rType, USHORT* pLen,
+ BOOL bAllowIntntl=FALSE, BOOL bOnlyIntntl=FALSE );
+
+// with advanced evaluation (International, "TRUE"/"FALSE")
+extern BOOL ImpConvStringExt( ::rtl::OUString& rSrc, SbxDataType eTargetType );
+
+// SBXINT.CXX
+
+double ImpRound( double );
+INT16 ImpGetInteger( const SbxValues* );
+void ImpPutInteger( SbxValues*, INT16 );
+sal_Int64 ImpGetInt64( const SbxValues* );
+void ImpPutInt64( SbxValues*, sal_Int64 );
+sal_uInt64 ImpGetUInt64( const SbxValues* );
+void ImpPutUInt64( SbxValues*, sal_uInt64 );
+
+sal_Int64 ImpDoubleToSalInt64( double d );
+sal_uInt64 ImpDoubleToSalUInt64( double d );
+double ImpSalUInt64ToDouble( sal_uInt64 n );
+
+// SBXLNG.CXX
+
+INT32 ImpGetLong( const SbxValues* );
+void ImpPutLong( SbxValues*, INT32 );
+
+// SBXSNG.CXX
+
+float ImpGetSingle( const SbxValues* );
+void ImpPutSingle( SbxValues*, float );
+
+// SBXDBL.CXX
+
+double ImpGetDouble( const SbxValues* );
+void ImpPutDouble( SbxValues*, double, BOOL bCoreString=FALSE );
+
+#if FALSE
+// SBX64.CXX
+
+SbxINT64 ImpGetINT64( const SbxValues* );
+void ImpPutINT64( SbxValues*, const SbxINT64& );
+SbxUINT64 ImpGetUINT64( const SbxValues* );
+void ImpPutUINT64( SbxValues*, const SbxUINT64& );
+#endif
+
+// SBXCURR.CXX
+
+SbxUINT64 ImpDoubleToUINT64( double );
+double ImpUINT64ToDouble( const SbxUINT64& );
+SbxINT64 ImpDoubleToINT64( double );
+double ImpINT64ToDouble( const SbxINT64& );
+
+#if TRUE
+INT32 ImpGetCurrLong( const SbxValues* );
+void ImpPutCurrLong( SbxValues*, INT32 );
+INT32 ImpDoubleToCurrLong( double );
+double ImpCurrLongToDouble( INT32 );
+#endif
+
+SbxINT64 ImpGetCurrency( const SbxValues* );
+void ImpPutCurrency( SbxValues*, const SbxINT64& );
+inline
+SbxINT64 ImpDoubleToCurrency( double d )
+ { return ImpDoubleToINT64( d * CURRENCY_FACTOR ); }
+inline
+double ImpCurrencyToDouble( const SbxINT64 &r )
+ { return ImpINT64ToDouble( r ) / CURRENCY_FACTOR; }
+
+
+// SBXDEC.CXX
+
+SbxDecimal* ImpCreateDecimal( SbxValues* p );
+SbxDecimal* ImpGetDecimal( const SbxValues* p );
+void ImpPutDecimal( SbxValues* p, SbxDecimal* pDec );
+
+// SBXDATE.CXX
+
+double ImpGetDate( const SbxValues* );
+void ImpPutDate( SbxValues*, double );
+
+// SBXSTR.CXX
+
+::rtl::OUString ImpGetString( const SbxValues* );
+::rtl::OUString ImpGetCoreString( const SbxValues* );
+void ImpPutString( SbxValues*, const ::rtl::OUString* );
+
+// SBXCHAR.CXX
+
+sal_Unicode ImpGetChar( const SbxValues* );
+void ImpPutChar( SbxValues*, sal_Unicode );
+
+// SBXBYTE.CXX
+BYTE ImpGetByte( const SbxValues* );
+void ImpPutByte( SbxValues*, BYTE );
+
+// SBXUINT.CXX
+
+UINT16 ImpGetUShort( const SbxValues* );
+void ImpPutUShort( SbxValues*, UINT16 );
+
+// SBXULNG.CXX
+
+UINT32 ImpGetULong( const SbxValues* );
+void ImpPutULong( SbxValues*, UINT32 );
+
+// SBXBOOL.CXX
+
+enum SbxBOOL ImpGetBool( const SbxValues* );
+void ImpPutBool( SbxValues*, INT16 );
+
+// ByteArry <--> String
+SbxArray* StringToByteArray(const ::rtl::OUString& rStr);
+::rtl::OUString ByteArrayToString(SbxArray* pArr);
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxcurr.cxx b/basic/source/sbx/sbxcurr.cxx
new file mode 100644
index 000000000000..0057d6f93aea
--- /dev/null
+++ b/basic/source/sbx/sbxcurr.cxx
@@ -0,0 +1,397 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+
+#include <basic/sbx.hxx>
+#include <tools/errcode.hxx>
+
+#define _TLBIGINT_INT64
+#include <tools/bigint.hxx>
+
+#include <basic/sbxvar.hxx>
+#include "sbxconv.hxx"
+
+static ::rtl::OUString ImpCurrencyToString( const SbxINT64& );
+static SbxINT64 ImpStringToCurrency( const ::rtl::OUString& );
+
+SbxINT64 ImpGetCurrency( const SbxValues* p )
+{
+ SbxValues aTmp;
+ SbxINT64 nRes;
+start:
+ switch( +p->eType )
+ {
+ case SbxNULL:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ case SbxEMPTY:
+ nRes.SetNull(); break;
+ case SbxCHAR:
+ nRes = ImpDoubleToCurrency( (double)p->nChar ); break;
+ case SbxBYTE:
+ nRes = ImpDoubleToCurrency( (double)p->nByte ); break;
+ case SbxINTEGER:
+ case SbxBOOL:
+ nRes = ImpDoubleToCurrency( (double)p->nInteger ); break;
+ case SbxERROR:
+ case SbxUSHORT:
+ nRes = ImpDoubleToCurrency( (double)p->nUShort ); break;
+ case SbxCURRENCY:
+ nRes = p->nLong64; break;
+ case SbxLONG:
+ nRes = ImpDoubleToCurrency( (double)p->nLong );
+ break;
+ case SbxULONG:
+ nRes = ImpDoubleToCurrency( (double)p->nULong );
+ break;
+ case SbxSALINT64:
+ nRes = ImpDoubleToCurrency( (double)p->nInt64 );
+ break;
+ case SbxSALUINT64:
+ nRes = ImpDoubleToCurrency( ImpSalUInt64ToDouble( p->uInt64 ) );
+ break;
+ case SbxSINGLE:
+ if( p->nSingle > SbxMAXCURR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes.SetMax();
+ }
+ else if( p->nSingle < SbxMINCURR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes.SetMin();
+ }
+ else
+ nRes = ImpDoubleToCurrency( (double)p->nSingle );
+ break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ if( p->nDouble > SbxMAXCURR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes.SetMax();
+ }
+ else if( p->nDouble < SbxMINCURR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes.SetMin();
+ }
+ else
+ nRes = ImpDoubleToCurrency( p->nDouble );
+ break;
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ {
+ double d = 0.0;
+ if( p->pDecimal )
+ p->pDecimal->getDouble( d );
+ if( d > SbxMAXCURR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes.SetMax();
+ }
+ else if( d < SbxMINCURR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes.SetMin();
+ }
+ else
+ nRes = ImpDoubleToCurrency( d );
+ break;
+ }
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+ if( !p->pOUString )
+ nRes.SetNull();
+ else
+ nRes = ImpStringToCurrency( *p->pOUString );
+ break;
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ nRes = pVal->GetCurrency();
+ else
+ {
+ SbxBase::SetError( SbxERR_NO_OBJECT ); nRes.SetNull();
+ }
+ break;
+ }
+
+ case SbxBYREF | SbxCHAR:
+ nRes = ImpDoubleToCurrency( (double)*p->pChar ); break;
+ case SbxBYREF | SbxBYTE:
+ nRes = ImpDoubleToCurrency( (double)*p->pByte ); break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ nRes = ImpDoubleToCurrency( (double)*p->pInteger ); break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ nRes = ImpDoubleToCurrency( (double)*p->pUShort ); break;
+ case SbxBYREF | SbxCURRENCY:
+ nRes = *p->pLong64; break;
+
+ // from here on had to be tested
+ case SbxBYREF | SbxLONG:
+ aTmp.nLong = *p->pLong; goto ref;
+ case SbxBYREF | SbxULONG:
+ aTmp.nULong = *p->pULong; goto ref;
+ case SbxBYREF | SbxSINGLE:
+ aTmp.nSingle = *p->pSingle; goto ref;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ aTmp.nDouble = *p->pDouble; goto ref;
+ case SbxBYREF | SbxSALINT64:
+ aTmp.nInt64 = *p->pnInt64; goto ref;
+ case SbxBYREF | SbxSALUINT64:
+ aTmp.uInt64 = *p->puInt64; goto ref;
+ ref:
+ aTmp.eType = SbxDataType( p->eType & 0x0FFF );
+ p = &aTmp; goto start;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION ); nRes.SetNull();
+ }
+ return nRes;
+}
+
+void ImpPutCurrency( SbxValues* p, const SbxINT64 &r )
+{
+ double dVal = ImpCurrencyToDouble( r );
+ SbxValues aTmp;
+start:
+ switch( +p->eType )
+ {
+ // Here are tests necessary
+ case SbxCHAR:
+ aTmp.pChar = &p->nChar; goto direct;
+ case SbxBYTE:
+ aTmp.pByte = &p->nByte; goto direct;
+ case SbxINTEGER:
+ case SbxBOOL:
+ aTmp.pInteger = &p->nInteger; goto direct;
+ case SbxLONG:
+ aTmp.pLong = &p->nLong; goto direct;
+ case SbxULONG:
+ aTmp.pULong = &p->nULong; goto direct;
+ case SbxERROR:
+ case SbxUSHORT:
+ aTmp.pUShort = &p->nUShort; goto direct;
+ direct:
+ aTmp.eType = SbxDataType( p->eType | SbxBYREF );
+ p = &aTmp; goto start;
+
+ // from here no longer
+ case SbxSINGLE:
+ p->nSingle = (float)dVal; break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ p->nDouble = dVal; break;
+ case SbxSALINT64:
+ p->nInt64 = ImpDoubleToSalInt64( dVal ); break;
+ case SbxSALUINT64:
+ p->uInt64 = ImpDoubleToSalUInt64( dVal ); break;
+ case SbxCURRENCY:
+ p->nLong64 = r; break;
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ {
+ SbxDecimal* pDec = ImpCreateDecimal( p );
+ if( !pDec->setDouble( dVal ) )
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ break;
+ }
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+ if( !p->pOUString )
+ p->pOUString = new ::rtl::OUString;
+
+ *p->pOUString = ImpCurrencyToString( r );
+ break;
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ pVal->PutCurrency( r );
+ else
+ SbxBase::SetError( SbxERR_NO_OBJECT );
+ break;
+ }
+ case SbxBYREF | SbxCHAR:
+ if( dVal > SbxMAXCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMAXCHAR;
+ }
+ else if( dVal < SbxMINCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMINCHAR;
+ }
+ *p->pChar = (xub_Unicode) dVal; break;
+ case SbxBYREF | SbxBYTE:
+ if( dVal > SbxMAXBYTE )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMAXBYTE;
+ }
+ else if( dVal < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); dVal = 0;
+ }
+ *p->pByte = (BYTE) dVal; break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ if( dVal > SbxMAXINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMAXINT;
+ }
+ else if( dVal < SbxMININT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMININT;
+ }
+ *p->pInteger = (INT16) dVal; break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ if( dVal > SbxMAXUINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMAXUINT;
+ }
+ else if( dVal < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); dVal = 0;
+ }
+ *p->pUShort = (UINT16) dVal; break;
+ case SbxBYREF | SbxLONG:
+ if( dVal > SbxMAXLNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMAXLNG;
+ }
+ else if( dVal < SbxMINLNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMINLNG;
+ }
+ *p->pLong = (INT32) dVal; break;
+ case SbxBYREF | SbxULONG:
+ if( dVal > SbxMAXULNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMAXULNG;
+ }
+ else if( dVal < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); dVal = 0;
+ }
+ *p->pULong = (UINT32) dVal; break;
+ case SbxBYREF | SbxSALINT64:
+ *p->pnInt64 = ImpDoubleToSalInt64( dVal ); break;
+ case SbxBYREF | SbxSALUINT64:
+ *p->puInt64 = ImpDoubleToSalUInt64( dVal ); break;
+ case SbxBYREF | SbxSINGLE:
+ *p->pSingle = (float) dVal; break;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ *p->pDouble = (double) dVal; break;
+ case SbxBYREF | SbxCURRENCY:
+ *p->pLong64 = r; break;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ }
+}
+
+// help functions for the conversion
+
+static ::rtl::OUString ImpCurrencyToString( const SbxINT64 &r )
+{
+ BigInt a10000 = 10000;
+
+ //return GetpApp()->GetAppInternational().GetCurr( BigInt( r ), 4 );
+ BigInt aInt( r );
+ aInt.Abs();
+ BigInt aFrac = aInt;
+ aInt /= a10000;
+ aFrac %= a10000;
+ aFrac += a10000;
+
+ ::rtl::OUString aString;
+ if( r.nHigh < 0 )
+ aString = ::rtl::OUString( (sal_Unicode)'-' );
+ aString += aInt.GetString();
+ aString += ::rtl::OUString( (sal_Unicode)'.' );
+ aString += aFrac.GetString().GetBuffer()+1;
+ return aString;
+}
+
+static SbxINT64 ImpStringToCurrency( const ::rtl::OUString &r )
+{
+ int nDec = 4;
+ String aStr;
+ const sal_Unicode* p = r.getStr();
+
+ if( *p == '-' )
+ aStr += *p++;
+
+ while( *p >= '0' && *p <= '9' ) {
+ aStr += *p++;
+ if( *p == ',' )
+ p++;
+ }
+
+ if( *p == '.' ) {
+ p++;
+ while( nDec && *p >= '0' && *p <= '9' ) {
+ aStr += *p++;
+ nDec--;
+ }
+ }
+ while( nDec ) {
+ aStr += '0';
+ nDec--;
+ }
+
+ BigInt aBig( aStr );
+ SbxINT64 nRes;
+ aBig.INT64( &nRes );
+ return nRes;
+}
+
+double ImpINT64ToDouble( const SbxINT64 &r )
+{ return (double)r.nHigh*(double)4294967296.0 + (double)r.nLow; }
+
+SbxINT64 ImpDoubleToINT64( double d )
+{
+ SbxINT64 nRes;
+ nRes.Set( d );
+ return nRes;
+}
+
+double ImpUINT64ToDouble( const SbxUINT64 &r )
+{ return (double)r.nHigh*(double)4294967296.0 + (double)r.nLow; }
+
+SbxUINT64 ImpDoubleToUINT64( double d )
+{
+ SbxUINT64 nRes;
+ nRes.Set( d );
+ return nRes;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxdate.cxx b/basic/source/sbx/sbxdate.cxx
new file mode 100644
index 000000000000..ed151a79679f
--- /dev/null
+++ b/basic/source/sbx/sbxdate.cxx
@@ -0,0 +1,416 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+#include <vcl/svapp.hxx>
+#include <svl/zforlist.hxx>
+#include <tools/errcode.hxx>
+#include <tools/color.hxx>
+#include <i18npool/lang.h>
+#include <basic/sbx.hxx>
+#include "sbxconv.hxx"
+#include "math.h"
+#include <comphelper/processfactory.hxx>
+
+
+double ImpGetDate( const SbxValues* p )
+{
+ double nRes;
+ switch( +p->eType )
+ {
+ case SbxNULL:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ case SbxEMPTY:
+ nRes = 0; break;
+ case SbxCHAR:
+ nRes = p->nChar; break;
+ case SbxBYTE:
+ nRes = p->nByte; break;
+ case SbxINTEGER:
+ case SbxBOOL:
+ nRes = p->nInteger; break;
+ case SbxERROR:
+ case SbxUSHORT:
+ nRes = p->nUShort; break;
+ case SbxLONG:
+ nRes = (double) p->nLong; break;
+ case SbxULONG:
+ nRes = (double) p->nULong; break;
+ case SbxSINGLE:
+ nRes = p->nSingle; break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ nRes = p->nDouble; break;
+ case SbxULONG64:
+ nRes = ImpUINT64ToDouble( p->nULong64 ); break;
+ case SbxLONG64:
+ nRes = ImpINT64ToDouble( p->nLong64 ); break;
+ case SbxCURRENCY:
+ nRes = ImpCurrencyToDouble( p->nLong64 ); break;
+ case SbxSALINT64:
+ nRes = static_cast< double >(p->nInt64); break;
+ case SbxSALUINT64:
+ nRes = ImpSalUInt64ToDouble( p->uInt64 ); break;
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ if( p->pDecimal )
+ p->pDecimal->getDouble( nRes );
+ else
+ nRes = 0.0;
+ break;
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+ if( !p->pOUString )
+ nRes = 0;
+ else
+ {
+#ifndef DOS
+ LanguageType eLangType = GetpApp()->GetSettings().GetLanguage();
+
+ SvNumberFormatter* pFormatter;
+ com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >
+ xFactory = comphelper::getProcessServiceFactory();
+ pFormatter = new SvNumberFormatter( xFactory, eLangType );
+
+ sal_uInt32 nIndex;
+ xub_StrLen nCheckPos = 0;
+ short nType = 127;
+
+ // Default templates of the formatter have only two-digit
+ // date. Therefore register an own format.
+
+ // HACK, because the number formatter in PutandConvertEntry replace the wildcard
+ // for month, day, year not according to the configuration.
+ // Problem: Print Year(Date) under Engl. OS
+ // quod vide basic\source\runtime\runtime.cxx
+
+ SvtSysLocale aSysLocale;
+ DateFormat eDate = aSysLocale.GetLocaleData().getDateFormat();
+ String aDateStr;
+ switch( eDate )
+ {
+ case MDY: aDateStr.AssignAscii( "MM.TT.JJJJ" ); break;
+ case DMY: aDateStr.AssignAscii( "TT.MM.JJJJ" ); break;
+ case YMD: aDateStr.AssignAscii( "JJJJ.MM.TT" ); break;
+ default: aDateStr.AssignAscii( "MM.TT.JJJJ" );
+ }
+
+ String aStr( aDateStr );
+ aStr.AppendAscii( " HH:MM:SS" );
+
+ pFormatter->PutandConvertEntry( aStr, nCheckPos, nType,
+ nIndex, LANGUAGE_GERMAN, eLangType );
+ BOOL bSuccess = pFormatter->IsNumberFormat( *p->pOUString, nIndex, nRes );
+ if ( bSuccess )
+ {
+ short nType_ = pFormatter->GetType( nIndex );
+ if(!(nType_ & ( NUMBERFORMAT_DATETIME | NUMBERFORMAT_DATE |
+ NUMBERFORMAT_TIME | NUMBERFORMAT_DEFINED )))
+ bSuccess = FALSE;
+ }
+
+ if ( !bSuccess )
+ {
+ SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0;
+ }
+
+ delete pFormatter;
+#else
+ SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0;
+#endif
+ }
+ break;
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ nRes = pVal->GetDate();
+ else
+ {
+ SbxBase::SetError( SbxERR_NO_OBJECT ); nRes = 0;
+ }
+ break;
+ }
+
+ case SbxBYREF | SbxCHAR:
+ nRes = *p->pChar; break;
+ case SbxBYREF | SbxBYTE:
+ nRes = *p->pByte; break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ nRes = *p->pInteger; break;
+ case SbxBYREF | SbxLONG:
+ nRes = *p->pLong; break;
+ case SbxBYREF | SbxULONG:
+ nRes = *p->pULong; break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ nRes = *p->pUShort; break;
+ case SbxBYREF | SbxSINGLE:
+ nRes = *p->pSingle; break;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ nRes = *p->pDouble; break;
+ case SbxBYREF | SbxULONG64:
+ nRes = ImpUINT64ToDouble( *p->pULong64 ); break;
+ case SbxBYREF | SbxLONG64:
+ nRes = ImpINT64ToDouble( *p->pLong64 ); break;
+ case SbxBYREF | SbxCURRENCY:
+ nRes = ImpCurrencyToDouble( *p->pLong64 ); break;
+ case SbxBYREF | SbxSALINT64:
+ nRes = static_cast< double >(*p->pnInt64); break;
+ case SbxBYREF | SbxSALUINT64:
+ nRes = ImpSalUInt64ToDouble( *p->puInt64 ); break;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0;
+ }
+ return nRes;
+}
+
+void ImpPutDate( SbxValues* p, double n )
+{
+ SbxValues aTmp;
+
+start:
+ switch( +p->eType )
+ {
+ case SbxDATE:
+ case SbxDOUBLE:
+ p->nDouble = n; break;
+
+ // from here will be tested
+ case SbxCHAR:
+ aTmp.pChar = &p->nChar; goto direct;
+ case SbxBYTE:
+ aTmp.pByte = &p->nByte; goto direct;
+ case SbxINTEGER:
+ case SbxBOOL:
+ aTmp.pInteger = &p->nInteger; goto direct;
+ case SbxLONG:
+ aTmp.pLong = &p->nLong; goto direct;
+ case SbxULONG:
+ aTmp.pULong = &p->nULong; goto direct;
+ case SbxERROR:
+ case SbxUSHORT:
+ aTmp.pUShort = &p->nUShort; goto direct;
+ case SbxSINGLE:
+ aTmp.pSingle = &p->nSingle; goto direct;
+ case SbxULONG64:
+ aTmp.pULong64 = &p->nULong64; goto direct;
+ case SbxLONG64:
+ case SbxCURRENCY:
+ aTmp.pLong64 = &p->nLong64; goto direct;
+ case SbxSALINT64:
+ aTmp.pnInt64 = &p->nInt64; goto direct;
+ case SbxSALUINT64:
+ aTmp.puInt64 = &p->uInt64; goto direct;
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ {
+ SbxDecimal* pDec = ImpCreateDecimal( p );
+ if( !pDec->setDouble( n ) )
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ break;
+ }
+ direct:
+ aTmp.eType = SbxDataType( p->eType | SbxBYREF );
+ p = &aTmp; goto start;
+
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+#ifndef DOS
+ {
+ if( !p->pOUString )
+ p->pOUString = new ::rtl::OUString;
+ Color* pColor;
+
+ LanguageType eLangType = GetpApp()->GetSettings().GetLanguage();
+ SvNumberFormatter* pFormatter;
+ com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >
+ xFactory = comphelper::getProcessServiceFactory();
+ pFormatter = new SvNumberFormatter( xFactory, eLangType );
+
+ sal_uInt32 nIndex;
+ xub_StrLen nCheckPos = 0;
+ short nType;
+
+ SvtSysLocale aSysLocale;
+ DateFormat eDate = aSysLocale.GetLocaleData().getDateFormat();
+ String aStr;
+ // if the whole-number part is 0, we want no year!
+ if( n <= -1.0 || n >= 1.0 )
+ {
+ // Time only if != 00:00:00
+ if( floor( n ) == n )
+ {
+ switch( eDate )
+ {
+ case MDY: aStr.AssignAscii( "MM.TT.JJJJ" ); break;
+ case DMY: aStr.AssignAscii( "TT.MM.JJJJ" ); break;
+ case YMD: aStr.AssignAscii( "JJJJ.MM.TT" ); break;
+ default: aStr.AssignAscii( "MM.TT.JJJJ" );
+ }
+ }
+ else
+ {
+ switch( eDate )
+ {
+ case MDY: aStr.AssignAscii( "MM.TT.JJJJ HH:MM:SS" ); break;
+ case DMY: aStr.AssignAscii( "TT.MM.JJJJ HH:MM:SS" ); break;
+ case YMD: aStr.AssignAscii( "JJJJ.MM.TT HH:MM:SS" ); break;
+ default: aStr.AssignAscii( "MM.TT.JJJJ HH:MM:SS" );
+ }
+ }
+ }
+ else
+ aStr.AppendAscii( "HH:MM:SS" );
+
+ pFormatter->PutandConvertEntry( aStr,
+ nCheckPos,
+ nType,
+ nIndex,
+ LANGUAGE_GERMAN,
+ eLangType );
+ String aTmpString;
+ pFormatter->GetOutputString( n, nIndex, aTmpString, &pColor );
+ *p->pOUString = aTmpString;
+ delete pFormatter;
+#endif
+ break;
+#ifndef DOS
+ }
+#endif
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ pVal->PutDate( n );
+ else
+ SbxBase::SetError( SbxERR_NO_OBJECT );
+ break;
+ }
+ case SbxBYREF | SbxCHAR:
+ if( n > SbxMAXCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXCHAR;
+ }
+ else if( n < SbxMINCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINCHAR;
+ }
+ *p->pChar = (xub_Unicode) n; break;
+ case SbxBYREF | SbxBYTE:
+ if( n > SbxMAXBYTE )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXBYTE;
+ }
+ else if( n < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = 0;
+ }
+ *p->pByte = (BYTE) n; break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ if( n > SbxMAXINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXINT;
+ }
+ else if( n < SbxMININT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMININT;
+ }
+ *p->pInteger = (INT16) n; break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ if( n > SbxMAXUINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXUINT;
+ }
+ else if( n < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = 0;
+ }
+ *p->pUShort = (UINT16) n; break;
+ case SbxBYREF | SbxLONG:
+ if( n > SbxMAXLNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXLNG;
+ }
+ else if( n < SbxMINLNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINLNG;
+ }
+ *p->pLong = (INT32) n; break;
+ case SbxBYREF | SbxULONG:
+ if( n > SbxMAXULNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXULNG;
+ }
+ else if( n < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = 0;
+ }
+ *p->pULong = (UINT32) n; break;
+ case SbxBYREF | SbxSINGLE:
+ if( n > SbxMAXSNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXSNG;
+ }
+ else if( n < SbxMINSNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINSNG;
+ }
+ *p->pSingle = (float) n; break;
+ case SbxBYREF | SbxSALINT64:
+ *p->pnInt64 = ImpDoubleToSalInt64( n ); break;
+ case SbxBYREF | SbxSALUINT64:
+ *p->puInt64 = ImpDoubleToSalUInt64( n ); break;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ *p->pDouble = (double) n; break;
+ case SbxBYREF | SbxCURRENCY:
+ if( n > SbxMAXCURR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXCURR;
+ }
+ else if( n < SbxMINCURR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINCURR;
+ }
+ *p->pLong64 = ImpDoubleToCurrency( n ); break;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxdbl.cxx b/basic/source/sbx/sbxdbl.cxx
new file mode 100644
index 000000000000..32d4a891b341
--- /dev/null
+++ b/basic/source/sbx/sbxdbl.cxx
@@ -0,0 +1,308 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+#include <tools/errcode.hxx>
+#include <basic/sbx.hxx>
+#include "sbxconv.hxx"
+#include "runtime.hxx"
+
+double ImpGetDouble( const SbxValues* p )
+{
+ double nRes;
+ switch( +p->eType )
+ {
+ case SbxNULL:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ case SbxEMPTY:
+ nRes = 0; break;
+ case SbxCHAR:
+ nRes = p->nChar; break;
+ case SbxBYTE:
+ nRes = p->nByte; break;
+ case SbxINTEGER:
+ case SbxBOOL:
+ nRes = p->nInteger; break;
+ case SbxERROR:
+ case SbxUSHORT:
+ nRes = p->nUShort; break;
+ case SbxLONG:
+ nRes = p->nLong; break;
+ case SbxULONG:
+ nRes = p->nULong; break;
+ case SbxSINGLE:
+ nRes = p->nSingle; break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ nRes = p->nDouble; break;
+ case SbxCURRENCY:
+ nRes = ImpCurrencyToDouble( p->nLong64 ); break;
+ case SbxSALINT64:
+ nRes = static_cast< double >(p->nInt64); break;
+ case SbxSALUINT64:
+ nRes = ImpSalUInt64ToDouble( p->uInt64 ); break;
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ if( p->pDecimal )
+ p->pDecimal->getDouble( nRes );
+ else
+ nRes = 0.0;
+ break;
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+ if( !p->pOUString )
+ {
+ nRes = 0;
+ if ( SbiRuntime::isVBAEnabled() )// VBA only behaviour
+ SbxBase::SetError( SbxERR_CONVERSION );
+ }
+ else
+ {
+ double d;
+ SbxDataType t;
+ if( ImpScan( *p->pOUString, d, t, NULL ) != SbxERR_OK )
+ {
+ nRes = 0;
+ if ( SbiRuntime::isVBAEnabled() )// VBA only behaviour
+ SbxBase::SetError( SbxERR_CONVERSION );
+ }
+ else
+ nRes = d;
+ }
+ break;
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ nRes = pVal->GetDouble();
+ else
+ {
+ SbxBase::SetError( SbxERR_NO_OBJECT ); nRes = 0;
+ }
+ break;
+ }
+
+ case SbxBYREF | SbxCHAR:
+ nRes = *p->pChar; break;
+ case SbxBYREF | SbxBYTE:
+ nRes = *p->pByte; break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ nRes = *p->pInteger; break;
+ case SbxBYREF | SbxLONG:
+ nRes = *p->pLong; break;
+ case SbxBYREF | SbxULONG:
+ nRes = *p->pULong; break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ nRes = *p->pUShort; break;
+ case SbxBYREF | SbxSINGLE:
+ nRes = *p->pSingle; break;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ nRes = *p->pDouble; break;
+ case SbxBYREF | SbxCURRENCY:
+ nRes = ImpCurrencyToDouble( *p->pLong64 ); break;
+ case SbxBYREF | SbxSALINT64:
+ nRes = static_cast< double >(*p->pnInt64); break;
+ case SbxBYREF | SbxSALUINT64:
+ nRes = ImpSalUInt64ToDouble( *p->puInt64 ); break;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0;
+ }
+ return nRes;
+}
+
+void ImpPutDouble( SbxValues* p, double n, BOOL bCoreString )
+{
+ SbxValues aTmp;
+start:
+ switch( +p->eType )
+ {
+ // Here are tests necessary
+ case SbxCHAR:
+ aTmp.pChar = &p->nChar; goto direct;
+ case SbxBYTE:
+ aTmp.pByte = &p->nByte; goto direct;
+ case SbxINTEGER:
+ case SbxBOOL:
+ aTmp.pInteger = &p->nInteger; goto direct;
+ case SbxLONG:
+ case SbxCURRENCY:
+ aTmp.pLong = &p->nLong; goto direct;
+ case SbxULONG:
+ aTmp.pULong = &p->nULong; goto direct;
+ case SbxERROR:
+ case SbxUSHORT:
+ aTmp.pUShort = &p->nUShort; goto direct;
+ case SbxSINGLE:
+ aTmp.pSingle = &p->nSingle; goto direct;
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ {
+ SbxDecimal* pDec = ImpCreateDecimal( p );
+ if( !pDec->setDouble( n ) )
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ break;
+ }
+ direct:
+ aTmp.eType = SbxDataType( p->eType | SbxBYREF );
+ p = &aTmp; goto start;
+
+ // from here on no longer
+ case SbxSALINT64:
+ p->nInt64 = ImpDoubleToSalInt64( n ); break;
+ case SbxSALUINT64:
+ p->uInt64 = ImpDoubleToSalUInt64( n ); break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ p->nDouble = n; break;
+
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+ if( !p->pOUString )
+ p->pOUString = new ::rtl::OUString;
+ ImpCvtNum( (double) n, 14, *p->pOUString, bCoreString );
+ break;
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ pVal->PutDouble( n );
+ else
+ SbxBase::SetError( SbxERR_NO_OBJECT );
+ break;
+ }
+ case SbxBYREF | SbxCHAR:
+ if( n > SbxMAXCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXCHAR;
+ }
+ else if( n < SbxMINCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINCHAR;
+ }
+ *p->pChar = (xub_Unicode) n; break;
+ case SbxBYREF | SbxBYTE:
+ if( n > SbxMAXBYTE )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXBYTE;
+ }
+ else if( n < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = 0;
+ }
+ *p->pByte = (BYTE) n; break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ if( n > SbxMAXINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXINT;
+ }
+ else if( n < SbxMININT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMININT;
+ }
+ *p->pInteger = (INT16) n; break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ if( n > SbxMAXUINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXUINT;
+ }
+ else if( n < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = 0;
+ }
+ *p->pUShort = (UINT16) n; break;
+ case SbxBYREF | SbxLONG:
+ if( n > SbxMAXLNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXLNG;
+ }
+ else if( n < SbxMINLNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINLNG;
+ }
+ *p->pLong = (INT32) n; break;
+ case SbxBYREF | SbxULONG:
+ if( n > SbxMAXULNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXULNG;
+ }
+ else if( n < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = 0;
+ }
+ *p->pULong = (UINT32) n; break;
+ case SbxBYREF | SbxSINGLE:
+ if( n > SbxMAXSNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXSNG;
+ }
+ else if( n < SbxMINSNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINSNG;
+ }
+ else if( n > 0 && n < SbxMAXSNG2 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXSNG2;
+ }
+ else if( n < 0 && n > SbxMINSNG2 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINSNG2;
+ }
+ *p->pSingle = (float) n; break;
+ case SbxBYREF | SbxSALINT64:
+ *p->pnInt64 = ImpDoubleToSalInt64( n ); break;
+ case SbxBYREF | SbxSALUINT64:
+ *p->puInt64 = ImpDoubleToSalUInt64( n ); break;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ *p->pDouble = (double) n; break;
+ case SbxBYREF | SbxCURRENCY:
+ if( n > SbxMAXCURR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXCURR;
+ }
+ else if( n < SbxMINCURR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINCURR;
+ }
+ *p->pLong64 = ImpDoubleToCurrency( n ); break;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxdec.cxx b/basic/source/sbx/sbxdec.cxx
new file mode 100644
index 000000000000..2b53c5fc1cab
--- /dev/null
+++ b/basic/source/sbx/sbxdec.cxx
@@ -0,0 +1,799 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+#include <tools/errcode.hxx>
+
+#include <basic/sbx.hxx>
+#include "sbxconv.hxx"
+
+#include <com/sun/star/bridge/oleautomation/Decimal.hpp>
+
+
+// int GnDecCounter = 0;
+
+// Implementation SbxDecimal
+SbxDecimal::SbxDecimal( void )
+{
+ setInt( 0 );
+ mnRefCount = 0;
+ // GnDecCounter++;
+}
+
+SbxDecimal::SbxDecimal( const SbxDecimal& rDec )
+{
+#ifdef WIN32
+ maDec = rDec.maDec;
+#else
+ (void)rDec;
+#endif
+ mnRefCount = 0;
+ // GnDecCounter++;
+}
+
+SbxDecimal::SbxDecimal
+ ( const com::sun::star::bridge::oleautomation::Decimal& rAutomationDec )
+{
+#ifdef WIN32
+ maDec.scale = rAutomationDec.Scale;
+ maDec.sign = rAutomationDec.Sign;
+ maDec.Lo32 = rAutomationDec.LowValue;
+ maDec.Mid32 = rAutomationDec.MiddleValue;
+ maDec.Hi32 = rAutomationDec.HighValue;
+#else
+ (void)rAutomationDec;
+#endif
+ mnRefCount = 0;
+ // GnDecCounter++;
+}
+
+void SbxDecimal::fillAutomationDecimal
+ ( com::sun::star::bridge::oleautomation::Decimal& rAutomationDec )
+{
+#ifdef WIN32
+ rAutomationDec.Scale = maDec.scale;
+ rAutomationDec.Sign = maDec.sign;
+ rAutomationDec.LowValue = maDec.Lo32;
+ rAutomationDec.MiddleValue = maDec.Mid32;
+ rAutomationDec.HighValue = maDec.Hi32;
+#else
+ (void)rAutomationDec;
+#endif
+}
+
+SbxDecimal::~SbxDecimal()
+{
+ // GnDecCounter--;
+}
+
+void releaseDecimalPtr( SbxDecimal*& rpDecimal )
+{
+ if( rpDecimal )
+ {
+ rpDecimal->mnRefCount--;
+ if( rpDecimal->mnRefCount == 0 )
+ {
+ delete rpDecimal;
+ rpDecimal = NULL;
+ }
+ }
+}
+
+#ifdef WIN32
+
+bool SbxDecimal::operator -= ( const SbxDecimal &r )
+{
+ HRESULT hResult = VarDecSub( &maDec, (LPDECIMAL)&r.maDec, &maDec );
+ bool bRet = ( hResult == S_OK );
+ return bRet;
+}
+
+bool SbxDecimal::operator += ( const SbxDecimal &r )
+{
+ HRESULT hResult = VarDecAdd( &maDec, (LPDECIMAL)&r.maDec, &maDec );
+ bool bRet = ( hResult == S_OK );
+ return bRet;
+}
+
+bool SbxDecimal::operator /= ( const SbxDecimal &r )
+{
+ HRESULT hResult = VarDecDiv( &maDec, (LPDECIMAL)&r.maDec, &maDec );
+ bool bRet = ( hResult == S_OK );
+ return bRet;
+}
+
+bool SbxDecimal::operator *= ( const SbxDecimal &r )
+{
+ HRESULT hResult = VarDecMul( &maDec, (LPDECIMAL)&r.maDec, &maDec );
+ bool bRet = ( hResult == S_OK );
+ return bRet;
+}
+
+bool SbxDecimal::neg( void )
+{
+ HRESULT hResult = VarDecNeg( &maDec, &maDec );
+ bool bRet = ( hResult == S_OK );
+ return bRet;
+}
+
+bool SbxDecimal::isZero( void )
+{
+ SbxDecimal aZeroDec;
+ aZeroDec.setLong( 0 );
+ bool bZero = ( EQ == compare( *this, aZeroDec ) );
+ return bZero;
+}
+
+SbxDecimal::CmpResult compare( const SbxDecimal &rLeft, const SbxDecimal &rRight )
+{
+ HRESULT hResult = VarDecCmp( (LPDECIMAL)&rLeft.maDec, (LPDECIMAL)&rRight.maDec );
+ SbxDecimal::CmpResult eRes = (SbxDecimal::CmpResult)hResult;
+ return eRes;
+}
+
+void SbxDecimal::setChar( sal_Unicode val )
+{
+ VarDecFromUI2( (USHORT)val, &maDec );
+}
+
+void SbxDecimal::setByte( BYTE val )
+{
+ VarDecFromUI1( (BYTE)val, &maDec );
+}
+
+void SbxDecimal::setShort( INT16 val )
+{
+ VarDecFromI2( (short)val, &maDec );
+}
+
+void SbxDecimal::setLong( INT32 val )
+{
+ VarDecFromI4( (long)val, &maDec );
+}
+
+void SbxDecimal::setUShort( UINT16 val )
+{
+ VarDecFromUI2( (USHORT)val, &maDec );
+}
+
+void SbxDecimal::setULong( UINT32 val )
+{
+ VarDecFromUI4( (ULONG)val, &maDec );
+}
+
+bool SbxDecimal::setSingle( float val )
+{
+ bool bRet = ( VarDecFromR4( val, &maDec ) == S_OK );
+ return bRet;
+}
+
+bool SbxDecimal::setDouble( double val )
+{
+ bool bRet = ( VarDecFromR8( val, &maDec ) == S_OK );
+ return bRet;
+}
+
+void SbxDecimal::setInt( int val )
+{
+ setLong( (INT32)val );
+}
+
+void SbxDecimal::setUInt( unsigned int val )
+{
+ setULong( (UINT32)val );
+}
+
+// sbxscan.cxx
+void ImpGetIntntlSep( sal_Unicode& rcDecimalSep, sal_Unicode& rcThousandSep );
+
+bool SbxDecimal::setString( ::rtl::OUString* pOUString )
+{
+ static LCID nLANGID = MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US );
+
+ // Convert delimiter
+ sal_Unicode cDecimalSep;
+ sal_Unicode cThousandSep;
+ ImpGetIntntlSep( cDecimalSep, cThousandSep );
+
+ bool bRet = false;
+ HRESULT hResult;
+ if( cDecimalSep != '.' || cThousandSep != ',' )
+ {
+ int nLen = pOUString->getLength();
+ sal_Unicode* pBuffer = new sal_Unicode[nLen + 1];
+ pBuffer[nLen] = 0;
+
+ const sal_Unicode* pSrc = pOUString->getStr();
+ int i;
+ for( i = 0 ; i < nLen ; ++i )
+ pBuffer[i] = pSrc[i];
+
+ sal_Unicode c;
+ i = 0;
+ while( (c = pBuffer[i]) != 0 )
+ {
+ if( c == cDecimalSep )
+ pBuffer[i] = '.';
+ else if( c == cThousandSep )
+ pBuffer[i] = ',';
+ i++;
+ }
+ hResult = VarDecFromStr( (OLECHAR*)pBuffer, nLANGID, 0, &maDec );
+ delete pBuffer;
+ }
+ else
+ {
+ hResult = VarDecFromStr( (OLECHAR*)pOUString->getStr(), nLANGID, 0, &maDec );
+ }
+ bRet = ( hResult == S_OK );
+ return bRet;
+}
+
+
+bool SbxDecimal::getChar( sal_Unicode& rVal )
+{
+ bool bRet = ( VarUI2FromDec( &maDec, &rVal ) == S_OK );
+ return bRet;
+}
+
+bool SbxDecimal::getByte( BYTE& rVal )
+{
+ bool bRet = ( VarUI1FromDec( &maDec, &rVal ) == S_OK );
+ return bRet;
+}
+
+bool SbxDecimal::getShort( INT16& rVal )
+{
+ bool bRet = ( VarI2FromDec( &maDec, &rVal ) == S_OK );
+ return bRet;
+}
+
+bool SbxDecimal::getLong( INT32& rVal )
+{
+ bool bRet = ( VarI4FromDec( &maDec, &rVal ) == S_OK );
+ return bRet;
+}
+
+bool SbxDecimal::getUShort( UINT16& rVal )
+{
+ bool bRet = ( VarUI2FromDec( &maDec, &rVal ) == S_OK );
+ return bRet;
+}
+
+bool SbxDecimal::getULong( UINT32& rVal )
+{
+ bool bRet = ( VarUI4FromDec( &maDec, &rVal ) == S_OK );
+ return bRet;
+}
+
+bool SbxDecimal::getSingle( float& rVal )
+{
+ bool bRet = ( VarR4FromDec( &maDec, &rVal ) == S_OK );
+ return bRet;
+}
+
+bool SbxDecimal::getDouble( double& rVal )
+{
+ bool bRet = ( VarR8FromDec( &maDec, &rVal ) == S_OK );
+ return bRet;
+}
+
+bool SbxDecimal::getInt( int& rVal )
+{
+ INT32 TmpVal;
+ bool bRet = getLong( TmpVal );
+ rVal = TmpVal;
+ return bRet;
+}
+
+bool SbxDecimal::getUInt( unsigned int& rVal )
+{
+ UINT32 TmpVal;
+ bool bRet = getULong( TmpVal );
+ rVal = TmpVal;
+ return bRet;
+}
+
+#else
+// !WIN32
+
+bool SbxDecimal::operator -= ( const SbxDecimal &r )
+{
+ (void)r;
+ return false;
+}
+
+bool SbxDecimal::operator += ( const SbxDecimal &r )
+{
+ (void)r;
+ return false;
+}
+
+bool SbxDecimal::operator /= ( const SbxDecimal &r )
+{
+ (void)r;
+ return false;
+}
+
+bool SbxDecimal::operator *= ( const SbxDecimal &r )
+{
+ (void)r;
+ return false;
+}
+
+bool SbxDecimal::neg( void )
+{
+ return false;
+}
+
+bool SbxDecimal::isZero( void )
+{
+ return false;
+}
+
+SbxDecimal::CmpResult compare( const SbxDecimal &rLeft, const SbxDecimal &rRight )
+{
+ (void)rLeft;
+ (void)rRight;
+ return (SbxDecimal::CmpResult)0;
+}
+
+void SbxDecimal::setChar( sal_Unicode val ) { (void)val; }
+void SbxDecimal::setByte( BYTE val ) { (void)val; }
+void SbxDecimal::setShort( INT16 val ) { (void)val; }
+void SbxDecimal::setLong( INT32 val ) { (void)val; }
+void SbxDecimal::setUShort( UINT16 val ) { (void)val; }
+void SbxDecimal::setULong( UINT32 val ) { (void)val; }
+bool SbxDecimal::setSingle( float val ) { (void)val; return false; }
+bool SbxDecimal::setDouble( double val ) { (void)val; return false; }
+void SbxDecimal::setInt( int val ) { (void)val; }
+void SbxDecimal::setUInt( unsigned int val ) { (void)val; }
+bool SbxDecimal::setString( ::rtl::OUString* pOUString ) { (void)pOUString; return false; }
+
+bool SbxDecimal::getChar( sal_Unicode& rVal ) { (void)rVal; return false; }
+bool SbxDecimal::getByte( BYTE& rVal ) { (void)rVal; return false; }
+bool SbxDecimal::getShort( INT16& rVal ) { (void)rVal; return false; }
+bool SbxDecimal::getLong( INT32& rVal ) { (void)rVal; return false; }
+bool SbxDecimal::getUShort( UINT16& rVal ) { (void)rVal; return false; }
+bool SbxDecimal::getULong( UINT32& rVal ) { (void)rVal; return false; }
+bool SbxDecimal::getSingle( float& rVal ) { (void)rVal; return false; }
+bool SbxDecimal::getDouble( double& rVal ) { (void)rVal; return false; }
+bool SbxDecimal::getInt( int& rVal ) { (void)rVal; return false; }
+bool SbxDecimal::getUInt( unsigned int& rVal ) { (void)rVal; return false; }
+
+#endif
+
+bool SbxDecimal::getString( ::rtl::OUString& rString )
+{
+#ifdef WIN32
+ static LCID nLANGID = MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US );
+
+ bool bRet = false;
+
+ OLECHAR sz[100];
+ BSTR aBStr = SysAllocString( sz );
+ if( aBStr != NULL )
+ {
+ HRESULT hResult = VarBstrFromDec( &maDec, nLANGID, 0, &aBStr );
+ bRet = ( hResult == S_OK );
+ if( bRet )
+ {
+ // Convert delimiter
+ sal_Unicode cDecimalSep;
+ sal_Unicode cThousandSep;
+ ImpGetIntntlSep( cDecimalSep, cThousandSep );
+
+ if( cDecimalSep != '.' || cThousandSep != ',' )
+ {
+ sal_Unicode c;
+ int i = 0;
+ while( (c = aBStr[i]) != 0 )
+ {
+ if( c == '.' )
+ aBStr[i] = cDecimalSep;
+ else if( c == ',' )
+ aBStr[i] = cThousandSep;
+ i++;
+ }
+ }
+ rString = reinterpret_cast<const sal_Unicode*>(aBStr);
+ }
+
+ SysFreeString( aBStr );
+ }
+ return bRet;
+#else
+ (void)rString;
+ return false;
+#endif
+}
+
+SbxDecimal* ImpCreateDecimal( SbxValues* p )
+{
+#ifdef WIN32
+ if( !p )
+ return NULL;
+
+ SbxDecimal*& rpDecimal = p->pDecimal;
+ if( rpDecimal == NULL )
+ {
+ rpDecimal = new SbxDecimal();
+ rpDecimal->addRef();
+ }
+ return rpDecimal;
+#else
+ (void)p;
+ return NULL;
+#endif
+}
+
+SbxDecimal* ImpGetDecimal( const SbxValues* p )
+{
+#ifdef WIN32
+ SbxValues aTmp;
+ SbxDecimal* pnDecRes;
+
+ SbxDataType eType = p->eType;
+ if( eType == SbxDECIMAL && p->pDecimal )
+ {
+ pnDecRes = new SbxDecimal( *p->pDecimal );
+ pnDecRes->addRef();
+ return pnDecRes;
+ }
+ pnDecRes = new SbxDecimal();
+ pnDecRes->addRef();
+
+start:
+ switch( +eType )
+ {
+ case SbxNULL:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ case SbxEMPTY:
+ pnDecRes->setShort( 0 ); break;
+ case SbxCHAR:
+ pnDecRes->setChar( p->nChar ); break;
+ case SbxBYTE:
+ pnDecRes->setByte( p->nByte ); break;
+ case SbxINTEGER:
+ case SbxBOOL:
+ pnDecRes->setInt( p->nInteger ); break;
+ case SbxERROR:
+ case SbxUSHORT:
+ pnDecRes->setUShort( p->nUShort ); break;
+ case SbxLONG:
+ pnDecRes->setLong( p->nLong ); break;
+ case SbxULONG:
+ pnDecRes->setULong( p->nULong ); break;
+ case SbxSINGLE:
+ if( !pnDecRes->setSingle( p->nSingle ) )
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ break;
+ case SbxSALINT64:
+ {
+ double d = (double)p->nInt64;
+ pnDecRes->setDouble( d );
+ break;
+ }
+ case SbxSALUINT64:
+ {
+ double d = ImpSalUInt64ToDouble( p->uInt64 );
+ pnDecRes->setDouble( d );
+ break;
+ }
+ case SbxDATE:
+ case SbxDOUBLE:
+ case SbxLONG64:
+ case SbxULONG64:
+ case SbxCURRENCY:
+ {
+ double dVal;
+ if( p->eType == SbxCURRENCY )
+ dVal = ImpCurrencyToDouble( p->nLong64 );
+ else if( p->eType == SbxLONG64 )
+ dVal = ImpINT64ToDouble( p->nLong64 );
+ else if( p->eType == SbxULONG64 )
+ dVal = ImpUINT64ToDouble( p->nULong64 );
+ else
+ dVal = p->nDouble;
+
+ if( !pnDecRes->setDouble( dVal ) )
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ break;
+ }
+ case SbxLPSTR:
+ case SbxSTRING:
+ case SbxBYREF | SbxSTRING:
+ pnDecRes->setString( p->pOUString ); break;
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ pnDecRes->setDecimal( pVal->GetDecimal() );
+ else
+ {
+ SbxBase::SetError( SbxERR_NO_OBJECT );
+ pnDecRes->setShort( 0 );
+ }
+ break;
+ }
+
+ case SbxBYREF | SbxCHAR:
+ pnDecRes->setChar( *p->pChar ); break;
+ case SbxBYREF | SbxBYTE:
+ pnDecRes->setByte( *p->pByte ); break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ pnDecRes->setInt( *p->pInteger ); break;
+ case SbxBYREF | SbxLONG:
+ pnDecRes->setLong( *p->pLong ); break;
+ case SbxBYREF | SbxULONG:
+ pnDecRes->setULong( *p->pULong ); break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ pnDecRes->setUShort( *p->pUShort ); break;
+
+ // from here on had to be tested
+ case SbxBYREF | SbxSINGLE:
+ aTmp.nSingle = *p->pSingle; goto ref;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ aTmp.nDouble = *p->pDouble; goto ref;
+ case SbxBYREF | SbxULONG64:
+ aTmp.nULong64 = *p->pULong64; goto ref;
+ case SbxBYREF | SbxLONG64:
+ case SbxBYREF | SbxCURRENCY:
+ aTmp.nLong64 = *p->pLong64; goto ref;
+ case SbxBYREF | SbxSALINT64:
+ aTmp.nInt64 = *p->pnInt64; goto ref;
+ case SbxBYREF | SbxSALUINT64:
+ aTmp.uInt64 = *p->puInt64; goto ref;
+ ref:
+ aTmp.eType = SbxDataType( p->eType & 0x0FFF );
+ p = &aTmp; goto start;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION ); pnDecRes->setShort( 0 );
+ }
+ return pnDecRes;
+#else
+ (void)p;
+ return NULL;
+#endif
+}
+
+
+void ImpPutDecimal( SbxValues* p, SbxDecimal* pDec )
+{
+#ifdef WIN32
+ if( !pDec )
+ return;
+
+ SbxValues aTmp;
+start:
+ switch( +p->eType )
+ {
+ // here had to be tested
+ case SbxCHAR:
+ aTmp.pChar = &p->nChar; goto direct;
+ case SbxBYTE:
+ aTmp.pByte = &p->nByte; goto direct;
+ case SbxULONG:
+ aTmp.pULong = &p->nULong; goto direct;
+ case SbxERROR:
+ case SbxUSHORT:
+ aTmp.pUShort = &p->nUShort; goto direct;
+ case SbxSALUINT64:
+ aTmp.puInt64 = &p->uInt64; goto direct;
+ case SbxINTEGER:
+ case SbxBOOL:
+ aTmp.pInteger = &p->nInteger; goto direct;
+ case SbxLONG:
+ aTmp.pLong = &p->nLong; goto direct;
+ case SbxSALINT64:
+ aTmp.pnInt64 = &p->nInt64; goto direct;
+ case SbxCURRENCY:
+ aTmp.pLong64 = &p->nLong64; goto direct;
+ direct:
+ aTmp.eType = SbxDataType( p->eType | SbxBYREF );
+ p = &aTmp; goto start;
+
+ // from here on no longer
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ {
+ if( pDec != p->pDecimal )
+ {
+ releaseDecimalPtr( p->pDecimal );
+ // if( p->pDecimal )
+ // p->pDecimal->ReleaseRef();
+ p->pDecimal = pDec;
+ if( pDec )
+ pDec->addRef();
+ }
+ break;
+ }
+ case SbxSINGLE:
+ {
+ float f;
+ pDec->getSingle( f );
+ p->nSingle = f;
+ break;
+ }
+ case SbxDATE:
+ case SbxDOUBLE:
+ {
+ double d;
+ pDec->getDouble( d );
+ p->nDouble = d;
+ break;
+ }
+ case SbxULONG64:
+ {
+ double d;
+ pDec->getDouble( d );
+ p->nULong64 = ImpDoubleToUINT64( d );
+ break;
+ }
+ case SbxLONG64:
+ {
+ double d;
+ pDec->getDouble( d );
+ p->nLong64 = ImpDoubleToINT64( d );
+ break;
+ }
+
+ case SbxLPSTR:
+ case SbxSTRING:
+ case SbxBYREF | SbxSTRING:
+ if( !p->pOUString )
+ p->pOUString = new ::rtl::OUString;
+ // ImpCvtNum( (double) n, 0, *p->pString );
+ pDec->getString( *p->pOUString );
+ break;
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ pVal->PutDecimal( pDec );
+ else
+ SbxBase::SetError( SbxERR_NO_OBJECT );
+ break;
+ }
+
+ case SbxBYREF | SbxCHAR:
+ if( !pDec->getChar( *p->pChar ) )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ *p->pChar = 0;
+ }
+ break;
+ case SbxBYREF | SbxBYTE:
+ if( !pDec->getChar( *p->pChar ) )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ *p->pByte = 0;
+ }
+ break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ if( !pDec->getShort( *p->pInteger ) )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ *p->pInteger = 0;
+ }
+ break;
+ // *p->pInteger = n; break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ if( !pDec->getUShort( *p->pUShort ) )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ *p->pUShort = 0;
+ }
+ break;
+ case SbxBYREF | SbxLONG:
+ if( !pDec->getLong( *p->pLong ) )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ *p->pLong = 0;
+ }
+ break;
+ case SbxBYREF | SbxULONG:
+ if( !pDec->getULong( *p->pULong ) )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ *p->pULong = 0;
+ }
+ break;
+ case SbxBYREF | SbxSALINT64:
+ {
+ double d;
+ if( !pDec->getDouble( d ) )
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ else
+ *p->pnInt64 = ImpDoubleToSalInt64( d );
+ break;
+ }
+ case SbxBYREF | SbxSALUINT64:
+ {
+ double d;
+ if( !pDec->getDouble( d ) )
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ else
+ *p->puInt64 = ImpDoubleToSalUInt64( d );
+ break;
+ }
+ case SbxBYREF | SbxSINGLE:
+ if( !pDec->getSingle( *p->pSingle ) )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ *p->pSingle = 0;
+ }
+ break;
+ // *p->pSingle = (float) n; break;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ if( !pDec->getDouble( *p->pDouble ) )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ *p->pDouble = 0;
+ }
+ break;
+ case SbxBYREF | SbxULONG64:
+ {
+ double d;
+ pDec->getDouble( d );
+ *p->pULong64 = ImpDoubleToUINT64( d );
+ break;
+ }
+ case SbxBYREF | SbxLONG64:
+ {
+ double d;
+ pDec->getDouble( d );
+ *p->pLong64 = ImpDoubleToINT64( d );
+ break;
+ }
+ case SbxBYREF | SbxCURRENCY:
+ {
+ double d;
+ pDec->getDouble( d );
+ *p->pLong64 = ImpDoubleToCurrency( d );
+ break;
+ }
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ }
+#else
+ (void)p;
+ (void)pDec;
+#endif
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxdec.hxx b/basic/source/sbx/sbxdec.hxx
new file mode 100644
index 000000000000..85d550919013
--- /dev/null
+++ b/basic/source/sbx/sbxdec.hxx
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+#ifndef __SBX_SBX_DEC_HXX
+#define __SBX_SBX_DEC_HXX
+
+#ifdef WIN32
+
+#undef WB_LEFT
+#undef WB_RIGHT
+#include <tools/prewin.h>
+} // close extern "C" {
+
+#ifndef __MINGW32__
+#include <comutil.h>
+#endif
+#include <oleauto.h>
+
+extern "C" { // reopen extern "C" {
+#include <tools/postwin.h>
+
+#endif
+#endif
+#include <basic/sbx.hxx>
+
+#include <com/sun/star/bridge/oleautomation/Decimal.hpp>
+
+
+// Decimal support
+// Implementation only for windows
+
+class SbxDecimal
+{
+ friend void releaseDecimalPtr( SbxDecimal*& rpDecimal );
+
+#ifdef WIN32
+ DECIMAL maDec;
+#endif
+ INT32 mnRefCount;
+
+public:
+ SbxDecimal( void );
+ SbxDecimal( const SbxDecimal& rDec );
+ SbxDecimal( const com::sun::star::bridge::oleautomation::Decimal& rAutomationDec );
+
+ ~SbxDecimal();
+
+ void addRef( void )
+ { mnRefCount++; }
+
+ void fillAutomationDecimal( com::sun::star::bridge::oleautomation::Decimal& rAutomationDec );
+
+ void setChar( sal_Unicode val );
+ void setByte( BYTE val );
+ void setShort( INT16 val );
+ void setLong( INT32 val );
+ void setUShort( UINT16 val );
+ void setULong( UINT32 val );
+ bool setSingle( float val );
+ bool setDouble( double val );
+ void setInt( int val );
+ void setUInt( unsigned int val );
+ bool setString( ::rtl::OUString* pOUString );
+ void setDecimal( SbxDecimal* pDecimal )
+ {
+#ifdef WIN32
+ if( pDecimal )
+ maDec = pDecimal->maDec;
+#else
+ (void)pDecimal;
+#endif
+ }
+
+ bool getChar( sal_Unicode& rVal );
+ bool getByte( BYTE& rVal );
+ bool getShort( INT16& rVal );
+ bool getLong( INT32& rVal );
+ bool getUShort( UINT16& rVal );
+ bool getULong( UINT32& rVal );
+ bool getSingle( float& rVal );
+ bool getDouble( double& rVal );
+ bool getInt( int& rVal );
+ bool getUInt( unsigned int& rVal );
+ bool getString( ::rtl::OUString& rString );
+
+ bool operator -= ( const SbxDecimal &r );
+ bool operator += ( const SbxDecimal &r );
+ bool operator /= ( const SbxDecimal &r );
+ bool operator *= ( const SbxDecimal &r );
+ bool neg( void );
+
+ bool isZero( void );
+
+ enum CmpResult { LT, EQ, GT };
+ friend CmpResult compare( const SbxDecimal &rLeft, const SbxDecimal &rRight );
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxexec.cxx b/basic/source/sbx/sbxexec.cxx
new file mode 100644
index 000000000000..0235bc5ce285
--- /dev/null
+++ b/basic/source/sbx/sbxexec.cxx
@@ -0,0 +1,401 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+#include <tools/errcode.hxx>
+#include <vcl/svapp.hxx>
+#include <basic/sbx.hxx>
+
+
+class SbxSimpleCharClass
+{
+public:
+ BOOL isAlpha( sal_Unicode c ) const
+ {
+ BOOL bRet = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+ return bRet;
+ }
+
+ BOOL isDigit( sal_Unicode c ) const
+ {
+ BOOL bRet = (c >= '0' && c <= '9');
+ return bRet;
+ }
+
+ BOOL isAlphaNumeric( sal_Unicode c ) const
+ {
+ BOOL bRet = isDigit( c ) || isAlpha( c );
+ return bRet;
+ }
+};
+
+
+static SbxVariable* Element
+ ( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf,
+ SbxClassType, const SbxSimpleCharClass& rCharClass );
+
+static const xub_Unicode* SkipWhitespace( const xub_Unicode* p )
+{
+ while( *p && ( *p == ' ' || *p == '\t' ) )
+ p++;
+ return p;
+}
+
+// Scanning of a symbol. The symbol were inserted in rSym, the return value
+// is the new scan position. The symbol is at errors empty.
+
+static const xub_Unicode* Symbol( const xub_Unicode* p, XubString& rSym, const SbxSimpleCharClass& rCharClass )
+{
+ USHORT nLen = 0;
+ // Did we have a nonstandard symbol?
+ if( *p == '[' )
+ {
+ rSym = ++p;
+ while( *p && *p != ']' )
+ p++, nLen++;
+ p++;
+ }
+ else
+ {
+ // A symbol had to begin with a alphabetic character or an underline
+ if( !rCharClass.isAlpha( *p ) && *p != '_' )
+ SbxBase::SetError( SbxERR_SYNTAX );
+ else
+ {
+ rSym = p;
+ // The it can contain alphabetic characters, numbers or underlines
+ while( *p && (rCharClass.isAlphaNumeric( *p ) || *p == '_') )
+ p++, nLen++;
+ // BASIC-Standard-Suffixes were ignored
+ if( *p && (*p == '%' || *p == '&' || *p == '!' || *p == '#' || *p == '$' ) )
+ p++;
+ }
+ }
+ rSym.Erase( nLen );
+ return p;
+}
+
+// Qualified name. Element.Element....
+
+static SbxVariable* QualifiedName
+ ( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf, SbxClassType t )
+{
+ static SbxSimpleCharClass aCharClass;
+
+ SbxVariableRef refVar;
+ const xub_Unicode* p = SkipWhitespace( *ppBuf );
+ if( aCharClass.isAlpha( *p ) || *p == '_' || *p == '[' )
+ {
+ // Read in the element
+ refVar = Element( pObj, pGbl, &p, t, aCharClass );
+ while( refVar.Is() && (*p == '.' || *p == '!') )
+ {
+ // It follows still an objectelement. The current element
+ // had to be a SBX-Object or had to deliver such an object!
+ pObj = PTR_CAST(SbxObject,(SbxVariable*) refVar);
+ if( !pObj )
+ // Then it had to deliver an object
+ pObj = PTR_CAST(SbxObject,refVar->GetObject());
+ refVar.Clear();
+ if( !pObj )
+ break;
+ p++;
+ // And the next element please
+ refVar = Element( pObj, pGbl, &p, t, aCharClass );
+ }
+ }
+ else
+ SbxBase::SetError( SbxERR_SYNTAX );
+ *ppBuf = p;
+ if( refVar.Is() )
+ refVar->AddRef();
+ return refVar;
+}
+
+// Read in of an operand. This could be a number, a string or
+// a function (with optional parameters).
+
+static SbxVariable* Operand
+ ( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf, BOOL bVar )
+{
+ static SbxSimpleCharClass aCharClass;
+
+ SbxVariableRef refVar( new SbxVariable );
+ const xub_Unicode* p = SkipWhitespace( *ppBuf );
+ if( !bVar && ( aCharClass.isDigit( *p )
+ || ( *p == '.' && aCharClass.isDigit( *( p+1 ) ) )
+ || *p == '-'
+ || *p == '&' ) )
+ {
+ // A number could be scanned in directly!
+ USHORT nLen;
+ if( !refVar->Scan( XubString( p ), &nLen ) )
+ refVar.Clear();
+ else
+ p += nLen;
+ }
+ else if( !bVar && *p == '"' )
+ {
+ // A string
+ XubString aString;
+ p++;
+ for( ;; )
+ {
+ // This is perhaps an error
+ if( !*p )
+ return NULL;
+ // Double quotes are OK
+ if( *p == '"' )
+ if( *++p != '"' )
+ break;
+ aString += *p++;
+ }
+ refVar->PutString( aString );
+ }
+ else
+ refVar = QualifiedName( pObj, pGbl, &p, SbxCLASS_DONTCARE );
+ *ppBuf = p;
+ if( refVar.Is() )
+ refVar->AddRef();
+ return refVar;
+}
+
+// Read in of a simple term. The operands +, -, * and /
+// are supported.
+
+static SbxVariable* MulDiv( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf )
+{
+ const xub_Unicode* p = *ppBuf;
+ SbxVariableRef refVar( Operand( pObj, pGbl, &p, FALSE ) );
+ p = SkipWhitespace( p );
+ while( refVar.Is() && ( *p == '*' || *p == '/' ) )
+ {
+ xub_Unicode cOp = *p++;
+ SbxVariableRef refVar2( Operand( pObj, pGbl, &p, FALSE ) );
+ if( refVar2.Is() )
+ {
+ // temporary variable!
+ SbxVariable* pVar = refVar;
+ pVar = new SbxVariable( *pVar );
+ refVar = pVar;
+ if( cOp == '*' )
+ *refVar *= *refVar2;
+ else
+ *refVar /= *refVar2;
+ }
+ else
+ {
+ refVar.Clear();
+ break;
+ }
+ }
+ *ppBuf = p;
+ if( refVar.Is() )
+ refVar->AddRef();
+ return refVar;
+}
+
+static SbxVariable* PlusMinus( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf )
+{
+ const xub_Unicode* p = *ppBuf;
+ SbxVariableRef refVar( MulDiv( pObj, pGbl, &p ) );
+ p = SkipWhitespace( p );
+ while( refVar.Is() && ( *p == '+' || *p == '-' ) )
+ {
+ xub_Unicode cOp = *p++;
+ SbxVariableRef refVar2( MulDiv( pObj, pGbl, &p ) );
+ if( refVar2.Is() )
+ {
+ // temporaere Variable!
+ SbxVariable* pVar = refVar;
+ pVar = new SbxVariable( *pVar );
+ refVar = pVar;
+ if( cOp == '+' )
+ *refVar += *refVar2;
+ else
+ *refVar -= *refVar2;
+ }
+ else
+ {
+ refVar.Clear();
+ break;
+ }
+ }
+ *ppBuf = p;
+ if( refVar.Is() )
+ refVar->AddRef();
+ return refVar;
+}
+
+static SbxVariable* Assign( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf )
+{
+ const xub_Unicode* p = *ppBuf;
+ SbxVariableRef refVar( Operand( pObj, pGbl, &p, TRUE ) );
+ p = SkipWhitespace( p );
+ if( refVar.Is() )
+ {
+ if( *p == '=' )
+ {
+ // Assign only onto properties!
+ if( refVar->GetClass() != SbxCLASS_PROPERTY )
+ {
+ SbxBase::SetError( SbxERR_BAD_ACTION );
+ refVar.Clear();
+ }
+ else
+ {
+ p++;
+ SbxVariableRef refVar2( PlusMinus( pObj, pGbl, &p ) );
+ if( refVar2.Is() )
+ {
+ SbxVariable* pVar = refVar;
+ SbxVariable* pVar2 = refVar2;
+ *pVar = *pVar2;
+ pVar->SetParameters( NULL );
+ }
+ }
+ }
+ else
+ // Simple call: once activating
+ refVar->Broadcast( SBX_HINT_DATAWANTED );
+ }
+ *ppBuf = p;
+ if( refVar.Is() )
+ refVar->AddRef();
+ return refVar;
+}
+
+// Read in of an element. This is a symbol, optional followed
+// by a parameter list. The symbol will be searched in the
+// specified object and the parameter list will be attached if necessary.
+
+static SbxVariable* Element
+ ( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf,
+ SbxClassType t, const SbxSimpleCharClass& rCharClass )
+{
+ XubString aSym;
+ const xub_Unicode* p = Symbol( *ppBuf, aSym, rCharClass );
+ SbxVariableRef refVar;
+ if( aSym.Len() )
+ {
+ USHORT nOld = pObj->GetFlags();
+ if( pObj == pGbl )
+ pObj->SetFlag( SBX_GBLSEARCH );
+ refVar = pObj->Find( aSym, t );
+ pObj->SetFlags( nOld );
+ if( refVar.Is() )
+ {
+ refVar->SetParameters( NULL );
+ // Follow still parameter?
+ p = SkipWhitespace( p );
+ if( *p == '(' )
+ {
+ p++;
+ SbxArrayRef refPar = new SbxArray;
+ USHORT nArg = 0;
+ // We are once relaxed and accept as well
+ // the line- or commandend as delimiter
+ // Search parameter always global!
+ while( *p && *p != ')' && *p != ']' )
+ {
+ SbxVariableRef refArg = PlusMinus( pGbl, pGbl, &p );
+ if( !refArg )
+ {
+ // Error during the parsing
+ refVar.Clear(); break;
+ }
+ else
+ {
+ // One copies the parameter, so that
+ // one have the current status (triggers also
+ // the call per access)
+ SbxVariable* pArg = refArg;
+ refPar->Put( new SbxVariable( *pArg ), ++nArg );
+ }
+ p = SkipWhitespace( p );
+ if( *p == ',' )
+ p++;
+ }
+ if( *p == ')' )
+ p++;
+ if( refVar.Is() )
+ refVar->SetParameters( refPar );
+ }
+ }
+ else
+ SbxBase::SetError( SbxERR_NO_METHOD );
+ }
+ *ppBuf = p;
+ if( refVar.Is() )
+ refVar->AddRef();
+ return refVar;
+}
+
+// Mainroutine
+
+SbxVariable* SbxObject::Execute( const XubString& rTxt )
+{
+ SbxVariable* pVar = NULL;
+ const xub_Unicode* p = rTxt.GetBuffer();
+ for( ;; )
+ {
+ p = SkipWhitespace( p );
+ if( !*p )
+ break;
+ if( *p++ != '[' )
+ {
+ SetError( SbxERR_SYNTAX ); break;
+ }
+ pVar = Assign( this, this, &p );
+ if( !pVar )
+ break;
+ p = SkipWhitespace( p );
+ if( *p++ != ']' )
+ {
+ SetError( SbxERR_SYNTAX ); break;
+ }
+ }
+ return pVar;
+}
+
+SbxVariable* SbxObject::FindQualified( const XubString& rName, SbxClassType t )
+{
+ SbxVariable* pVar = NULL;
+ const xub_Unicode* p = rName.GetBuffer();
+ p = SkipWhitespace( p );
+ if( !*p )
+ return NULL;;
+ pVar = QualifiedName( this, this, &p, t );
+ p = SkipWhitespace( p );
+ if( *p )
+ SetError( SbxERR_SYNTAX );
+ return pVar;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxform.cxx b/basic/source/sbx/sbxform.cxx
new file mode 100644
index 000000000000..533de965dbbb
--- /dev/null
+++ b/basic/source/sbx/sbxform.cxx
@@ -0,0 +1,1170 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+
+#include <stdlib.h>
+
+#include <basic/sbxform.hxx>
+
+/*
+TODO: gibt es noch irgend welche Star-Basic Besonderheiten ?
+
+ was bedeutet: * als Platzhalter
+
+BEMERKUNG: Visual-Basic behandelt folgende (ung"ultige) Format-Strings
+ wie angezeigt:
+
+ ##0##.##0## --> ##000.000##
+
+ (diese Klasse verh"alt sich genau so).
+*/
+
+#include <stdio.h> // f"ur: sprintf()
+#include <float.h> // f"ur: DBL_DIG, DBL_EPSILON
+#include <math.h> // f"ur: floor(), fabs(), log10(), pow()
+
+//=================================================================
+//=========================== DEFINES =============================
+//=================================================================
+
+#define _NO_DIGIT -1
+
+#define MAX_NO_OF_EXP_DIGITS 5
+ // +4 wegen dem Wertebereich: zwischen -308 und +308
+ // +1 f"ur abschliessende 0
+#define MAX_NO_OF_DIGITS DBL_DIG
+#define MAX_DOUBLE_BUFFER_LENGTH MAX_NO_OF_DIGITS + 9
+ // +1 f"ur Vorzeichen
+ // +1 f"ur Ziffer vor dem Dezimal-Punkt
+ // +1 f"ur Dezimal-Punkt
+ // +2 f"ur Exponent E und Exp. Vorzeichen
+ // +3 f"ur den Wert des Exponenten
+ // +1 f"ur abschliessende 0
+
+// Defines f"ur die Ziffern:
+#define ASCII_0 '0' // 48
+#define ASCII_9 '9' // 57
+
+#define CREATE_1000SEP_CHAR '@'
+
+#define FORMAT_SEPARATOR ';'
+
+// vordefinierte Formate f"ur den Format$()-Befehl:
+#define BASICFORMAT_GENERALNUMBER "General Number"
+#define BASICFORMAT_CURRENCY "Currency"
+#define BASICFORMAT_FIXED "Fixed"
+#define BASICFORMAT_STANDARD "Standard"
+#define BASICFORMAT_PERCENT "Percent"
+#define BASICFORMAT_SCIENTIFIC "Scientific"
+#define BASICFORMAT_YESNO "Yes/No"
+#define BASICFORMAT_TRUEFALSE "True/False"
+#define BASICFORMAT_ONOFF "On/Off"
+
+#define EMPTYFORMATSTRING ""
+
+// Bem.: Visual-Basic hat bei Floating-Point-Zahlen maximal 12 Stellen
+// nach dem Dezimal-Punkt.
+// Alle Format-Strings sind kompatibel zu Visual-Basic:
+#define GENERALNUMBER_FORMAT "0.############"
+ // max. 12 Stellen in Visual-Basic !
+#define CURRENCY_FORMAT "@$0.00;@($0.00)"
+#define FIXED_FORMAT "0.00"
+#define STANDARD_FORMAT "@0.00"
+#define PERCENT_FORMAT "0.00%"
+#define SCIENTIFIC_FORMAT "#.00E+00"
+// BEMERKUNG: das Zeichen @ bedeutet, das Tausender-Separatoren erzeugt
+// weden sollen. Dies ist eine StarBasic 'Erweiterung'.
+
+//=================================================================
+
+// zur Bestimmung der Anzahl Stellen in dNumber
+double get_number_of_digits( double dNumber )
+//double floor_log10_fabs( double dNumber )
+{
+ if( dNumber==0.0 )
+ // 0 hat zumindest auch eine Stelle !
+ return 0.0; //ehemals 1.0, jetzt 0.0 wegen #40025;
+ else
+ return floor( log10( fabs( dNumber ) ) );
+}
+
+//=================================================================
+//======================= IMPLEMENTATION ==========================
+//=================================================================
+
+SbxBasicFormater::SbxBasicFormater( sal_Unicode _cDecPoint, sal_Unicode _cThousandSep,
+ String _sOnStrg,
+ String _sOffStrg,
+ String _sYesStrg,
+ String _sNoStrg,
+ String _sTrueStrg,
+ String _sFalseStrg,
+ String _sCurrencyStrg,
+ String _sCurrencyFormatStrg )
+{
+ cDecPoint = _cDecPoint;
+ cThousandSep = _cThousandSep;
+ sOnStrg = _sOnStrg;
+ sOffStrg = _sOffStrg;
+ sYesStrg = _sYesStrg;
+ sNoStrg = _sNoStrg;
+ sTrueStrg = _sTrueStrg;
+ sFalseStrg = _sFalseStrg;
+ sCurrencyStrg = _sCurrencyStrg;
+ sCurrencyFormatStrg = _sCurrencyFormatStrg;
+}
+
+// Funktion zur Ausgabe eines Fehler-Textes (zum Debuggen)
+/*
+void SbxBasicFormater::ShowError( char * sErrMsg )
+{
+// cout << "ERROR in Format$(): " << sErrMsg << endl;
+}
+*/
+// verschiebt alle Zeichen des Strings, angefangen von der nStartPos,
+// um eine Position zu gr"osseren Indizes, d.h. es wird Platz f"ur
+// ein neues (einzuf"ugendes) Zeichen geschafft.
+// ACHTUNG: der String MUSS gross genug sein !
+inline void SbxBasicFormater::ShiftString( String& sStrg, USHORT nStartPos )
+{
+ sStrg.Erase( nStartPos,1 );
+}
+
+// Funktion um ein Zeichen an einen String anzuh"angen
+inline void SbxBasicFormater::StrAppendChar( String& sStrg, sal_Unicode ch )
+{
+ sStrg.Insert( ch );
+}
+
+// h"angt die "ubergebene Ziffer nDigit an den "ubergebenen String sStrg
+// an, dabei wird "uberpr"uft ob nDigit eine g"ultige Ziffer ist,
+// falls dies nicht der Fall ist, wird nichts gemacht.
+void SbxBasicFormater::AppendDigit( String& sStrg, short nDigit )
+{
+ if( nDigit>=0 && nDigit<=9 )
+ StrAppendChar( sStrg, (sal_Unicode)(nDigit+ASCII_0) );
+}
+
+// verschiebt den Dezimal-Punkt um eine Stelle nach links
+void SbxBasicFormater::LeftShiftDecimalPoint( String& sStrg )
+{
+ USHORT nPos = sStrg.Search( cDecPoint );
+
+ if( nPos!=STRING_NOTFOUND )
+ {
+ // vertausche Dezimal-Punkt
+ sStrg.SetChar( nPos, sStrg.GetChar( nPos - 1 ) );
+ sStrg.SetChar( nPos-1, cDecPoint );
+ }
+}
+
+// rundet in einem String die Ziffer an der angegebenen Stelle,
+// es wird ein Flag zur"uckgeliefert, falls ein Overflow auftrat,
+// d.h. 99.99 --> 100.00, d.h. ein Gr"ossenordung ge"andert wurde
+// (geschieht beim Runden einer 9).
+void SbxBasicFormater::StrRoundDigit( String& sStrg, short nPos, BOOL& bOverflow )
+{
+ // wurde ggf ein falscher Index uebergeben --> Aufruf ignorieren
+ if( nPos<0 )
+ return;
+
+ bOverflow = FALSE;
+ // "uberspringe den Dezimalpunkt und Tausender-Trennzeichen
+ sal_Unicode c = sStrg.GetChar( nPos );
+ if( nPos>0 && (c == cDecPoint || c == cThousandSep) )
+ {
+ StrRoundDigit( sStrg,nPos-1,bOverflow );
+ // AENDERUNG ab 9.3.1997: nach rekursivem Call die Methode SOFORT beenden !
+ return;
+ }
+ // "uberspringe alle nicht-Ziffern:
+ // BEMERKUNG:
+ // in einem g"ultigen Format-String sollte die Ausgabe
+ // der Zahl an einem St"uck geschen, d.h. Sonderzeichen sollten
+ // NUR vor ODER nach der Zahl stehen und nicht mitten in der
+ // Format-Angabe f"ur die Zahl
+ while( nPos>=0 && (sStrg.GetChar( nPos )<ASCII_0 || sStrg.GetChar( nPos )>ASCII_9) )
+ nPos--;
+ // muss ggf. noch Platz f"ur eine weitere (f"uhrende) Ziffer
+ // geschaffen werden ?
+ if( nPos==-1 )
+ {
+ ShiftString( sStrg,0 );
+ // f"uhrende 1 einf"ugen: z.B. 99.99 f"ur 0.0
+ sStrg.SetChar( 0, '1' );
+ bOverflow = TRUE;
+ }
+ else
+ {
+ // ist die zu rundende Position eine Ziffer ?
+ sal_Unicode c2 = sStrg.GetChar( nPos );
+ if( c2 >= ASCII_0 && c2 <= ASCII_9 )
+ {
+ // muss eine 9 gerundet werden? Falls: Ja --> rekursiver Aufruf
+ if( c2 == ASCII_9 )
+ {
+ sStrg.SetChar( nPos, '0' );
+ StrRoundDigit( sStrg,nPos-1,bOverflow );
+ }
+ else
+ sStrg.SetChar( nPos, c2+1 );
+ }
+ else
+ {
+ // --> Nein, d.h. Platz f"ur Ziffer schaffen: z.B. -99.99 f"ur #0.0
+ // da gerundet wird MUSS es immer eine g"ultige Position
+ // nPos+1 geben !
+ ShiftString( sStrg,nPos+1 );
+ // f"uhrende 1 einf"ugen
+ sStrg.SetChar( nPos+1, '1' );
+ bOverflow = TRUE;
+ }
+ }
+}
+
+// rundet in einem String die Ziffer an der angegebenen Stelle
+void SbxBasicFormater::StrRoundDigit( String& sStrg, short nPos )
+{
+ BOOL bOverflow;
+
+ StrRoundDigit( sStrg,nPos,bOverflow );
+}
+
+// parse den Formatstring von der "ubergebenen Position zur"uck
+// und l"osche ggf. "uberf"ussige 0en, z.B. 4.50 in 0.0#
+void SbxBasicFormater::ParseBack( String& sStrg, const String& sFormatStrg,
+ short nFormatPos )
+{
+ // WICHTIG: nFormatPos kann auch negativ sein, in diesem Fall Aufruf ignorieren
+ for( short i=nFormatPos;
+ i>0 && sFormatStrg.GetChar( i ) == '#' && sStrg.GetChar( (sStrg.Len()-1) ) == '0';
+ i-- )
+ { sStrg.Erase( sStrg.Len()-1 ); }
+}
+
+#ifdef _with_sprintf
+
+/*
+ Bemerkung:
+ Zahl wird mit maximaler (sinnvollen) Genauigkeit in einen String
+ umgewandelt (mit sprintf()), dieser String wird dann im Schleifen-
+ Durchlauf nach der entsprechenden Ziffer durchsucht.
+*/
+// initialisiert die Daten der Klasse um einen Scan-Durchlauf durchzuf"uhren
+void SbxBasicFormater::InitScan( double _dNum )
+{
+ char sBuffer[ MAX_DOUBLE_BUFFER_LENGTH ];
+
+ dNum = _dNum;
+ InitExp( get_number_of_digits( dNum ) );
+ // maximal 15 Nachkomma-Stellen, Format-Beispiel: -1.234000000000000E-001
+ /*int nCount =*/ sprintf( sBuffer,"%+22.15lE",dNum );
+ sSciNumStrg.AssignAscii( sBuffer );
+}
+
+void SbxBasicFormater::InitExp( double _dNewExp )
+{
+ char sBuffer[ MAX_DOUBLE_BUFFER_LENGTH ];
+ // bestimme den Exponenten (kann immer GENAU durch int dargestellt werden)
+ nNumExp = (short)_dNewExp;
+ // und dessen String
+ /*int nCount =*/ sprintf( sBuffer,"%+i",nNumExp );
+ sNumExpStrg.AssignAscii( sBuffer );
+ // bestimme die Anzahl der Stellen im Exponenten
+ nExpExp = (short)get_number_of_digits( (double)nNumExp );
+}
+
+// bestimmt die Ziffer an der angegebenen Stelle (gedacht zur Anwendung im
+// Scan-Durchlauf)
+short SbxBasicFormater::GetDigitAtPosScan( short nPos, BOOL& bFoundFirstDigit )
+{
+ // Versuch eine gr"ossere Ziffer zu lesen,
+ // z.B. Stelle 4 in 1.234,
+ // oder eine Ziffer ausserhalb der Aufl"osung der
+ // Zahl (double) zu lesen (z.B. max. 15 Stellen).
+ if( nPos>nNumExp || abs(nNumExp-nPos)>MAX_NO_OF_DIGITS )
+ return _NO_DIGIT;
+ // bestimme den Index der Stelle in dem Number-String:
+ // "uberlese das Vorzeichen
+ USHORT no = 1;
+ // falls notwendig den Dezimal-Punkt "uberlesen:
+ if( nPos<nNumExp )
+ no++;
+ no += nNumExp-nPos;
+ // Abfrage der ersten (g"ultigen) Ziffer der Zahl --> Flag setzen
+ if( nPos==nNumExp )
+ bFoundFirstDigit = TRUE;
+ return (short)(sSciNumStrg.GetChar( no ) - ASCII_0);
+}
+
+short SbxBasicFormater::GetDigitAtPosExpScan( short nPos, BOOL& bFoundFirstDigit )
+{
+ // ist die abgefragte Stelle zu gross f"ur den Exponenten ?
+ if( nPos>nExpExp )
+ return -1;
+
+ // bestimme den Index der Stelle in dem Number-String:
+ // "uberlese das Vorzeichen
+ USHORT no = 1;
+ no += nExpExp-nPos;
+ // Abfrage der ersten (g"ultigen) Ziffer der Zahl --> Flag setzen
+ if( nPos==nExpExp )
+ bFoundFirstDigit = TRUE;
+ return (short)(sNumExpStrg.GetChar( no ) - ASCII_0);
+}
+
+// es kann ein Wert f"ur den Exponent angegeben werden, da ggf. die
+// Zahl ggf. NICHT normiert (z.B. 1.2345e-03) dargestellt werden soll,
+// sondern eventuell 123.345e-3 !
+short SbxBasicFormater::GetDigitAtPosExpScan( double dNewExponent, short nPos,
+ BOOL& bFoundFirstDigit )
+{
+ // neuer Exponent wurde "ubergeben, aktualisiere
+ // die tempor"aren Klassen-Variablen
+ InitExp( dNewExponent );
+ // und jetzt die Stelle bestimmen
+ return GetDigitAtPosExpScan( nPos,bFoundFirstDigit );
+}
+
+#else
+
+/* Probleme mit der folgenden Methode:
+
+TODO: ggf einen 'intelligenten' Peek-Parser um Rundungsfehler bei
+ double-Zahlen herauszufinden ? z.B. f"ur 0.00115 #.#e-000
+
+ Problem mit: format( 0.3345 , "0.000" )
+ Problem mit: format( 0.00115 , "0.0000" )
+
+*/
+// liefert die Ziffer an der angegebenen '10er System'-Position,
+// d.h. positive nPos f"ur Stellen vor dem Komma und negative
+// f"ur Stellen nach dem Komma.
+// nPos==0 bedeutet erste Stelle vor dem Komma, also 10^0.
+// liefert 0..9 f"ur g"ultige Ziffern und -1 f"ur nicht vorhanden,
+// d.h. falls die "ubergebene Zahl zu klein ist
+// (z.B. Stelle 5 bei dNumber=123).
+// Weiter wird in dNextNumber die um die f"uhrenden Stellen
+// (bis nPos) gek"urzte Zahl zur"uckgeliefert, z.B.
+// GetDigitAtPos( 3434.565 , 2 , dNewNumber ) --> dNewNumber = 434.565
+// dies kann f"ur Schleifenabarbeitung g"unstiger sein, d.h.
+// die Zahlen immer von der gr"ossten Stelle abarbeiten/scanen.
+// In bFoundFirstDigit wird ggf. ein Flag gesetzt wenn eine Ziffer
+// gefunden wurde, dies wird dazu verwendet um 'Fehler' beim Parsen 202
+// zu vermeiden, die
+//
+// ACHTUNG: anscheinend gibt es manchmal noch Probleme mit Rundungs-Fehlern!
+short SbxBasicFormater::GetDigitAtPos( double dNumber, short nPos,
+ double& dNextNumber, BOOL& bFoundFirstDigit )
+// ACHTUNG: nPos kann auch negativ werden, f"ur Stellen nach dem Dezimal-Punkt
+{
+ double dTemp = dNumber;
+ double dDigit,dPos;
+ short nMaxDigit;
+
+ // erst mal aus der Zahl eine positive Zahl machen:
+ dNumber = fabs( dNumber );
+ dPos = (double)nPos;
+
+ // "uberpr"ufe ob Zahl zu klein f"ur angegebene Stelle ist
+ nMaxDigit = (short)get_number_of_digits( dNumber );
+ // f"uhrende Ziffern 'l"oschen'
+ // Bem.: Fehler nur bei Zahlen gr"osser 0, d.h. bei Ziffern vor dem
+ // Dezimal-Punkt
+ if( nMaxDigit<nPos && !bFoundFirstDigit && nPos>=0 )
+ return _NO_DIGIT;
+ // Ziffer gefunden, setze Flag:
+ bFoundFirstDigit = TRUE;
+ for( short i=nMaxDigit; i>=nPos; i-- )
+ {
+ double dI = (double)i;
+ double dTemp1 = pow( 10.0,dI );
+ // pr"apariere nun die gesuchte Ziffer:
+ dDigit = floor( pow( 10.0,log10( fabs( dNumber ) )-dI ) );
+ dNumber -= dTemp1 * dDigit;
+ }
+ // Zuweisung f"ur optimierte Schleifen-Durchl"aufe
+ dNextNumber = dNumber;
+ // und zum Schluss noch die float-Rundungsungenauigkeiten heraus filtern
+ return RoundDigit( dDigit );
+}
+
+// rundet eine double-Zahl zwischen 0 und 9 auf die genaue
+// Integer-Zahl, z.B. 2.8 -> 3 und 2.2 -> 2
+short SbxBasicFormater::RoundDigit( double dNumber )
+{
+ // ist der Wertebereich g"ultig ?
+ if( dNumber<0.0 || dNumber>10.0 )
+ return -1;
+ short nTempHigh = (short)(dNumber+0.5); // ggf. floor( )
+ return nTempHigh;
+}
+
+#endif
+
+// kopiert den entsprechenden Teil des Format-Strings, falls vorhanden,
+// und liefert diesen zur"uck.
+// Somit wird ein neuer String erzeugt, der vom Aufrufer wieder freigegeben
+// werden muss
+String SbxBasicFormater::GetPosFormatString( const String& sFormatStrg, BOOL & bFound )
+{
+ bFound = FALSE; // default...
+ USHORT nPos = sFormatStrg.Search( FORMAT_SEPARATOR );
+
+ if( nPos!=STRING_NOTFOUND )
+ {
+ bFound = TRUE;
+ // der Format-String f"ur die positiven Zahlen ist alles
+ // vor dem ersten ';'
+ return sFormatStrg.Copy( 0,nPos );
+ }
+ // kein ; gefunden, liefere Leerstring
+ String aRetStr;
+ aRetStr.AssignAscii( EMPTYFORMATSTRING );
+ return aRetStr;
+}
+
+// siehe auch GetPosFormatString()
+String SbxBasicFormater::GetNegFormatString( const String& sFormatStrg, BOOL & bFound )
+{
+ bFound = FALSE; // default...
+ USHORT nPos = sFormatStrg.Search( FORMAT_SEPARATOR );
+
+ if( nPos!=STRING_NOTFOUND )
+ {
+ // der Format-String f"ur die negative Zahlen ist alles
+ // zwischen dem ersten und dem zweiten ';'.
+ // Daher: hole erst mal alles nach dem ersten ';'
+ String sTempStrg = sFormatStrg.Copy( nPos+1 );
+ // und suche darin ggf. ein weiteres ';'
+ nPos = sTempStrg.Search( FORMAT_SEPARATOR );
+ bFound = TRUE;
+ if( nPos==STRING_NOTFOUND )
+ // keins gefunden, liefere alles...
+ return sTempStrg;
+ else
+ // ansonsten den String zwischen den beiden ';' liefern
+ return sTempStrg.Copy( 0,nPos );
+ }
+ String aRetStr;
+ aRetStr.AssignAscii( EMPTYFORMATSTRING );
+ return aRetStr;
+}
+
+// siehe auch GetPosFormatString()
+String SbxBasicFormater::Get0FormatString( const String& sFormatStrg, BOOL & bFound )
+{
+ bFound = FALSE; // default...
+ USHORT nPos = sFormatStrg.Search( FORMAT_SEPARATOR );
+
+ if( nPos!=STRING_NOTFOUND )
+ {
+ // der Format-String f"ur die Null ist alles
+ // was nach dem zweiten ';' kommt.
+ // Daher: hole erst mal alles nach dem ersten ';'
+ String sTempStrg = sFormatStrg.Copy( nPos+1 );
+ // und suche darin ggf. ein weiteres ';'
+ nPos = sTempStrg.Search( FORMAT_SEPARATOR );
+ if( nPos!=STRING_NOTFOUND )
+ {
+ bFound = TRUE;
+ sTempStrg = sTempStrg.Copy( nPos+1 );
+ nPos = sTempStrg.Search( FORMAT_SEPARATOR );
+ if( nPos==STRING_NOTFOUND )
+ // keins gefunden, liefere alles...
+ return sTempStrg;
+ else
+ return sTempStrg.Copy( 0,nPos );
+ }
+ }
+ // kein ; gefunden, liefere Leerstring
+ String aRetStr;
+ aRetStr.AssignAscii( EMPTYFORMATSTRING );
+ return aRetStr;
+}
+
+// siehe auch GetPosFormatString()
+String SbxBasicFormater::GetNullFormatString( const String& sFormatStrg, BOOL & bFound )
+{
+ bFound = FALSE; // default...
+ USHORT nPos = sFormatStrg.Search( FORMAT_SEPARATOR );
+
+ if( nPos!=STRING_NOTFOUND )
+ {
+ // der Format-String f"ur die Null ist alles
+ // was nach dem dritten ';' kommt.
+ // Daher: hole erst mal alles nach dem ersten ';'
+ String sTempStrg = sFormatStrg.Copy( nPos+1 );
+ // und suche darin ggf. ein weiteres ';'
+ nPos = sTempStrg.Search( FORMAT_SEPARATOR );
+ if( nPos!=STRING_NOTFOUND )
+ {
+ // und suche nun nach dem dritten ';'
+ sTempStrg = sTempStrg.Copy( nPos+1 );
+ nPos = sTempStrg.Search( FORMAT_SEPARATOR );
+ if( nPos!=STRING_NOTFOUND )
+ {
+ bFound = TRUE;
+ return sTempStrg.Copy( nPos+1 );
+ }
+ }
+ }
+ // kein ; gefunden, liefere Leerstring
+ String aRetStr;
+ aRetStr.AssignAscii( EMPTYFORMATSTRING );
+ return aRetStr;
+}
+
+// analysiert den Format-String, liefert Wert <> 0 falls ein Fehler
+// aufgetreten ist
+short SbxBasicFormater::AnalyseFormatString( const String& sFormatStrg,
+ short& nNoOfDigitsLeft, short& nNoOfDigitsRight,
+ short& nNoOfOptionalDigitsLeft,
+ short& nNoOfExponentDigits, short& nNoOfOptionalExponentDigits,
+ BOOL& bPercent, BOOL& bCurrency, BOOL& bScientific,
+ BOOL& bGenerateThousandSeparator,
+ short& nMultipleThousandSeparators )
+{
+ USHORT nLen;
+ short nState = 0;
+
+ nLen = sFormatStrg.Len();
+ // initialisiere alle Z"ahler und Flags
+ nNoOfDigitsLeft = 0;
+ nNoOfDigitsRight = 0;
+ nNoOfOptionalDigitsLeft = 0;
+ nNoOfExponentDigits = 0;
+ nNoOfOptionalExponentDigits = 0;
+ bPercent = FALSE;
+ bCurrency = FALSE;
+ bScientific = FALSE;
+ // ab 11.7.97: sobald ein Komma in dem Format String gefunden wird,
+ // werden alle 3 Zehnerpotenzen markiert (d.h. tausender, milionen, ...)
+ // bisher wurde nur an den gesetzten Position ein Tausender-Separator
+ // ausgegeben oder wenn ein @ im Format-String stand.
+ // Dies war ein Missverstaendnis der VB Kompatiblitaet.
+ bGenerateThousandSeparator = sFormatStrg.Search( ',' ) != STRING_NOTFOUND;
+ nMultipleThousandSeparators = 0;
+ // und untersuche den Format-String nach den gew"unschten Informationen
+ for( USHORT i=0; i<nLen; i++ )
+ {
+ sal_Unicode c = sFormatStrg.GetChar( i );
+ switch( c ) {
+ case '#':
+ case '0':
+ if( nState==0 )
+ {
+ nNoOfDigitsLeft++;
+// TODO hier ggf. bessere Fehler-"Uberpr"ufung der Mantisse auf g"ultige Syntax (siehe Grammatik)
+ // ACHTUNG: 'undefiniertes' Verhalten falls # und 0
+ // gemischt werden !!!
+ // BEMERKUNG: eigentlich sind #-Platzhalter bei Scientific
+ // Darstellung vor dem Dezimal-Punkt sinnlos !
+ if( c=='#' )
+ nNoOfOptionalDigitsLeft++;
+ }
+ else if( nState==1 )
+ nNoOfDigitsRight++;
+ else if( nState==-1 ) // suche 0 im Exponent
+ {
+ if( c=='#' ) // # schaltet den Zustand weiter
+ {
+ nNoOfOptionalExponentDigits++;
+ nState = -2;
+ }
+ nNoOfExponentDigits++;
+ }
+ else if( nState==-2 ) // suche # im Exponent
+ {
+ if( c=='0' )
+ // ERROR: 0 nach # im Exponent ist NICHT erlaubt !!
+ return -4;
+ nNoOfOptionalExponentDigits++;
+ nNoOfExponentDigits++;
+ }
+ break;
+ case '.':
+ nState++;
+ if( nState>1 )
+ return -1; // ERROR: zu viele Dezimal-Punkte
+ break;
+ case '%':
+ bPercent = TRUE;
+ /* old:
+ bPercent++;
+ if( bPercent>1 )
+ return -2; // ERROR: zu viele Prozent-Zeichen
+ */
+ break;
+ case '(':
+ bCurrency = TRUE;
+ break;
+ case ',':
+ {
+ sal_Unicode ch = sFormatStrg.GetChar( i+1 );
+ // vorl"aufig wird NUR auf zwei aufeinanderfolgede
+ // Zeichen gepr"uft
+ if( ch!=0 && (ch==',' || ch=='.') )
+ nMultipleThousandSeparators++;
+ } break;
+ case 'e':
+ case 'E':
+ // #i13821 not when no digits before
+ if( nNoOfDigitsLeft > 0 || nNoOfDigitsRight > 0 )
+ {
+ nState = -1; // breche jetzt das Z"ahlen der Stellen ab
+ bScientific = TRUE;
+ }
+ /* old:
+ bScientific++;
+ if( bScientific>1 )
+ return -3; // ERROR: zu viele Exponent-Zeichen
+ */
+ break;
+ // EIGENES Kommando-Zeichen, das die Erzeugung der
+ // Tausender-Trennzeichen einschaltet
+ case '\\':
+ // Ignore next char
+ i++;
+ break;
+ case CREATE_1000SEP_CHAR:
+ bGenerateThousandSeparator = TRUE;
+ break;
+ }
+ }
+ return 0;
+}
+
+// das Flag bCreateSign zeigt an, dass bei der Mantisse ein Vorzeichen
+// erzeugt werden soll
+void SbxBasicFormater::ScanFormatString( double dNumber,
+ const String& sFormatStrg, String& sReturnStrg,
+ BOOL bCreateSign )
+{
+ short /*nErr,*/nNoOfDigitsLeft,nNoOfDigitsRight,nNoOfOptionalDigitsLeft,
+ nNoOfExponentDigits,nNoOfOptionalExponentDigits,
+ nMultipleThousandSeparators;
+ BOOL bPercent,bCurrency,bScientific,bGenerateThousandSeparator;
+
+ // Initialisiere den Return-String
+ sReturnStrg = String();
+
+ // analysiere den Format-String, d.h. bestimme folgende Werte:
+ /*
+ - Anzahl der Ziffern vor dem Komma
+ - Anzahl der Ziffern nach dem Komma
+ - optionale Ziffern vor dem Komma
+ - Anzahl der Ziffern im Exponent
+ - optionale Ziffern im Exponent
+ - Prozent-Zeichen gefunden ?
+ - () f"ur negatives Vorzeichen ?
+ - Exponetial-Schreibweise ?
+ - sollen Tausender-Separatoren erzeugt werden ?
+ - wird ein Prozent-Zeichen gefunden ? --> dNumber *= 100.0;
+ - gibt es aufeinanderfolgende Tausender-Trennzeichen ?
+ ,, oder ,. --> dNumber /= 1000.0;
+ - sonstige Fehler ? mehrfache Dezimalpunkte, E's, etc.
+ --> Fehler werden zur Zeit einfach ignoriert
+ */
+ /*nErr =*/ AnalyseFormatString( sFormatStrg,nNoOfDigitsLeft,nNoOfDigitsRight,
+ nNoOfOptionalDigitsLeft,nNoOfExponentDigits,
+ nNoOfOptionalExponentDigits,
+ bPercent,bCurrency,bScientific,bGenerateThousandSeparator,
+ nMultipleThousandSeparators );
+ /* es werden alle Fehler ignoriert, wie in Visual-Basic
+ if( nErr!=0 )
+ {
+ char sBuffer[512];
+
+ //sprintf( sBuffer,"bad format-string >%s< err=%i",sFormatStrg,nErr );
+ strcpy( sBuffer,"bad format-string" );
+ ShowError( sBuffer );
+ }
+ else
+ */
+ {
+ // Spezialbehandlung f"ur Spezialzeichen
+ if( bPercent )
+ dNumber *= 100.0;
+// TODO: diese Vorgabe (,, oder ,.) ist NICHT Visual-Basic kompatibel !
+ // Frage: soll das hier stehen bleiben (Anforderungen) ?
+ if( nMultipleThousandSeparators )
+ dNumber /= 1000.0;
+
+ // einige Arbeits-Variablen
+ double dExponent;
+ short i,nLen;
+ short nState,nDigitPos,nExponentPos,nMaxDigit,nMaxExponentDigit;
+ BOOL bFirstDigit,bFirstExponentDigit,bFoundFirstDigit,
+ bIsNegative,bZeroSpaceOn, bSignHappend,bDigitPosNegative;
+
+ // Initialisierung der Arbeits-Variablen
+ bSignHappend = FALSE;
+ bFoundFirstDigit = FALSE;
+ bIsNegative = dNumber<0.0;
+ nLen = sFormatStrg.Len();
+ dExponent = get_number_of_digits( dNumber );
+ nExponentPos = 0;
+ nMaxExponentDigit = 0;
+ nMaxDigit = (short)dExponent;
+ bDigitPosNegative = false;
+ if( bScientific )
+ {
+ //if( nNoOfOptionalDigitsLeft>0 )
+ // ShowError( "# in scientific-format in front of the decimal-point has no effect" );
+ // beim Exponent ggf. "uberz"ahlige Stellen vor dem Komma abziehen
+ dExponent = dExponent - (double)(nNoOfDigitsLeft-1);
+ nDigitPos = nMaxDigit;
+ nMaxExponentDigit = (short)get_number_of_digits( dExponent );
+ nExponentPos = nNoOfExponentDigits-1 - nNoOfOptionalExponentDigits;
+ }
+ else
+ {
+ nDigitPos = nNoOfDigitsLeft-1; // Z"ahlweise f"angt bei 0 an, 10^0
+ // hier ben"otigt man keine Exponent-Daten !
+ bDigitPosNegative = (nDigitPos < 0);
+ }
+ bFirstDigit = TRUE;
+ bFirstExponentDigit = TRUE;
+ nState = 0; // 0 --> Mantisse; 1 --> Exponent
+ bZeroSpaceOn = 0;
+
+
+#ifdef _with_sprintf
+ InitScan( dNumber );
+#endif
+ // scanne jetzt den Format-String:
+ sal_Unicode cForce = 0;
+ for( i=0; i<nLen; i++ )
+ {
+ sal_Unicode c;
+ if( cForce )
+ {
+ c = cForce;
+ cForce = 0;
+ }
+ else
+ {
+ c = sFormatStrg.GetChar( i );
+ }
+ switch( c ) {
+ case '0':
+ case '#':
+ if( nState==0 )
+ {
+ // Behandlung der Mantisse
+ if( bFirstDigit )
+ {
+ //org:bFirstDigit = FALSE;
+ // ggf. Vorzeichen erzeugen
+ // Bem.: bei bCurrency soll das negative
+ // Vorzeichen durch () angezeigt werden
+ if( bIsNegative && !bCreateSign/*!bCurrency*/ && !bSignHappend )
+ {
+ // nur einmal ein Vorzeichen ausgeben
+ bSignHappend = TRUE;
+ StrAppendChar( sReturnStrg,'-' );
+ }
+ // hier jetzt "uberz"ahlige Stellen ausgeben,
+ // d.h. vom Format-String nicht erfasste Stellen
+ if( nMaxDigit>nDigitPos )
+ {
+ for( short j=nMaxDigit; j>nDigitPos; j-- )
+ {
+ short nTempDigit;
+#ifdef _with_sprintf
+ AppendDigit( sReturnStrg,nTempDigit = GetDigitAtPosScan( j,bFoundFirstDigit ) );
+#else
+ AppendDigit( sReturnStrg,nTempDigit = GetDigitAtPos( dNumber,j,dNumber,bFoundFirstDigit ) );
+#endif
+ // wurde wirklich eine Ziffer eingefuegt ?
+ if( nTempDigit!=_NO_DIGIT )
+ // jetzt wurde wirklich eine Ziffer ausgegeben, Flag setzen
+ bFirstDigit = FALSE;
+ // muss ggf. ein Tausender-Trennzeichen erzeugt werden?
+ if( bGenerateThousandSeparator && ( c=='0' || nMaxDigit>=nDigitPos ) && j>0 && (j % 3 == 0) )
+ StrAppendChar( sReturnStrg,cThousandSep );
+ }
+ }
+ }
+ // muss f"ur eine leere Stelle eventuell eine 0 ausgegeben werden ?
+ if( nMaxDigit<nDigitPos && ( c=='0' || bZeroSpaceOn ) )
+ {
+ AppendDigit( sReturnStrg,0 ); // Ja
+ // jetzt wurde wirklich eine Ziffer ausgegeben, Flag setzen
+ bFirstDigit = FALSE;
+ bZeroSpaceOn = 1;
+ // BEM.: bei Visual-Basic schaltet die erste 0 f"ur alle
+ // nachfolgenden # (bis zum Dezimal-Punkt) die 0 ein,
+ // dieses Verhalten wird hier mit dem Flag simmuliert.
+ // muss ggf. ein Tausender-Trennzeichen erzeugt werden?
+ if( bGenerateThousandSeparator && ( c=='0' || nMaxDigit>=nDigitPos ) && nDigitPos>0 && (nDigitPos % 3 == 0) )
+ StrAppendChar( sReturnStrg,cThousandSep );
+ }
+ else
+ {
+ short nTempDigit;
+#ifdef _with_sprintf
+ AppendDigit( sReturnStrg,nTempDigit = GetDigitAtPosScan( nDigitPos,bFoundFirstDigit ) );
+#else
+ AppendDigit( sReturnStrg,nTempDigit = GetDigitAtPos( dNumber,nDigitPos,dNumber,bFoundFirstDigit ) );
+#endif
+ // wurde wirklich eine Ziffer eingefuegt ?
+ if( nTempDigit!=_NO_DIGIT )
+ // jetzt wurde wirklich eine Ziffer ausgegeben, Flag setzen
+ bFirstDigit = FALSE;
+ // muss ggf. ein Tausender-Trennzeichen erzeugt werden?
+ if( bGenerateThousandSeparator && ( c=='0' || nMaxDigit>=nDigitPos ) && nDigitPos>0 && (nDigitPos % 3 == 0) )
+ StrAppendChar( sReturnStrg,cThousandSep );
+ }
+ // und Position aktualisieren
+ nDigitPos--;
+ }
+ else
+ {
+ // Behandlung des Exponenten
+ if( bFirstExponentDigit )
+ {
+ // Vorzeichen wurde schon bei e/E ausgegeben
+ bFirstExponentDigit = FALSE;
+ if( nMaxExponentDigit>nExponentPos )
+ // hier jetzt "uberz"ahlige Stellen ausgeben,
+ // d.h. vom Format-String nicht erfasste Stellen
+ {
+ for( short j=nMaxExponentDigit; j>nExponentPos; j-- )
+ {
+#ifdef _with_sprintf
+ AppendDigit( sReturnStrg,GetDigitAtPosExpScan( dExponent,j,bFoundFirstDigit ) );
+#else
+ AppendDigit( sReturnStrg,GetDigitAtPos( dExponent,j,dExponent,bFoundFirstDigit ) );
+#endif
+ }
+ }
+ }
+ // muss f"ur eine leere Stelle eventuell eine 0 ausgegeben werden ?
+ if( nMaxExponentDigit<nExponentPos && c=='0' )
+ AppendDigit( sReturnStrg,0 ); // Ja
+ else
+#ifdef _with_sprintf
+ AppendDigit( sReturnStrg,GetDigitAtPosExpScan( dExponent,nExponentPos,bFoundFirstDigit ) );
+#else
+ AppendDigit( sReturnStrg,GetDigitAtPos( dExponent,nExponentPos,dExponent,bFoundFirstDigit ) );
+#endif
+ nExponentPos--;
+ }
+ break;
+ case '.':
+ if( bDigitPosNegative ) // #i13821: If no digits before .
+ {
+ bDigitPosNegative = false;
+ nDigitPos = 0;
+ cForce = '#';
+ i-=2;
+ break;
+ }
+ // gebe Komma aus
+ StrAppendChar( sReturnStrg,cDecPoint );
+ break;
+ case '%':
+ // ggf. "uberf"ussige 0en l"oschen, z.B. 4.500e4 in 0.0##e-00
+ ParseBack( sReturnStrg,sFormatStrg,i-1 );
+ // gebe Prozent-Zeichen aus
+ sReturnStrg.Insert('%');
+ break;
+ case 'e':
+ case 'E':
+ // muss Mantisse noch gerundet werden, bevor der Exponent angezeigt wird ?
+ {
+ // gibt es ueberhaupt eine Mantisse ?
+ if( bFirstDigit )
+ {
+ // anscheinend nicht, d.h. ungueltiger Format String, z.B. E000.00
+ // d.h. ignoriere diese e bzw. E Zeichen
+ // ggf. einen Fehler (wie Visual Basic) ausgeben ?
+
+ // #i13821: VB 6 behaviour
+ StrAppendChar( sReturnStrg,c );
+ break;
+ }
+
+ BOOL bOverflow = FALSE;
+#ifdef _with_sprintf
+ short nNextDigit = GetDigitAtPosScan( nDigitPos,bFoundFirstDigit );
+#else
+ short nNextDigit = GetDigitAtPos( dNumber,nDigitPos,dNumber,bFoundFirstDigit );
+#endif
+ if( nNextDigit>=5 )
+ StrRoundDigit( sReturnStrg,sReturnStrg.Len()-1,bOverflow );
+ if( bOverflow )
+ {
+ // es wurde eine f"uhrende 9 gerundet, d.h.
+ // verschiebe den Dezimal-Punkt um eine Stelle nach links
+ LeftShiftDecimalPoint( sReturnStrg );
+ // und l"osche die letzte Ziffer, diese wird
+ // duch die f"uhrende 1 ersetzt:
+ sReturnStrg.SetChar( sReturnStrg.Len()-1 , 0 );
+ // der Exponent muss um 1 erh"oht werden,
+ // da der Dezimalpunkt verschoben wurde
+ dExponent += 1.0;
+ }
+ // ggf. "uberf"ussige 0en l"oschen, z.B. 4.500e4 in 0.0##e-00
+ ParseBack( sReturnStrg,sFormatStrg,i-1 );
+ }
+ // "andere Zustand des Scanners
+ nState++;
+ // gebe Exponent-Zeichen aus
+ StrAppendChar( sReturnStrg,c );
+ // i++; // MANIPULATION der Schleifen-Variable !
+ c = sFormatStrg.GetChar( ++i );
+ // und gebe Vorzeichen / Exponent aus
+ if( c!=0 )
+ {
+ if( c=='-' )
+ {
+ // falls Exponent < 0 gebe - aus
+ if( dExponent<0.0 )
+ StrAppendChar( sReturnStrg,'-' );
+ }
+ else if( c=='+' )
+ {
+ // gebe auf jeden Fall das Vorzeichen des Exponenten aus !
+ if( dExponent<0.0 )
+ StrAppendChar( sReturnStrg,'-' );
+ else
+ StrAppendChar( sReturnStrg,'+' );
+ }
+ //else
+ // ShowError( "operator e/E did not find + or -" );
+ }
+ //else
+ // ShowError( "operator e/E ended with 0" );
+ break;
+ case ',':
+ // ACHTUNG: nur falls Zahl bisher ausgegeben wurde
+ // das Zeichen ausgeben
+ ////--> Siehe Kommentar vom 11.7. in AnalyseFormatString()
+ ////if( !bFirstDigit )
+ //// // gebe Tausender-Trennzeichen aus
+ //// StrAppendChar( sReturnStrg,cThousandSep );
+ break;
+ case ';':
+ break;
+ case '(':
+ case ')':
+ // ggf. "uberf"ussige 0en l"oschen, z.B. 4.500e4 in 0.0##e-00
+ ParseBack( sReturnStrg,sFormatStrg,i-1 );
+ if( bIsNegative )
+ StrAppendChar( sReturnStrg,c );
+ break;
+ case '$':
+ // den String fuer die Waehrung dranhengen:
+ sReturnStrg += sCurrencyStrg;
+ break;
+ case ' ':
+ case '-':
+ case '+':
+ // ggf. "uberf"ussige 0en l"oschen, z.B. 4.500e4 in 0.0##e-00
+ ParseBack( sReturnStrg,sFormatStrg,i-1 );
+ // gebe das jeweilige Zeichen direkt aus
+ StrAppendChar( sReturnStrg,c );
+ break;
+ case '\\':
+ // ggf. "uberf"ussige 0en l"oschen, z.B. 4.500e4 in 0.0##e-00
+ // falls Sonderzeichen am Ende oder mitten in
+ // Format-String vorkommen
+ ParseBack( sReturnStrg,sFormatStrg,i-1 );
+ // Sonderzeichen gefunden, gebe N"ACHSTES
+ // Zeichen direkt aus (falls es existiert)
+ // i++;
+ c = sFormatStrg.GetChar( ++i );
+ if( c!=0 )
+ StrAppendChar( sReturnStrg,c );
+ //else
+ // ShowError( "operator \\ ended with 0" );
+ break;
+ case CREATE_1000SEP_CHAR:
+ // hier ignorieren, Aktion wurde schon in
+ // AnalyseFormatString durchgef"uhrt
+ break;
+ default:
+ // auch die Zeichen und Ziffern ausgeben (wie in Visual-Basic)
+ if( ( c>='a' && c<='z' ) ||
+ ( c>='A' && c<='Z' ) ||
+ ( c>='1' && c<='9' ) )
+ StrAppendChar( sReturnStrg,c );
+ // else
+ // ignorieren !
+ // ehemals: ShowError( "bad character in format-string" );
+ }
+ }
+ // Format-String wurde vollst"andig gescanned,
+ // muss die letzte Stelle nun gerundet werden ?
+ // Dies hier ist jedoch NUR notwendig, falls das
+ // Zahlenformat NICHT Scientific-Format ist !
+ if( !bScientific )
+ {
+#ifdef _with_sprintf
+ short nNextDigit = GetDigitAtPosScan( nDigitPos,bFoundFirstDigit );
+#else
+ short nNextDigit = GetDigitAtPos( dNumber,nDigitPos,dNumber,bFoundFirstDigit );
+#endif
+ if( nNextDigit>=5 )
+ StrRoundDigit( sReturnStrg,sReturnStrg.Len()-1 );
+ }
+ // und ganz zum Schluss:
+ // ggf. "uberf"ussige 0en l"oschen, z.B. 4.500e4 in 0.0##e-00#,
+ // ABER nur Stellen nach dem Dezimal-Punkt k"onnen gel"oscht werden
+ if( nNoOfDigitsRight>0 )
+ ParseBack( sReturnStrg,sFormatStrg,sFormatStrg.Len()-1 );
+ }
+}
+
+String SbxBasicFormater::BasicFormatNull( String sFormatStrg )
+{
+ BOOL bNullFormatFound;
+ String sNullFormatStrg = GetNullFormatString( sFormatStrg,bNullFormatFound );
+
+ if( bNullFormatFound )
+ return sNullFormatStrg;
+ String aRetStr;
+ aRetStr.AssignAscii( "null" );
+ return aRetStr;
+}
+
+String SbxBasicFormater::BasicFormat( double dNumber, String sFormatStrg )
+{
+ BOOL bPosFormatFound,bNegFormatFound,b0FormatFound;
+
+ // analysiere Format-String auf vordefinierte Formate:
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_GENERALNUMBER ) )
+ sFormatStrg.AssignAscii( GENERALNUMBER_FORMAT );
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_CURRENCY ) )
+ sFormatStrg = sCurrencyFormatStrg; // old: CURRENCY_FORMAT;
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_FIXED ) )
+ sFormatStrg.AssignAscii( FIXED_FORMAT );
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_STANDARD ) )
+ sFormatStrg.AssignAscii( STANDARD_FORMAT );
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_PERCENT ) )
+ sFormatStrg.AssignAscii( PERCENT_FORMAT );
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_SCIENTIFIC ) )
+ sFormatStrg.AssignAscii( SCIENTIFIC_FORMAT );
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_YESNO ) )
+ return ( dNumber==0.0 ) ? sNoStrg : sYesStrg ;
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_TRUEFALSE ) )
+ return ( dNumber==0.0 ) ? sFalseStrg : sTrueStrg ;
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_ONOFF ) )
+ return ( dNumber==0.0 ) ? sOffStrg : sOnStrg ;
+
+ // analysiere Format-String auf ';', d.h. Format-Strings f"ur
+ // positive-, negative- und 0-Werte
+ String sPosFormatStrg = GetPosFormatString( sFormatStrg, bPosFormatFound );
+ String sNegFormatStrg = GetNegFormatString( sFormatStrg, bNegFormatFound );
+ String s0FormatStrg = Get0FormatString( sFormatStrg, b0FormatFound );
+ //String sNullFormatStrg = GetNullFormatString( sFormatStrg, bNullFormatFound );
+
+ String sReturnStrg;
+ String sTempStrg;
+
+ if( dNumber==0.0 )
+ {
+ sTempStrg = sFormatStrg;
+ if( b0FormatFound )
+ {
+ // wurde ggf. Leer-String uebergeben ?
+ if( s0FormatStrg.Len() == 0 && bPosFormatFound )
+ // --> Ja, dann verwende String fuer positive Werte
+ sTempStrg = sPosFormatStrg;
+ else
+ sTempStrg = s0FormatStrg;
+ }
+ else if( bPosFormatFound )
+ {
+ // verwende String fuer positive Werte
+ sTempStrg = sPosFormatStrg;
+ }
+ ScanFormatString( dNumber, sTempStrg, sReturnStrg,/*bCreateSign=*/FALSE );
+ }
+ else
+ {
+ if( dNumber<0.0 )
+ {
+ if( bNegFormatFound )
+ {
+ // wurde ggf. Leer-String uebergeben ?
+ if( sNegFormatStrg.Len() == 0 && bPosFormatFound )
+ {
+ // --> Ja, dann verwende String fuer positive Werte
+ // und setzte Minus-Zeichen davor !
+ sTempStrg = String::CreateFromAscii("-");
+ sTempStrg += sPosFormatStrg;
+ }
+ else
+ sTempStrg = sNegFormatStrg;
+ }
+ else
+ sTempStrg = sFormatStrg;
+ // falls KEIN Format-String speziell f"ur negative Werte angegeben
+ // wurde, so soll das Vorzeichen ausgegeben werden
+ ScanFormatString( dNumber, sTempStrg, sReturnStrg,/*bCreateSign=*/bNegFormatFound/*sNegFormatStrg!=EMPTYFORMATSTRING*/ );
+ }
+ else // if( dNumber>0.0 )
+ {
+ ScanFormatString( dNumber,
+ (/*sPosFormatStrg!=EMPTYFORMATSTRING*/bPosFormatFound ? sPosFormatStrg : sFormatStrg),
+ sReturnStrg,/*bCreateSign=*/FALSE );
+ }
+ }
+ return sReturnStrg;
+}
+
+BOOL SbxBasicFormater::isBasicFormat( String sFormatStrg )
+{
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_GENERALNUMBER ) )
+ return TRUE;
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_CURRENCY ) )
+ return TRUE;
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_FIXED ) )
+ return TRUE;
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_STANDARD ) )
+ return TRUE;
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_PERCENT ) )
+ return TRUE;
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_SCIENTIFIC ) )
+ return TRUE;
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_YESNO ) )
+ return TRUE;
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_TRUEFALSE ) )
+ return TRUE;
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_ONOFF ) )
+ return TRUE;
+ return FALSE;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxint.cxx b/basic/source/sbx/sbxint.cxx
new file mode 100644
index 000000000000..1bf183688932
--- /dev/null
+++ b/basic/source/sbx/sbxint.cxx
@@ -0,0 +1,965 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+#include <tools/errcode.hxx>
+#include <basic/sbx.hxx>
+#include "sbxconv.hxx"
+
+double ImpRound( double d )
+{
+ return d + ( d < 0 ? -0.5 : 0.5 );
+}
+
+INT16 ImpGetInteger( const SbxValues* p )
+{
+ SbxValues aTmp;
+ INT16 nRes;
+start:
+ switch( +p->eType )
+ {
+ case SbxNULL:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ case SbxEMPTY:
+ nRes = 0; break;
+ case SbxCHAR:
+ nRes = p->nChar; break;
+ case SbxBYTE:
+ nRes = p->nByte; break;
+ case SbxINTEGER:
+ case SbxBOOL:
+ nRes = p->nInteger; break;
+ case SbxERROR:
+ case SbxUSHORT:
+ if( p->nUShort > (USHORT) SbxMAXINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXINT;
+ }
+ else
+ nRes = (INT16) p->nUShort;
+ break;
+ case SbxLONG:
+ if( p->nLong > SbxMAXINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXINT;
+ }
+ else if( p->nLong < SbxMININT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMININT;
+ }
+ else
+ nRes = (INT16) p->nLong;
+ break;
+ case SbxULONG:
+ if( p->nULong > SbxMAXINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXINT;
+ }
+ else
+ nRes = (INT16) p->nULong;
+ break;
+ case SbxSINGLE:
+ if( p->nSingle > SbxMAXINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXINT;
+ }
+ else if( p->nSingle < SbxMININT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMININT;
+ }
+ else
+ nRes = (INT16) ImpRound( p->nSingle );
+ break;
+ case SbxSALINT64:
+ if( p->nInt64 > SbxMAXINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXINT;
+ }
+ else if( p->nInt64 < SbxMININT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMININT;
+ }
+ else
+ nRes = (INT16) p->nInt64;
+ break;
+ case SbxSALUINT64:
+ if( p->uInt64 > SbxMAXINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXINT;
+ }
+ else
+ nRes = (INT16) p->uInt64;
+ break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ case SbxLONG64:
+ case SbxULONG64:
+ case SbxCURRENCY:
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ {
+ double dVal;
+ if( p->eType == SbxCURRENCY )
+ dVal = ImpCurrencyToDouble( p->nLong64 );
+ else if( p->eType == SbxLONG64 )
+ dVal = ImpINT64ToDouble( p->nLong64 );
+ else if( p->eType == SbxULONG64 )
+ dVal = ImpUINT64ToDouble( p->nULong64 );
+ else if( p->eType == SbxDECIMAL )
+ {
+ dVal = 0.0;
+ if( p->pDecimal )
+ p->pDecimal->getDouble( dVal );
+ }
+ else
+ dVal = p->nDouble;
+
+ if( dVal > SbxMAXINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXINT;
+ }
+ else if( dVal < SbxMININT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMININT;
+ }
+ else
+ nRes = (INT16) ImpRound( dVal );
+ break;
+ }
+ case SbxLPSTR:
+ case SbxSTRING:
+ case SbxBYREF | SbxSTRING:
+ if( !p->pOUString )
+ nRes = 0;
+ else
+ {
+ double d;
+ SbxDataType t;
+ if( ImpScan( *p->pOUString, d, t, NULL ) != SbxERR_OK )
+ nRes = 0;
+ else if( d > SbxMAXINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXINT;
+ }
+ else if( d < SbxMININT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMININT;
+ }
+ else
+ nRes = (INT16) ImpRound( d );
+ }
+ break;
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ nRes = pVal->GetInteger();
+ else
+ {
+ SbxBase::SetError( SbxERR_NO_OBJECT ); nRes = 0;
+ }
+ break;
+ }
+
+ case SbxBYREF | SbxCHAR:
+ nRes = *p->pChar; break;
+ case SbxBYREF | SbxBYTE:
+ nRes = *p->pByte; break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ nRes = *p->pInteger; break;
+
+ // from here had to be tested
+ case SbxBYREF | SbxLONG:
+ aTmp.nLong = *p->pLong; goto ref;
+ case SbxBYREF | SbxULONG:
+ aTmp.nULong = *p->pULong; goto ref;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ aTmp.nUShort = *p->pUShort; goto ref;
+ case SbxBYREF | SbxSINGLE:
+ aTmp.nSingle = *p->pSingle; goto ref;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ aTmp.nDouble = *p->pDouble; goto ref;
+ case SbxBYREF | SbxULONG64:
+ aTmp.nULong64 = *p->pULong64; goto ref;
+ case SbxBYREF | SbxLONG64:
+ case SbxBYREF | SbxCURRENCY:
+ aTmp.nLong64 = *p->pLong64; goto ref;
+ case SbxBYREF | SbxSALINT64:
+ aTmp.nInt64 = *p->pnInt64; goto ref;
+ case SbxBYREF | SbxSALUINT64:
+ aTmp.uInt64 = *p->puInt64; goto ref;
+ ref:
+ aTmp.eType = SbxDataType( p->eType & 0x0FFF );
+ p = &aTmp; goto start;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0;
+ }
+ return nRes;
+}
+
+void ImpPutInteger( SbxValues* p, INT16 n )
+{
+ SbxValues aTmp;
+start:
+ switch( +p->eType )
+ {
+ // here had to be tested
+ case SbxCHAR:
+ aTmp.pChar = &p->nChar; goto direct;
+ case SbxBYTE:
+ aTmp.pByte = &p->nByte; goto direct;
+ case SbxULONG:
+ aTmp.pULong = &p->nULong; goto direct;
+ case SbxERROR:
+ case SbxUSHORT:
+ aTmp.pUShort = &p->nUShort; goto direct;
+ case SbxSALUINT64:
+ aTmp.puInt64 = &p->uInt64; goto direct;
+ direct:
+ aTmp.eType = SbxDataType( p->eType | SbxBYREF );
+ p = &aTmp; goto start;
+
+ // frome here no longer
+ case SbxINTEGER:
+ case SbxBOOL:
+ p->nInteger = n; break;
+ case SbxLONG:
+ p->nLong = n; break;
+ case SbxSINGLE:
+ p->nSingle = n; break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ p->nDouble = n; break;
+ case SbxSALINT64:
+ p->nInt64 = n; break;
+ case SbxULONG64:
+ p->nULong64 = ImpDoubleToUINT64( (double)n ); break;
+ case SbxLONG64:
+ p->nLong64 = ImpDoubleToINT64( (double)n ); break;
+ case SbxCURRENCY:
+ p->nLong64 = ImpDoubleToCurrency( (double)n ); break;
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ ImpCreateDecimal( p )->setInt( n );
+ break;
+
+ case SbxLPSTR:
+ case SbxSTRING:
+ case SbxBYREF | SbxSTRING:
+ if( !p->pOUString )
+ p->pOUString = new ::rtl::OUString;
+ ImpCvtNum( (double) n, 0, *p->pOUString );
+ break;
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ pVal->PutInteger( n );
+ else
+ SbxBase::SetError( SbxERR_NO_OBJECT );
+ break;
+ }
+ case SbxBYREF | SbxCHAR:
+ if( n < SbxMINCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINCHAR;
+ }
+ *p->pChar = (char) n; break;
+ case SbxBYREF | SbxBYTE:
+ if( n > SbxMAXBYTE )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXBYTE;
+ }
+ else if( n < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = 0;
+ }
+ *p->pByte = (BYTE) n; break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ *p->pInteger = n; break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ if( n < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = 0;
+ }
+ *p->pUShort = (UINT16) n; break;
+ case SbxBYREF | SbxLONG:
+ *p->pLong = (INT32) n; break;
+ case SbxBYREF | SbxULONG:
+ if( n < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = 0;
+ }
+ *p->pULong = (UINT32) n; break;
+ case SbxBYREF | SbxSALINT64:
+ *p->pnInt64 = n; break;
+ case SbxBYREF | SbxSALUINT64:
+ if( n < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); *p->puInt64 = 0;
+ }
+ else
+ *p->puInt64 = n;
+ break;
+ case SbxBYREF | SbxSINGLE:
+ *p->pSingle = (float) n; break;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ *p->pDouble = (double) n; break;
+ case SbxBYREF | SbxULONG64:
+ *p->pULong64 = ImpDoubleToUINT64( (double)n ); break;
+ case SbxBYREF | SbxLONG64:
+ *p->pLong64 = ImpDoubleToINT64( (double)n ); break;
+ case SbxBYREF | SbxCURRENCY:
+ *p->pLong64 = ImpDoubleToCurrency( (double)n ); break;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ }
+}
+
+
+// sal_Int64 / hyper
+
+sal_Int64 ImpDoubleToSalInt64( double d )
+{
+ sal_Int64 nRes;
+ if( d > SbxMAXSALINT64 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXSALINT64;
+ }
+ else if( d < SbxMINSALINT64 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMINSALINT64;
+ }
+ else
+ nRes = (sal_Int64) ImpRound( d );
+ return nRes;
+}
+
+sal_uInt64 ImpDoubleToSalUInt64( double d )
+{
+ sal_uInt64 nRes;
+ if( d > SbxMAXSALUINT64 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXSALUINT64;
+ }
+ else if( d < 0.0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0;
+ }
+ else
+ nRes = (sal_uInt64) ImpRound( d );
+ return nRes;
+}
+
+double ImpSalUInt64ToDouble( sal_uInt64 n )
+{
+ double d = 0.0;
+ if( n > SbxMAXSALINT64 )
+ SbxBase::SetError( SbxERR_CONVERSION );
+ else
+ d = (double)(sal_Int64) n;
+ return d;
+}
+
+
+sal_Int64 ImpGetInt64( const SbxValues* p )
+{
+ SbxValues aTmp;
+ sal_Int64 nRes;
+start:
+ switch( +p->eType )
+ {
+ case SbxNULL:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ case SbxEMPTY:
+ nRes = 0; break;
+ case SbxCHAR:
+ nRes = p->nChar; break;
+ case SbxBYTE:
+ nRes = p->nByte; break;
+ case SbxINTEGER:
+ case SbxBOOL:
+ nRes = p->nInteger; break;
+ case SbxERROR:
+ case SbxUSHORT:
+ nRes = p->nUShort; break;
+ case SbxLONG:
+ nRes = p->nLong; break;
+ case SbxULONG:
+ nRes = (sal_Int64) p->nULong; break;
+ case SbxSINGLE:
+ nRes = ImpDoubleToSalInt64( (double)p->nSingle );
+ break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ case SbxLONG64:
+ case SbxULONG64:
+ case SbxCURRENCY:
+ {
+ double dVal;
+ if( p->eType == SbxCURRENCY )
+ dVal = ImpCurrencyToDouble( p->nLong64 );
+ else if( p->eType == SbxLONG64 )
+ dVal = ImpINT64ToDouble( p->nLong64 );
+ else if( p->eType == SbxULONG64 )
+ dVal = ImpUINT64ToDouble( p->nULong64 );
+ else
+ dVal = p->nDouble;
+
+ nRes = ImpDoubleToSalInt64( dVal );
+ break;
+ }
+ case SbxSALINT64:
+ nRes = p->nInt64; break;
+ case SbxSALUINT64:
+ if( p->uInt64 > SbxMAXSALINT64 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXSALINT64;
+ }
+ else
+ nRes = (sal_Int64) p->uInt64;
+ break;
+
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+ if( !p->pOUString )
+ nRes = 0;
+ else
+ {
+ ::rtl::OString aOStr = ::rtl::OUStringToOString
+ ( *p->pOUString, RTL_TEXTENCODING_ASCII_US );
+ nRes = aOStr.toInt64();
+ if( nRes == 0 )
+ {
+ // Check if really 0 or invalid conversion
+ double d;
+ SbxDataType t;
+ if( ImpScan( *p->pOUString, d, t, NULL ) != SbxERR_OK )
+ nRes = 0;
+ else
+ nRes = ImpDoubleToSalInt64( d );
+ }
+ }
+ break;
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ nRes = pVal->GetInt64();
+ else
+ {
+ SbxBase::SetError( SbxERR_NO_OBJECT ); nRes = 0;
+ }
+ break;
+ }
+
+ case SbxBYREF | SbxCHAR:
+ nRes = *p->pChar; break;
+ case SbxBYREF | SbxBYTE:
+ nRes = *p->pByte; break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ nRes = *p->pInteger; break;
+ case SbxBYREF | SbxLONG:
+ nRes = *p->pLong; break;
+ case SbxBYREF | SbxULONG:
+ nRes = *p->pULong; break;
+ case SbxBYREF | SbxSALINT64:
+ nRes = *p->pnInt64; break;
+
+ // from here the values has to be checked
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ aTmp.nUShort = *p->pUShort; goto ref;
+ case SbxBYREF | SbxSINGLE:
+ aTmp.nSingle = *p->pSingle; goto ref;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ aTmp.nDouble = *p->pDouble; goto ref;
+ case SbxBYREF | SbxULONG64:
+ aTmp.nULong64 = *p->pULong64; goto ref;
+ case SbxBYREF | SbxLONG64:
+ case SbxBYREF | SbxCURRENCY:
+ aTmp.nLong64 = *p->pLong64; goto ref;
+ case SbxBYREF | SbxSALUINT64:
+ aTmp.uInt64 = *p->puInt64; goto ref;
+ ref:
+ aTmp.eType = SbxDataType( p->eType & 0x0FFF );
+ p = &aTmp; goto start;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0;
+ }
+ return nRes;
+}
+
+void ImpPutInt64( SbxValues* p, sal_Int64 n )
+{
+ SbxValues aTmp;
+
+start:
+ switch( +p->eType )
+ {
+ // Check neccessary
+ case SbxCHAR:
+ aTmp.pChar = &p->nChar; goto direct;
+ case SbxBYTE:
+ aTmp.pByte = &p->nByte; goto direct;
+ case SbxINTEGER:
+ case SbxBOOL:
+ aTmp.pInteger = &p->nInteger; goto direct;
+ case SbxULONG64:
+ aTmp.pULong64 = &p->nULong64; goto direct;
+ case SbxLONG64:
+ case SbxCURRENCY:
+ aTmp.pLong64 = &p->nLong64; goto direct;
+ case SbxULONG:
+ aTmp.pULong = &p->nULong; goto direct;
+ case SbxERROR:
+ case SbxUSHORT:
+ aTmp.pUShort = &p->nUShort; goto direct;
+ case SbxLONG:
+ aTmp.pnInt64 = &p->nInt64; goto direct;
+ case SbxSALUINT64:
+ aTmp.puInt64 = &p->uInt64; goto direct;
+
+ direct:
+ aTmp.eType = SbxDataType( p->eType | SbxBYREF );
+ p = &aTmp; goto start;
+
+ // Check not neccessary
+ case SbxSALINT64:
+ p->nInt64 = n; break;
+ case SbxSINGLE:
+ p->nSingle = (float) n; break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ p->nDouble = (double) n; break;
+
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+ {
+ if( !p->pOUString )
+ p->pOUString = new ::rtl::OUString;
+
+ ::rtl::OString aOStr = ::rtl::OString::valueOf( n );
+ (*p->pOUString) = ::rtl::OStringToOUString
+ ( aOStr, RTL_TEXTENCODING_ASCII_US );
+ break;
+ }
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ pVal->PutInt64( n );
+ else
+ SbxBase::SetError( SbxERR_NO_OBJECT );
+ break;
+ }
+ case SbxBYREF | SbxCHAR:
+ if( n > SbxMAXCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXCHAR;
+ }
+ else if( n < SbxMINCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINCHAR;
+ }
+ *p->pChar = (xub_Unicode) n; break;
+ case SbxBYREF | SbxBYTE:
+ if( n > SbxMAXBYTE )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXBYTE;
+ }
+ else if( n < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = 0;
+ }
+ *p->pByte = (BYTE) n; break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ if( n > SbxMAXINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXINT;
+ }
+ else if( n < SbxMININT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMININT;
+ }
+ *p->pInteger = (INT16) n; break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ if( n > SbxMAXUINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXUINT;
+ }
+ else if( n < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = 0;
+ }
+ *p->pUShort = (UINT16) n; break;
+ case SbxBYREF | SbxLONG:
+ if( n > SbxMAXLNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXLNG;
+ }
+ else if( n < SbxMINLNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINLNG;
+ }
+ *p->pLong = (INT32) n; break;
+ case SbxBYREF | SbxULONG:
+ if( n > SbxMAXULNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXULNG;
+ }
+ else if( n < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = 0;
+ }
+ *p->pULong = (UINT32) n; break;
+ case SbxBYREF | SbxSINGLE:
+ *p->pSingle = (float) n; break;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ *p->pDouble = (double) n; break;
+ case SbxBYREF | SbxCURRENCY:
+ if( n > SbxMAXCURR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = (sal_Int64) SbxMAXCURR;
+ }
+ else if( n < SbxMINCURR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = (sal_Int64) SbxMINCURR;
+ }
+ *p->pLong64 = ImpDoubleToCurrency( (double)n ); break;
+
+ case SbxBYREF | SbxSALINT64:
+ *p->pnInt64 = n; break;
+ case SbxBYREF | SbxSALUINT64:
+ if( n < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = 0;
+ }
+ *p->puInt64 = (sal_Int64) n; break;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ }
+}
+
+sal_uInt64 ImpGetUInt64( const SbxValues* p )
+{
+ SbxValues aTmp;
+ sal_uInt64 nRes;
+start:
+ switch( +p->eType )
+ {
+ case SbxNULL:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ case SbxEMPTY:
+ nRes = 0; break;
+ case SbxCHAR:
+ nRes = p->nChar; break;
+ case SbxBYTE:
+ nRes = p->nByte; break;
+ case SbxINTEGER:
+ case SbxBOOL:
+ nRes = p->nInteger; break;
+ case SbxERROR:
+ case SbxUSHORT:
+ nRes = p->nUShort; break;
+ case SbxLONG:
+ nRes = p->nLong; break;
+ case SbxULONG:
+ nRes = (sal_uInt64) p->nULong; break;
+ case SbxSINGLE:
+ nRes = ImpDoubleToSalUInt64( (double)p->nSingle );
+ break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ case SbxLONG64:
+ case SbxULONG64:
+ case SbxCURRENCY:
+ {
+ double dVal;
+ if( p->eType == SbxCURRENCY )
+ dVal = ImpCurrencyToDouble( p->nLong64 );
+ else if( p->eType == SbxLONG64 )
+ dVal = ImpINT64ToDouble( p->nLong64 );
+ else if( p->eType == SbxULONG64 )
+ dVal = ImpUINT64ToDouble( p->nULong64 );
+ else
+ dVal = p->nDouble;
+
+ nRes = ImpDoubleToSalUInt64( dVal );
+ break;
+ }
+ case SbxSALINT64:
+ if( p->nInt64 < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0;
+ }
+ else
+ nRes = (sal_uInt64) p->nInt64;
+ case SbxSALUINT64:
+ nRes = p->uInt64; break;
+
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+ if( !p->pOUString )
+ nRes = 0;
+ else
+ {
+ ::rtl::OString aOStr = ::rtl::OUStringToOString
+ ( *p->pOUString, RTL_TEXTENCODING_ASCII_US );
+ sal_Int64 n64 = aOStr.toInt64();
+ if( n64 == 0 )
+ {
+ // Check if really 0 or invalid conversion
+ double d;
+ SbxDataType t;
+ if( ImpScan( *p->pOUString, d, t, NULL ) != SbxERR_OK )
+ nRes = 0;
+ else if( d > SbxMAXSALUINT64 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXSALUINT64;
+ }
+ else if( d < 0.0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0;
+ }
+ else
+ nRes = (sal_uInt64) ImpRound( d );
+ }
+ else if( n64 < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0;
+ }
+ else
+ {
+ nRes = n64;
+ }
+ }
+ break;
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ nRes = pVal->GetUInt64();
+ else
+ {
+ SbxBase::SetError( SbxERR_NO_OBJECT ); nRes = 0;
+ }
+ break;
+ }
+
+ case SbxBYREF | SbxCHAR:
+ nRes = *p->pChar; break;
+ case SbxBYREF | SbxBYTE:
+ nRes = *p->pByte; break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ nRes = *p->pInteger; break;
+ case SbxBYREF | SbxLONG:
+ nRes = *p->pLong; break;
+ case SbxBYREF | SbxULONG:
+ nRes = *p->pULong; break;
+ case SbxBYREF | SbxSALUINT64:
+ nRes = *p->puInt64; break;
+
+ // from here the values has to be checked
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ aTmp.nUShort = *p->pUShort; goto ref;
+ case SbxBYREF | SbxSINGLE:
+ aTmp.nSingle = *p->pSingle; goto ref;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ aTmp.nDouble = *p->pDouble; goto ref;
+ case SbxBYREF | SbxULONG64:
+ aTmp.nULong64 = *p->pULong64; goto ref;
+ case SbxBYREF | SbxLONG64:
+ case SbxBYREF | SbxCURRENCY:
+ aTmp.nLong64 = *p->pLong64; goto ref;
+ case SbxBYREF | SbxSALINT64:
+ aTmp.nInt64 = *p->pnInt64; goto ref;
+ ref:
+ aTmp.eType = SbxDataType( p->eType & 0x0FFF );
+ p = &aTmp; goto start;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0;
+ }
+ return nRes;
+}
+
+void ImpPutUInt64( SbxValues* p, sal_uInt64 n )
+{
+ SbxValues aTmp;
+
+start:
+ switch( +p->eType )
+ {
+ // Check neccessary
+ case SbxCHAR:
+ aTmp.pChar = &p->nChar; goto direct;
+ case SbxBYTE:
+ aTmp.pByte = &p->nByte; goto direct;
+ case SbxINTEGER:
+ case SbxBOOL:
+ aTmp.pInteger = &p->nInteger; goto direct;
+ case SbxULONG64:
+ aTmp.pULong64 = &p->nULong64; goto direct;
+ case SbxLONG64:
+ case SbxCURRENCY:
+ aTmp.pLong64 = &p->nLong64; goto direct;
+ case SbxULONG:
+ aTmp.pULong = &p->nULong; goto direct;
+ case SbxERROR:
+ case SbxUSHORT:
+ aTmp.pUShort = &p->nUShort; goto direct;
+ case SbxLONG:
+ aTmp.pnInt64 = &p->nInt64; goto direct;
+ case SbxSALINT64:
+ aTmp.pnInt64 = &p->nInt64; goto direct;
+ case SbxSINGLE:
+ aTmp.pSingle = &p->nSingle; goto direct;
+ case SbxDATE:
+ case SbxDOUBLE:
+ aTmp.pDouble = &p->nDouble; goto direct;
+
+ direct:
+ aTmp.eType = SbxDataType( p->eType | SbxBYREF );
+ p = &aTmp; goto start;
+
+ // Check not neccessary
+ case SbxSALUINT64:
+ p->uInt64 = n; break;
+
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+ if( !p->pOUString )
+ p->pOUString = new ::rtl::OUString;
+ if( n > SbxMAXSALINT64 )
+ SbxBase::SetError( SbxERR_CONVERSION );
+ else
+ {
+ ::rtl::OString aOStr = ::rtl::OString::valueOf( (sal_Int64)n );
+ (*p->pOUString) = ::rtl::OStringToOUString
+ ( aOStr, RTL_TEXTENCODING_ASCII_US );
+ }
+ break;
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ pVal->PutUInt64( n );
+ else
+ SbxBase::SetError( SbxERR_NO_OBJECT );
+ break;
+ }
+ case SbxBYREF | SbxCHAR:
+ if( n > SbxMAXCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXCHAR;
+ }
+ *p->pChar = (xub_Unicode) n; break;
+ case SbxBYREF | SbxBYTE:
+ if( n > SbxMAXBYTE )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXBYTE;
+ }
+ *p->pByte = (BYTE) n; break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ if( n > SbxMAXINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXINT;
+ }
+ *p->pInteger = (INT16) n; break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ if( n > SbxMAXUINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXUINT;
+ }
+ *p->pUShort = (UINT16) n; break;
+ case SbxBYREF | SbxLONG:
+ if( n > SbxMAXLNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXLNG;
+ }
+ *p->pLong = (INT32) n; break;
+ case SbxBYREF | SbxULONG:
+ if( n > SbxMAXULNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXULNG;
+ }
+ *p->pULong = (UINT32) n; break;
+ case SbxBYREF | SbxSINGLE:
+ *p->pDouble = (float)ImpSalUInt64ToDouble( n ); break;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ *p->pDouble = ImpSalUInt64ToDouble( n ); break;
+ case SbxBYREF | SbxCURRENCY:
+ if( n > SbxMAXSALINT64 || (sal_Int64)n > SbxMAXCURR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = (sal_Int64) SbxMAXCURR;
+ }
+ *p->pLong64 = ImpDoubleToCurrency( (double)(sal_Int64) n ); break;
+
+ case SbxBYREF | SbxSALUINT64:
+ *p->puInt64 = n; break;
+ case SbxBYREF | SbxSALINT64:
+ if( n > SbxMAXSALINT64 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = 0;
+ }
+ *p->pnInt64 = (sal_Int64) n; break;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ }
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxlng.cxx b/basic/source/sbx/sbxlng.cxx
new file mode 100644
index 000000000000..748034171dde
--- /dev/null
+++ b/basic/source/sbx/sbxlng.cxx
@@ -0,0 +1,343 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+#include <tools/errcode.hxx>
+#include <basic/sbx.hxx>
+#include "sbxconv.hxx"
+
+INT32 ImpGetLong( const SbxValues* p )
+{
+ SbxValues aTmp;
+ INT32 nRes;
+start:
+ switch( +p->eType )
+ {
+ case SbxNULL:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ case SbxEMPTY:
+ nRes = 0; break;
+ case SbxCHAR:
+ nRes = p->nChar; break;
+ case SbxBYTE:
+ nRes = p->nByte; break;
+ case SbxINTEGER:
+ case SbxBOOL:
+ nRes = p->nInteger; break;
+ case SbxERROR:
+ case SbxUSHORT:
+ nRes = p->nUShort; break;
+ case SbxLONG:
+ nRes = p->nLong; break;
+ case SbxULONG:
+ if( p->nULong > SbxMAXLNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXLNG;
+ }
+ else
+ nRes = (INT32) p->nULong;
+ break;
+ case SbxSINGLE:
+ if( p->nSingle > SbxMAXLNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXLNG;
+ }
+ else if( p->nSingle < SbxMINLNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMINLNG;
+ }
+ else
+ nRes = (INT32) ImpRound( p->nSingle );
+ break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ case SbxLONG64:
+ case SbxULONG64:
+ case SbxSALINT64:
+ case SbxSALUINT64:
+ case SbxCURRENCY:
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ {
+ double dVal;
+ if( p->eType == SbxCURRENCY )
+ dVal = ImpCurrencyToDouble( p->nLong64 );
+ else if( p->eType == SbxLONG64 )
+ dVal = ImpINT64ToDouble( p->nLong64 );
+ else if( p->eType == SbxULONG64 )
+ dVal = ImpUINT64ToDouble( p->nULong64 );
+ else if( p->eType == SbxSALINT64 )
+ dVal = static_cast< double >(p->nInt64);
+ else if( p->eType == SbxSALUINT64 )
+ dVal = ImpSalUInt64ToDouble( p->uInt64 );
+ else if( p->eType == SbxDECIMAL )
+ {
+ dVal = 0.0;
+ if( p->pDecimal )
+ p->pDecimal->getDouble( dVal );
+ }
+ else
+ dVal = p->nDouble;
+
+ if( dVal > SbxMAXLNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXLNG;
+ }
+ else if( dVal < SbxMINLNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMINLNG;
+ }
+ else
+ nRes = (INT32) ImpRound( dVal );
+ break;
+ }
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+ if( !p->pOUString )
+ nRes = 0;
+ else
+ {
+ double d;
+ SbxDataType t;
+ if( ImpScan( *p->pOUString, d, t, NULL ) != SbxERR_OK )
+ nRes = 0;
+ else if( d > SbxMAXLNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXLNG;
+ }
+ else if( d < SbxMINLNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMINLNG;
+ }
+ else
+ nRes = (INT32) ImpRound( d );
+ }
+ break;
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ nRes = pVal->GetLong();
+ else
+ {
+ SbxBase::SetError( SbxERR_NO_OBJECT ); nRes = 0;
+ }
+ break;
+ }
+
+ case SbxBYREF | SbxCHAR:
+ nRes = *p->pChar; break;
+ case SbxBYREF | SbxBYTE:
+ nRes = *p->pByte; break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ nRes = *p->pInteger; break;
+ case SbxBYREF | SbxLONG:
+ nRes = *p->pLong; break;
+
+ // from here had to be tested
+ case SbxBYREF | SbxULONG:
+ aTmp.nULong = *p->pULong; goto ref;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ aTmp.nUShort = *p->pUShort; goto ref;
+ case SbxBYREF | SbxSINGLE:
+ aTmp.nSingle = *p->pSingle; goto ref;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ aTmp.nDouble = *p->pDouble; goto ref;
+ case SbxBYREF | SbxSALINT64:
+ aTmp.nInt64 = *p->pnInt64; goto ref;
+ case SbxBYREF | SbxSALUINT64:
+ aTmp.uInt64 = *p->puInt64; goto ref;
+ case SbxBYREF | SbxULONG64:
+ aTmp.nULong64 = *p->pULong64; goto ref;
+ case SbxBYREF | SbxLONG64:
+ case SbxBYREF | SbxCURRENCY:
+ aTmp.nLong64 = *p->pLong64; goto ref;
+ ref:
+ aTmp.eType = SbxDataType( p->eType & 0x0FFF );
+ p = &aTmp; goto start;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0;
+ }
+ return nRes;
+}
+
+void ImpPutLong( SbxValues* p, INT32 n )
+{
+ SbxValues aTmp;
+
+start:
+ switch( +p->eType )
+ {
+ // From here had to be tested
+ case SbxCHAR:
+ aTmp.pChar = &p->nChar; goto direct;
+ case SbxBYTE:
+ aTmp.pByte = &p->nByte; goto direct;
+ case SbxINTEGER:
+ case SbxBOOL:
+ aTmp.pInteger = &p->nInteger; goto direct;
+ case SbxULONG64:
+ aTmp.pULong64 = &p->nULong64; goto direct;
+ case SbxLONG64:
+ case SbxCURRENCY:
+ aTmp.pLong64 = &p->nLong64; goto direct;
+ case SbxULONG:
+ aTmp.pULong = &p->nULong; goto direct;
+ case SbxSALUINT64:
+ aTmp.puInt64 = &p->uInt64; goto direct;
+ case SbxERROR:
+ case SbxUSHORT:
+ aTmp.pUShort = &p->nUShort;
+ direct:
+ aTmp.eType = SbxDataType( p->eType | SbxBYREF );
+ p = &aTmp; goto start;
+
+ // from here no longer
+ case SbxLONG:
+ p->nLong = n; break;
+ case SbxSINGLE:
+ p->nSingle = (float) n; break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ p->nDouble = n; break;
+ case SbxSALINT64:
+ p->nInt64 = n; break;
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ ImpCreateDecimal( p )->setLong( n );
+ break;
+
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+ if( !p->pOUString )
+ p->pOUString = new ::rtl::OUString;
+ ImpCvtNum( (double) n, 0, *p->pOUString );
+ break;
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ pVal->PutLong( n );
+ else
+ SbxBase::SetError( SbxERR_NO_OBJECT );
+ break;
+ }
+ case SbxBYREF | SbxCHAR:
+ if( n > SbxMAXCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXCHAR;
+ }
+ else if( n < SbxMINCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINCHAR;
+ }
+ *p->pChar = (xub_Unicode) n; break;
+ case SbxBYREF | SbxBYTE:
+ if( n > SbxMAXBYTE )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXBYTE;
+ }
+ else if( n < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = 0;
+ }
+ *p->pByte = (BYTE) n; break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ if( n > SbxMAXINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXINT;
+ }
+ else if( n < SbxMININT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMININT;
+ }
+ *p->pInteger = (INT16) n; break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ if( n > SbxMAXUINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXUINT;
+ }
+ else if( n < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = 0;
+ }
+ *p->pUShort = (UINT16) n; break;
+ case SbxBYREF | SbxLONG:
+ *p->pLong = n; break;
+ case SbxBYREF | SbxULONG:
+ if( n < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = 0;
+ }
+ *p->pULong = (UINT32) n; break;
+ case SbxBYREF | SbxSALINT64:
+ *p->pnInt64 = n; break;
+ case SbxBYREF | SbxSALUINT64:
+ if( n < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); *p->puInt64 = 0;
+ }
+ else
+ *p->puInt64 = n;
+ break;
+ case SbxBYREF | SbxSINGLE:
+ *p->pSingle = (float) n; break;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ *p->pDouble = (double) n; break;
+ case SbxBYREF | SbxCURRENCY:
+ double d;
+ if( n > SbxMAXCURR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); d = SbxMAXCURR;
+ }
+ else if( n < SbxMINCURR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); d = SbxMINCURR;
+ }
+ else
+ {
+ d = n;
+ }
+ *p->pLong64 = ImpDoubleToCurrency( d ); break;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxmstrm.cxx b/basic/source/sbx/sbxmstrm.cxx
new file mode 100644
index 000000000000..c2eeaeff7dfe
--- /dev/null
+++ b/basic/source/sbx/sbxmstrm.cxx
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+#include <basic/sbxmstrm.hxx>
+
+SbxDataType SbxMemoryStream::GetType() const
+{
+ return SbxMEMORYSTREAM;
+}
+
+SbxMemoryStream::~SbxMemoryStream()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxobj.cxx b/basic/source/sbx/sbxobj.cxx
new file mode 100644
index 000000000000..afc7debdc95f
--- /dev/null
+++ b/basic/source/sbx/sbxobj.cxx
@@ -0,0 +1,1067 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+#include <tools/stream.hxx>
+#include <vcl/sound.hxx>
+#include <basic/sbx.hxx>
+#include <basic/sbxbase.hxx>
+#include "sbxres.hxx"
+#include <svl/brdcst.hxx>
+
+TYPEINIT1(SbxMethod,SbxVariable)
+TYPEINIT1(SbxProperty,SbxVariable)
+TYPEINIT2(SbxObject,SbxVariable,SfxListener)
+
+static const char* pNameProp; // Name-Property
+static const char* pParentProp; // Parent-Property
+
+static USHORT nNameHash = 0, nParentHash = 0;
+
+/////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////
+
+SbxObject::SbxObject( const XubString& rClass )
+ : SbxVariable( SbxOBJECT ), aClassName( rClass )
+{
+ aData.pObj = this;
+ if( !nNameHash )
+ {
+ pNameProp = GetSbxRes( STRING_NAMEPROP );
+ pParentProp = GetSbxRes( STRING_PARENTPROP );
+ nNameHash = MakeHashCode( String::CreateFromAscii( pNameProp ) );
+ nParentHash = MakeHashCode( String::CreateFromAscii( pParentProp ) );
+ }
+ SbxObject::Clear();
+ SbxObject::SetName( rClass );
+}
+
+SbxObject::SbxObject( const SbxObject& rObj )
+ : SvRefBase( rObj ), SbxVariable( rObj.GetType() ),
+ SfxListener( rObj )
+{
+ *this = rObj;
+}
+
+SbxObject& SbxObject::operator=( const SbxObject& r )
+{
+ if( &r != this )
+ {
+ SbxVariable::operator=( r );
+ aClassName = r.aClassName;
+ pMethods = new SbxArray;
+ pProps = new SbxArray;
+ pObjs = new SbxArray( SbxOBJECT );
+ // Die Arrays werden kopiert, die Inhalte uebernommen
+ *pMethods = *r.pMethods;
+ *pProps = *r.pProps;
+ *pObjs = *r.pObjs;
+ // Da die Variablen uebernommen wurden, ist dies OK
+ pDfltProp = r.pDfltProp;
+ SetName( r.GetName() );
+ SetFlags( r.GetFlags() );
+ SetModified( TRUE );
+ }
+ return *this;
+}
+
+static void CheckParentsOnDelete( SbxObject* pObj, SbxArray* p )
+{
+ for( USHORT i = 0; i < p->Count(); i++ )
+ {
+ SbxVariableRef& rRef = p->GetRef( i );
+ if( rRef->IsBroadcaster() )
+ pObj->EndListening( rRef->GetBroadcaster(), TRUE );
+ // Hat das Element mehr als eine Referenz und noch einen Listener?
+ if( rRef->GetRefCount() > 1 )
+ {
+ rRef->SetParent( NULL );
+ DBG_ASSERT( !rRef->IsBroadcaster() || rRef->GetBroadcaster().GetListenerCount(), "Object element with dangling parent" );
+ }
+ }
+}
+
+SbxObject::~SbxObject()
+{
+ CheckParentsOnDelete( this, pProps );
+ CheckParentsOnDelete( this, pMethods );
+ CheckParentsOnDelete( this, pObjs );
+}
+
+SbxDataType SbxObject::GetType() const
+{
+ return SbxOBJECT;
+}
+
+SbxClassType SbxObject::GetClass() const
+{
+ return SbxCLASS_OBJECT;
+}
+
+void SbxObject::Clear()
+{
+ pMethods = new SbxArray;
+ pProps = new SbxArray;
+ pObjs = new SbxArray( SbxOBJECT );
+ SbxVariable* p;
+ p = Make( String::CreateFromAscii( pNameProp ), SbxCLASS_PROPERTY, SbxSTRING );
+ p->SetFlag( SBX_DONTSTORE );
+ p = Make( String::CreateFromAscii( pParentProp ), SbxCLASS_PROPERTY, SbxOBJECT );
+ p->ResetFlag( SBX_WRITE );
+ p->SetFlag( SBX_DONTSTORE );
+ pDfltProp = NULL;
+ SetModified( FALSE );
+}
+
+void SbxObject::SFX_NOTIFY( SfxBroadcaster&, const TypeId&,
+ const SfxHint& rHint, const TypeId& )
+{
+ const SbxHint* p = PTR_CAST(SbxHint,&rHint);
+ if( p )
+ {
+ ULONG nId = p->GetId();
+ BOOL bRead = BOOL( nId == SBX_HINT_DATAWANTED );
+ BOOL bWrite = BOOL( nId == SBX_HINT_DATACHANGED );
+ SbxVariable* pVar = p->GetVar();
+ if( bRead || bWrite )
+ {
+ XubString aVarName( pVar->GetName() );
+ USHORT nHash_ = MakeHashCode( aVarName );
+ if( nHash_ == nNameHash
+ && aVarName.EqualsIgnoreCaseAscii( pNameProp ) )
+ {
+ if( bRead )
+ pVar->PutString( GetName() );
+ else
+ SetName( pVar->GetString() );
+ }
+ else if( nHash_ == nParentHash
+ && aVarName.EqualsIgnoreCaseAscii( pParentProp ) )
+ {
+ SbxObject* p_ = GetParent();
+ if( !p_ )
+ p_ = this;
+ pVar->PutObject( p_ );
+ }
+ }
+ }
+}
+
+BOOL SbxObject::IsClass( const XubString& rName ) const
+{
+ return BOOL( aClassName.EqualsIgnoreCaseAscii( rName ) );
+}
+
+SbxVariable* SbxObject::FindUserData( UINT32 nData )
+{
+ if( !GetAll( SbxCLASS_DONTCARE ) )
+ return NULL;
+
+ SbxVariable* pRes = pMethods->FindUserData( nData );
+ if( !pRes )
+ pRes = pProps->FindUserData( nData );
+ if( !pRes )
+ pRes = pObjs->FindUserData( nData );
+ // Search in den Parents?
+ if( !pRes && IsSet( SBX_GBLSEARCH ) )
+ {
+ SbxObject* pCur = this;
+ while( !pRes && pCur->pParent )
+ {
+ // Ich selbst bin schon durchsucht worden!
+ USHORT nOwn = pCur->GetFlags();
+ pCur->ResetFlag( SBX_EXTSEARCH );
+ // Ich suche bereits global!
+ USHORT nPar = pCur->pParent->GetFlags();
+ pCur->pParent->ResetFlag( SBX_GBLSEARCH );
+ pRes = pCur->pParent->FindUserData( nData );
+ pCur->SetFlags( nOwn );
+ pCur->pParent->SetFlags( nPar );
+ pCur = pCur->pParent;
+ }
+ }
+ return pRes;
+}
+
+SbxVariable* SbxObject::Find( const XubString& rName, SbxClassType t )
+{
+#ifdef DBG_UTIL
+ static USHORT nLvl = 0;
+ static const char* pCls[] =
+ { "DontCare","Array","Value","Variable","Method","Property","Object" };
+ ByteString aNameStr1( (const UniString&)rName, RTL_TEXTENCODING_ASCII_US );
+ ByteString aNameStr2( (const UniString&)SbxVariable::GetName(), RTL_TEXTENCODING_ASCII_US );
+ DbgOutf( "SBX: Search %.*s %s %s in %s",
+ nLvl++, " ",
+ ( t >= SbxCLASS_DONTCARE && t <= SbxCLASS_OBJECT )
+ ? pCls[ t-1 ] : "Unknown class", aNameStr1.GetBuffer(), aNameStr1.GetBuffer() );
+#endif
+
+ if( !GetAll( t ) )
+ return NULL;
+ SbxVariable* pRes = NULL;
+ pObjs->SetFlag( SBX_EXTSEARCH );
+ if( t == SbxCLASS_DONTCARE )
+ {
+ pRes = pMethods->Find( rName, SbxCLASS_METHOD );
+ if( !pRes )
+ pRes = pProps->Find( rName, SbxCLASS_PROPERTY );
+ if( !pRes )
+ pRes = pObjs->Find( rName, t );
+ }
+ else
+ {
+ SbxArray* pArray = NULL;
+ switch( t )
+ {
+ case SbxCLASS_VARIABLE:
+ case SbxCLASS_PROPERTY: pArray = pProps; break;
+ case SbxCLASS_METHOD: pArray = pMethods; break;
+ case SbxCLASS_OBJECT: pArray = pObjs; break;
+ default:
+ DBG_ASSERT( !this, "Ungueltige SBX-Klasse" );
+ }
+ if( pArray )
+ pRes = pArray->Find( rName, t );
+ }
+ // Extended Search im Objekt-Array?
+ // Fuer Objekte und DontCare ist das Objektarray bereits
+ // durchsucht worden
+ if( !pRes && ( t == SbxCLASS_METHOD || t == SbxCLASS_PROPERTY ) )
+ pRes = pObjs->Find( rName, t );
+ // Search in den Parents?
+ if( !pRes && IsSet( SBX_GBLSEARCH ) )
+ {
+ SbxObject* pCur = this;
+ while( !pRes && pCur->pParent )
+ {
+ // Ich selbst bin schon durchsucht worden!
+ USHORT nOwn = pCur->GetFlags();
+ pCur->ResetFlag( SBX_EXTSEARCH );
+ // Ich suche bereits global!
+ USHORT nPar = pCur->pParent->GetFlags();
+ pCur->pParent->ResetFlag( SBX_GBLSEARCH );
+ pRes = pCur->pParent->Find( rName, t );
+ pCur->SetFlags( nOwn );
+ pCur->pParent->SetFlags( nPar );
+ pCur = pCur->pParent;
+ }
+ }
+#ifdef DBG_UTIL
+ nLvl--;
+ if( pRes )
+ {
+ ByteString aNameStr3( (const UniString&)rName, RTL_TEXTENCODING_ASCII_US );
+ ByteString aNameStr4( (const UniString&)SbxVariable::GetName(), RTL_TEXTENCODING_ASCII_US );
+ DbgOutf( "SBX: Found %.*s %s in %s",
+ nLvl, " ", aNameStr3.GetBuffer(), aNameStr4.GetBuffer() );
+ }
+#endif
+ return pRes;
+}
+
+// Kurzform: Die Parent-Kette wird durchsucht
+// Das ganze rekursiv, da Call() ueberladen sein kann
+// Qualified Names sind zugelassen
+
+BOOL SbxObject::Call( const XubString& rName, SbxArray* pParam )
+{
+ SbxVariable* pMeth = FindQualified( rName, SbxCLASS_DONTCARE);
+ if( pMeth && pMeth->ISA(SbxMethod) )
+ {
+ // FindQualified() koennte schon zugeschlagen haben!
+ if( pParam )
+ pMeth->SetParameters( pParam );
+ pMeth->Broadcast( SBX_HINT_DATAWANTED );
+ pMeth->SetParameters( NULL );
+ return TRUE;
+ }
+ SetError( SbxERR_NO_METHOD );
+ return FALSE;
+}
+
+SbxProperty* SbxObject::GetDfltProperty()
+{
+ if ( !pDfltProp && aDfltPropName.Len() )
+ {
+ pDfltProp = (SbxProperty*) Find( aDfltPropName, SbxCLASS_PROPERTY );
+ if( !pDfltProp )
+ pDfltProp = (SbxProperty*) Make( aDfltPropName, SbxCLASS_PROPERTY, SbxVARIANT );
+ }
+ return pDfltProp;
+}
+void SbxObject::SetDfltProperty( const XubString& rName )
+{
+ if ( rName != aDfltPropName )
+ pDfltProp = NULL;
+ aDfltPropName = rName;
+ SetModified( TRUE );
+}
+
+void SbxObject::SetDfltProperty( SbxProperty* p )
+{
+ if( p )
+ {
+ USHORT n;
+ SbxArray* pArray = FindVar( p, n );
+ pArray->Put( p, n );
+ if( p->GetParent() != this )
+ p->SetParent( this );
+ Broadcast( SBX_HINT_OBJECTCHANGED );
+ }
+ pDfltProp = p;
+ SetModified( TRUE );
+}
+
+// Suchen einer bereits vorhandenen Variablen. Falls sie gefunden wurde,
+// wird der Index gesetzt, sonst wird der Count des Arrays geliefert.
+// In jedem Fall wird das korrekte Array geliefert.
+
+SbxArray* SbxObject::FindVar( SbxVariable* pVar, USHORT& nArrayIdx )
+{
+ SbxArray* pArray = NULL;
+ if( pVar ) switch( pVar->GetClass() )
+ {
+ case SbxCLASS_VARIABLE:
+ case SbxCLASS_PROPERTY: pArray = pProps; break;
+ case SbxCLASS_METHOD: pArray = pMethods; break;
+ case SbxCLASS_OBJECT: pArray = pObjs; break;
+ default:
+ DBG_ASSERT( !this, "Ungueltige SBX-Klasse" );
+ }
+ if( pArray )
+ {
+ nArrayIdx = pArray->Count();
+ // ist die Variable per Name vorhanden?
+ pArray->ResetFlag( SBX_EXTSEARCH );
+ SbxVariable* pOld = pArray->Find( pVar->GetName(), pVar->GetClass() );
+ if( pOld )
+ for( USHORT i = 0; i < pArray->Count(); i++ )
+ {
+ SbxVariableRef& rRef = pArray->GetRef( i );
+ if( (SbxVariable*) rRef == pOld )
+ {
+ nArrayIdx = i; break;
+ }
+ }
+ }
+ return pArray;
+}
+
+// Falls ein neues Objekt eingerichtet wird, wird es, falls es bereits
+// eines mit diesem Namen gibt, indiziert.
+
+SbxVariable* SbxObject::Make( const XubString& rName, SbxClassType ct, SbxDataType dt )
+{
+ // Ist das Objekt bereits vorhanden?
+ SbxArray* pArray = NULL;
+ switch( ct )
+ {
+ case SbxCLASS_VARIABLE:
+ case SbxCLASS_PROPERTY: pArray = pProps; break;
+ case SbxCLASS_METHOD: pArray = pMethods; break;
+ case SbxCLASS_OBJECT: pArray = pObjs; break;
+ default:
+ DBG_ASSERT( !this, "Ungueltige SBX-Klasse" );
+ }
+ if( !pArray )
+ return NULL;
+ // Collections duerfen gleichnamige Objekte enthalten
+ if( !( ct == SbxCLASS_OBJECT && ISA(SbxCollection) ) )
+ {
+ SbxVariable* pRes = pArray->Find( rName, ct );
+ if( pRes )
+ {
+/* Wegen haeufiger Probleme (z.B. #67000) erstmal ganz raus
+#ifdef DBG_UTIL
+ if( pRes->GetHashCode() != nNameHash
+ && pRes->GetHashCode() != nParentHash )
+ {
+ XubString aMsg( "SBX-Element \"" );
+ aMsg += pRes->GetName();
+ aMsg += "\"\n in Objekt \"";
+ aMsg += GetName();
+ aMsg += "\" bereits vorhanden";
+ DbgError( (const char*)aMsg.GetStr() );
+ }
+#endif
+*/
+ return pRes;
+ }
+ }
+ SbxVariable* pVar = NULL;
+ switch( ct )
+ {
+ case SbxCLASS_VARIABLE:
+ case SbxCLASS_PROPERTY:
+ pVar = new SbxProperty( rName, dt );
+ break;
+ case SbxCLASS_METHOD:
+ pVar = new SbxMethod( rName, dt );
+ break;
+ case SbxCLASS_OBJECT:
+ pVar = CreateObject( rName );
+ break;
+ default: break;
+ }
+ pVar->SetParent( this );
+ pArray->Put( pVar, pArray->Count() );
+ SetModified( TRUE );
+ // Das Objekt lauscht immer
+ StartListening( pVar->GetBroadcaster(), TRUE );
+ Broadcast( SBX_HINT_OBJECTCHANGED );
+ return pVar;
+}
+
+SbxObject* SbxObject::MakeObject( const XubString& rName, const XubString& rClass )
+{
+ // Ist das Objekt bereits vorhanden?
+ if( !ISA(SbxCollection) )
+ {
+ SbxVariable* pRes = pObjs->Find( rName, SbxCLASS_OBJECT );
+ if( pRes )
+ {
+/* Wegen haeufiger Probleme (z.B. #67000) erstmal ganz raus
+#ifdef DBG_UTIL
+ if( pRes->GetHashCode() != nNameHash
+ && pRes->GetHashCode() != nParentHash )
+ {
+ XubString aMsg( "SBX-Objekt \"" );
+ aMsg += pRes->GetName();
+ aMsg += "\"\n in Objekt \"";
+ aMsg += GetName();
+ aMsg += "\" bereits vorhanden";
+ DbgError( (const char*)aMsg.GetStr() );
+ }
+#endif
+*/
+ return PTR_CAST(SbxObject,pRes);
+ }
+ }
+ SbxObject* pVar = CreateObject( rClass );
+ if( pVar )
+ {
+ pVar->SetName( rName );
+ pVar->SetParent( this );
+ pObjs->Put( pVar, pObjs->Count() );
+ SetModified( TRUE );
+ // Das Objekt lauscht immer
+ StartListening( pVar->GetBroadcaster(), TRUE );
+ Broadcast( SBX_HINT_OBJECTCHANGED );
+ }
+ return pVar;
+}
+
+void SbxObject::Insert( SbxVariable* pVar )
+{
+ USHORT nIdx;
+ SbxArray* pArray = FindVar( pVar, nIdx );
+ if( pArray )
+ {
+ // Hinein damit. Man sollte allerdings auf die Pointer aufpassen!
+ if( nIdx < pArray->Count() )
+ {
+ // dann gibt es dieses Element bereits
+ // Bei Collections duerfen gleichnamige Objekte hinein
+ if( pArray == pObjs && ISA(SbxCollection) )
+ nIdx = pArray->Count();
+ else
+ {
+ SbxVariable* pOld = pArray->Get( nIdx );
+ // schon drin: ueberschreiben
+ if( pOld == pVar )
+ return;
+
+/* Wegen haeufiger Probleme (z.B. #67000) erstmal ganz raus
+#ifdef DBG_UTIL
+ if( pOld->GetHashCode() != nNameHash
+ && pOld->GetHashCode() != nParentHash )
+ {
+ XubString aMsg( "SBX-Element \"" );
+ aMsg += pVar->GetName();
+ aMsg += "\"\n in Objekt \"";
+ aMsg += GetName();
+ aMsg += "\" bereits vorhanden";
+ DbgError( (const char*)aMsg.GetStr() );
+ }
+#endif
+*/
+ EndListening( pOld->GetBroadcaster(), TRUE );
+ if( pVar->GetClass() == SbxCLASS_PROPERTY )
+ {
+ if( pOld == pDfltProp )
+ pDfltProp = (SbxProperty*) pVar;
+ }
+ }
+ }
+ StartListening( pVar->GetBroadcaster(), TRUE );
+ pArray->Put( pVar, nIdx );
+ if( pVar->GetParent() != this )
+ pVar->SetParent( this );
+ SetModified( TRUE );
+ Broadcast( SBX_HINT_OBJECTCHANGED );
+#ifdef DBG_UTIL
+ static const char* pCls[] =
+ { "DontCare","Array","Value","Variable","Method","Property","Object" };
+ XubString aVarName( pVar->GetName() );
+ if ( !aVarName.Len() && pVar->ISA(SbxObject) )
+ aVarName = PTR_CAST(SbxObject,pVar)->GetClassName();
+ ByteString aNameStr1( (const UniString&)aVarName, RTL_TEXTENCODING_ASCII_US );
+ ByteString aNameStr2( (const UniString&)SbxVariable::GetName(), RTL_TEXTENCODING_ASCII_US );
+ DbgOutf( "SBX: Insert %s %s in %s",
+ ( pVar->GetClass() >= SbxCLASS_DONTCARE &&
+ pVar->GetClass() <= SbxCLASS_OBJECT )
+ ? pCls[ pVar->GetClass()-1 ] : "Unknown class", aNameStr1.GetBuffer(), aNameStr1.GetBuffer() );
+#endif
+ }
+}
+
+// AB 23.4.1997, Optimierung, Einfuegen ohne Ueberpruefung auf doppelte
+// Eintraege und ohne Broadcasts, wird nur in SO2/auto.cxx genutzt
+void SbxObject::QuickInsert( SbxVariable* pVar )
+{
+ SbxArray* pArray = NULL;
+ if( pVar )
+ {
+ switch( pVar->GetClass() )
+ {
+ case SbxCLASS_VARIABLE:
+ case SbxCLASS_PROPERTY: pArray = pProps; break;
+ case SbxCLASS_METHOD: pArray = pMethods; break;
+ case SbxCLASS_OBJECT: pArray = pObjs; break;
+ default:
+ DBG_ASSERT( !this, "Ungueltige SBX-Klasse" );
+ }
+ }
+ if( pArray )
+ {
+ StartListening( pVar->GetBroadcaster(), TRUE );
+ pArray->Put( pVar, pArray->Count() );
+ if( pVar->GetParent() != this )
+ pVar->SetParent( this );
+ SetModified( TRUE );
+#ifdef DBG_UTIL
+ static const char* pCls[] =
+ { "DontCare","Array","Value","Variable","Method","Property","Object" };
+ XubString aVarName( pVar->GetName() );
+ if ( !aVarName.Len() && pVar->ISA(SbxObject) )
+ aVarName = PTR_CAST(SbxObject,pVar)->GetClassName();
+ ByteString aNameStr1( (const UniString&)aVarName, RTL_TEXTENCODING_ASCII_US );
+ ByteString aNameStr2( (const UniString&)SbxVariable::GetName(), RTL_TEXTENCODING_ASCII_US );
+ DbgOutf( "SBX: Insert %s %s in %s",
+ ( pVar->GetClass() >= SbxCLASS_DONTCARE &&
+ pVar->GetClass() <= SbxCLASS_OBJECT )
+ ? pCls[ pVar->GetClass()-1 ] : "Unknown class", aNameStr1.GetBuffer(), aNameStr1.GetBuffer() );
+#endif
+ }
+}
+
+// AB 23.3.1997, Spezial-Methode, gleichnamige Controls zulassen
+void SbxObject::VCPtrInsert( SbxVariable* pVar )
+{
+ SbxArray* pArray = NULL;
+ if( pVar )
+ {
+ switch( pVar->GetClass() )
+ {
+ case SbxCLASS_VARIABLE:
+ case SbxCLASS_PROPERTY: pArray = pProps; break;
+ case SbxCLASS_METHOD: pArray = pMethods; break;
+ case SbxCLASS_OBJECT: pArray = pObjs; break;
+ default:
+ DBG_ASSERT( !this, "Ungueltige SBX-Klasse" );
+ }
+ }
+ if( pArray )
+ {
+ StartListening( pVar->GetBroadcaster(), TRUE );
+ pArray->Put( pVar, pArray->Count() );
+ if( pVar->GetParent() != this )
+ pVar->SetParent( this );
+ SetModified( TRUE );
+ Broadcast( SBX_HINT_OBJECTCHANGED );
+ }
+}
+
+void SbxObject::Remove( const XubString& rName, SbxClassType t )
+{
+ Remove( SbxObject::Find( rName, t ) );
+}
+
+void SbxObject::Remove( SbxVariable* pVar )
+{
+ USHORT nIdx;
+ SbxArray* pArray = FindVar( pVar, nIdx );
+ if( pArray && nIdx < pArray->Count() )
+ {
+#ifdef DBG_UTIL
+ XubString aVarName( pVar->GetName() );
+ if ( !aVarName.Len() && pVar->ISA(SbxObject) )
+ aVarName = PTR_CAST(SbxObject,pVar)->GetClassName();
+ ByteString aNameStr1( (const UniString&)aVarName, RTL_TEXTENCODING_ASCII_US );
+ ByteString aNameStr2( (const UniString&)SbxVariable::GetName(), RTL_TEXTENCODING_ASCII_US );
+#endif
+ SbxVariableRef pVar_ = pArray->Get( nIdx );
+ if( pVar_->IsBroadcaster() )
+ EndListening( pVar_->GetBroadcaster(), TRUE );
+ if( (SbxVariable*) pVar_ == pDfltProp )
+ pDfltProp = NULL;
+ pArray->Remove( nIdx );
+ if( pVar_->GetParent() == this )
+ pVar_->SetParent( NULL );
+ SetModified( TRUE );
+ Broadcast( SBX_HINT_OBJECTCHANGED );
+ }
+}
+
+// AB 23.3.1997, Loeschen per Pointer fuer Controls (doppelte Namen!)
+void SbxObject::VCPtrRemove( SbxVariable* pVar )
+{
+ USHORT nIdx;
+ // Neu FindVar-Methode, sonst identisch mit normaler Methode
+ SbxArray* pArray = VCPtrFindVar( pVar, nIdx );
+ if( pArray && nIdx < pArray->Count() )
+ {
+ SbxVariableRef xVar = pArray->Get( nIdx );
+ if( xVar->IsBroadcaster() )
+ EndListening( xVar->GetBroadcaster(), TRUE );
+ if( (SbxVariable*) xVar == pDfltProp )
+ pDfltProp = NULL;
+ pArray->Remove( nIdx );
+ if( xVar->GetParent() == this )
+ xVar->SetParent( NULL );
+ SetModified( TRUE );
+ Broadcast( SBX_HINT_OBJECTCHANGED );
+ }
+}
+
+// AB 23.3.1997, Zugehoerige Spezial-Methode, nur ueber Pointer suchen
+SbxArray* SbxObject::VCPtrFindVar( SbxVariable* pVar, USHORT& nArrayIdx )
+{
+ SbxArray* pArray = NULL;
+ if( pVar ) switch( pVar->GetClass() )
+ {
+ case SbxCLASS_VARIABLE:
+ case SbxCLASS_PROPERTY: pArray = pProps; break;
+ case SbxCLASS_METHOD: pArray = pMethods; break;
+ case SbxCLASS_OBJECT: pArray = pObjs; break;
+ default:
+ DBG_ASSERT( !this, "Ungueltige SBX-Klasse" );
+ }
+ if( pArray )
+ {
+ nArrayIdx = pArray->Count();
+ for( USHORT i = 0; i < pArray->Count(); i++ )
+ {
+ SbxVariableRef& rRef = pArray->GetRef( i );
+ if( (SbxVariable*) rRef == pVar )
+ {
+ nArrayIdx = i; break;
+ }
+ }
+ }
+ return pArray;
+}
+
+
+
+void SbxObject::SetPos( SbxVariable* pVar, USHORT nPos )
+{
+ USHORT nIdx;
+ SbxArray* pArray = FindVar( pVar, nIdx );
+ if( pArray )
+ {
+ if( nPos >= pArray->Count() )
+ nPos = pArray->Count() - 1;
+ if( nIdx < ( pArray->Count() - 1 ) )
+ {
+ SbxVariableRef refVar = pArray->Get( nIdx );
+ pArray->Remove( nIdx );
+ pArray->Insert( refVar, nPos );
+ }
+ }
+// SetModified( TRUE );
+// Broadcast( SBX_HINT_OBJECTCHANGED );
+}
+
+static BOOL LoadArray( SvStream& rStrm, SbxObject* pThis, SbxArray* pArray )
+{
+ SbxArrayRef p = (SbxArray*) SbxBase::Load( rStrm );
+ if( !p.Is() )
+ return FALSE;
+ for( USHORT i = 0; i < p->Count(); i++ )
+ {
+ SbxVariableRef& r = p->GetRef( i );
+ SbxVariable* pVar = r;
+ if( pVar )
+ {
+ pVar->SetParent( pThis );
+ pThis->StartListening( pVar->GetBroadcaster(), TRUE );
+ }
+ }
+ pArray->Merge( p );
+ return TRUE;
+}
+
+// Der Load eines Objekts ist additiv!
+
+BOOL SbxObject::LoadData( SvStream& rStrm, USHORT nVer )
+{
+ // Hilfe fuer das Einlesen alter Objekte: einfach TRUE zurueck,
+ // LoadPrivateData() muss Default-Zustand herstellen
+ if( !nVer )
+ return TRUE;
+
+ pDfltProp = NULL;
+ if( !SbxVariable::LoadData( rStrm, nVer ) )
+ return FALSE;
+ // Wenn kein fremdes Objekt enthalten ist, uns selbst eintragen
+ if( aData.eType == SbxOBJECT && !aData.pObj )
+ aData.pObj = this;
+ sal_uInt32 nSize;
+ XubString aDfltProp;
+ rStrm.ReadByteString( aClassName, RTL_TEXTENCODING_ASCII_US );
+ rStrm.ReadByteString( aDfltProp, RTL_TEXTENCODING_ASCII_US );
+ ULONG nPos = rStrm.Tell();
+ rStrm >> nSize;
+ if( !LoadPrivateData( rStrm, nVer ) )
+ return FALSE;
+ ULONG nNewPos = rStrm.Tell();
+ nPos += nSize;
+ DBG_ASSERT( nPos >= nNewPos, "SBX: Zu viele Daten eingelesen" );
+ if( nPos != nNewPos )
+ rStrm.Seek( nPos );
+ if( !LoadArray( rStrm, this, pMethods )
+ || !LoadArray( rStrm, this, pProps )
+ || !LoadArray( rStrm, this, pObjs ) )
+ return FALSE;
+ // Properties setzen
+ if( aDfltProp.Len() )
+ pDfltProp = (SbxProperty*) pProps->Find( aDfltProp, SbxCLASS_PROPERTY );
+ SetModified( FALSE );
+ return TRUE;
+}
+
+BOOL SbxObject::StoreData( SvStream& rStrm ) const
+{
+ if( !SbxVariable::StoreData( rStrm ) )
+ return FALSE;
+ XubString aDfltProp;
+ if( pDfltProp )
+ aDfltProp = pDfltProp->GetName();
+ rStrm.WriteByteString( aClassName, RTL_TEXTENCODING_ASCII_US );
+ rStrm.WriteByteString( aDfltProp, RTL_TEXTENCODING_ASCII_US );
+ ULONG nPos = rStrm.Tell();
+ rStrm << (UINT32) 0L;
+ if( !StorePrivateData( rStrm ) )
+ return FALSE;
+ ULONG nNew = rStrm.Tell();
+ rStrm.Seek( nPos );
+ rStrm << (UINT32) ( nNew - nPos );
+ rStrm.Seek( nNew );
+ if( !pMethods->Store( rStrm ) )
+ return FALSE;
+ if( !pProps->Store( rStrm ) )
+ return FALSE;
+ if( !pObjs->Store( rStrm ) )
+ return FALSE;
+ ((SbxObject*) this)->SetModified( FALSE );
+ return TRUE;
+}
+
+XubString SbxObject::GenerateSource( const XubString &rLinePrefix,
+ const SbxObject* )
+{
+ // Properties in einem String einsammeln
+ XubString aSource;
+ SbxArrayRef xProps( GetProperties() );
+ bool bLineFeed = false;
+ for ( USHORT nProp = 0; nProp < xProps->Count(); ++nProp )
+ {
+ SbxPropertyRef xProp = (SbxProperty*) xProps->Get(nProp);
+ XubString aPropName( xProp->GetName() );
+ if ( xProp->CanWrite()
+ && !( xProp->GetHashCode() == nNameHash
+ && aPropName.EqualsIgnoreCaseAscii( pNameProp ) ) )
+ {
+ // ausser vor dem ersten Property immer einen Umbruch einfuegen
+ if ( bLineFeed )
+ aSource.AppendAscii( "\n" );
+ else
+ bLineFeed = true;
+
+ aSource += rLinePrefix;
+ aSource += '.';
+ aSource += aPropName;
+ aSource.AppendAscii( " = " );
+
+ // den Property-Wert textuell darstellen
+ switch ( xProp->GetType() )
+ {
+ case SbxEMPTY:
+ case SbxNULL:
+ // kein Wert
+ break;
+
+ case SbxSTRING:
+ {
+ // Strings in Anf"uhrungszeichen
+ aSource.AppendAscii( "\"" );
+ aSource += xProp->GetString();
+ aSource.AppendAscii( "\"" );
+ break;
+ }
+
+ default:
+ {
+ // sonstiges wie z.B. Zahlen direkt
+ aSource += xProp->GetString();
+ break;
+ }
+ }
+ }
+ }
+ return aSource;
+}
+
+static BOOL CollectAttrs( const SbxBase* p, XubString& rRes )
+{
+ XubString aAttrs;
+ if( p->IsHidden() )
+ aAttrs.AssignAscii( "Hidden" );
+ if( p->IsSet( SBX_EXTSEARCH ) )
+ {
+ if( aAttrs.Len() )
+ aAttrs += ',';
+ aAttrs.AppendAscii( "ExtSearch" );
+ }
+ if( !p->IsVisible() )
+ {
+ if( aAttrs.Len() )
+ aAttrs += ',';
+ aAttrs.AppendAscii( "Invisible" );
+ }
+ if( p->IsSet( SBX_DONTSTORE ) )
+ {
+ if( aAttrs.Len() )
+ aAttrs += ',';
+ aAttrs.AppendAscii( "DontStore" );
+ }
+ if( aAttrs.Len() )
+ {
+ rRes.AssignAscii( " (" );
+ rRes += aAttrs;
+ rRes += ')';
+ return TRUE;
+ }
+ else
+ {
+ rRes.Erase();
+ return FALSE;
+ }
+}
+
+void SbxObject::Dump( SvStream& rStrm, BOOL bFill )
+{
+ // Einr"uckung
+ static USHORT nLevel = 0;
+ if ( nLevel > 10 )
+ {
+ rStrm << "<too deep>" << endl;
+ return;
+ }
+ ++nLevel;
+ String aIndent;
+ for ( USHORT n = 1; n < nLevel; ++n )
+ aIndent.AppendAscii( " " );
+
+ // ggf. Objekt vervollst"andigen
+ if ( bFill )
+ GetAll( SbxCLASS_DONTCARE );
+
+ // Daten des Objekts selbst ausgeben
+ ByteString aNameStr( (const UniString&)GetName(), RTL_TEXTENCODING_ASCII_US );
+ ByteString aClassNameStr( (const UniString&)aClassName, RTL_TEXTENCODING_ASCII_US );
+ rStrm << "Object( "
+ << ByteString::CreateFromInt64( (ULONG) this ).GetBuffer() << "=='"
+ << ( aNameStr.Len() ? aNameStr.GetBuffer() : "<unnamed>" ) << "', "
+ << "of class '" << aClassNameStr.GetBuffer() << "', "
+ << "counts "
+ << ByteString::CreateFromInt64( GetRefCount() ).GetBuffer()
+ << " refs, ";
+ if ( GetParent() )
+ {
+ ByteString aParentNameStr( (const UniString&)GetName(), RTL_TEXTENCODING_ASCII_US );
+ rStrm << "in parent "
+ << ByteString::CreateFromInt64( (ULONG) GetParent() ).GetBuffer()
+ << "=='" << ( aParentNameStr.Len() ? aParentNameStr.GetBuffer() : "<unnamed>" ) << "'";
+ }
+ else
+ rStrm << "no parent ";
+ rStrm << " )" << endl;
+ ByteString aIndentNameStr( (const UniString&)aIndent, RTL_TEXTENCODING_ASCII_US );
+ rStrm << aIndentNameStr.GetBuffer() << "{" << endl;
+
+ // Flags
+ XubString aAttrs;
+ if( CollectAttrs( this, aAttrs ) )
+ {
+ ByteString aAttrStr( (const UniString&)aAttrs, RTL_TEXTENCODING_ASCII_US );
+ rStrm << aIndentNameStr.GetBuffer() << "- Flags: " << aAttrStr.GetBuffer() << endl;
+ }
+
+ // Methods
+ rStrm << aIndentNameStr.GetBuffer() << "- Methods:" << endl;
+ for( USHORT i = 0; i < pMethods->Count(); i++ )
+ {
+ SbxVariableRef& r = pMethods->GetRef( i );
+ SbxVariable* pVar = r;
+ if( pVar )
+ {
+ XubString aLine( aIndent );
+ aLine.AppendAscii( " - " );
+ aLine += pVar->GetName( SbxNAME_SHORT_TYPES );
+ XubString aAttrs2;
+ if( CollectAttrs( pVar, aAttrs2 ) )
+ aLine += aAttrs2;
+ if( !pVar->IsA( TYPE(SbxMethod) ) )
+ aLine.AppendAscii( " !! Not a Method !!" );
+ rStrm.WriteByteString( aLine, RTL_TEXTENCODING_ASCII_US );
+
+ // bei Object-Methods auch das Object ausgeben
+ if ( pVar->GetValues_Impl().eType == SbxOBJECT &&
+ pVar->GetValues_Impl().pObj &&
+ pVar->GetValues_Impl().pObj != this &&
+ pVar->GetValues_Impl().pObj != GetParent() )
+ {
+ rStrm << " contains ";
+ ((SbxObject*) pVar->GetValues_Impl().pObj)->Dump( rStrm, bFill );
+ }
+ else
+ rStrm << endl;
+ }
+ }
+
+ // Properties
+ rStrm << aIndentNameStr.GetBuffer() << "- Properties:" << endl;
+ {
+ for( USHORT i = 0; i < pProps->Count(); i++ )
+ {
+ SbxVariableRef& r = pProps->GetRef( i );
+ SbxVariable* pVar = r;
+ if( pVar )
+ {
+ XubString aLine( aIndent );
+ aLine.AppendAscii( " - " );
+ aLine += pVar->GetName( SbxNAME_SHORT_TYPES );
+ XubString aAttrs3;
+ if( CollectAttrs( pVar, aAttrs3 ) )
+ aLine += aAttrs3;
+ if( !pVar->IsA( TYPE(SbxProperty) ) )
+ aLine.AppendAscii( " !! Not a Property !!" );
+ rStrm.WriteByteString( aLine, RTL_TEXTENCODING_ASCII_US );
+
+ // bei Object-Properties auch das Object ausgeben
+ if ( pVar->GetValues_Impl().eType == SbxOBJECT &&
+ pVar->GetValues_Impl().pObj &&
+ pVar->GetValues_Impl().pObj != this &&
+ pVar->GetValues_Impl().pObj != GetParent() )
+ {
+ rStrm << " contains ";
+ ((SbxObject*) pVar->GetValues_Impl().pObj)->Dump( rStrm, bFill );
+ }
+ else
+ rStrm << endl;
+ }
+ }
+ }
+
+ // Objects
+ rStrm << aIndentNameStr.GetBuffer() << "- Objects:" << endl;
+ {
+ for( USHORT i = 0; i < pObjs->Count(); i++ )
+ {
+ SbxVariableRef& r = pObjs->GetRef( i );
+ SbxVariable* pVar = r;
+ if ( pVar )
+ {
+ rStrm << aIndentNameStr.GetBuffer() << " - Sub";
+ if ( pVar->ISA(SbxObject) )
+ ((SbxObject*) pVar)->Dump( rStrm, bFill );
+ else if ( pVar->ISA(SbxVariable) )
+ ((SbxVariable*) pVar)->Dump( rStrm, bFill );
+ }
+ }
+ }
+
+ rStrm << aIndentNameStr.GetBuffer() << "}" << endl << endl;
+ --nLevel;
+}
+
+SvDispatch* SbxObject::GetSvDispatch()
+{
+ return NULL;
+}
+
+BOOL SbxMethod::Run( SbxValues* pValues )
+{
+ SbxValues aRes;
+ if( !pValues )
+ pValues = &aRes;
+ pValues->eType = SbxVARIANT;
+ return Get( *pValues );
+}
+
+SbxClassType SbxMethod::GetClass() const
+{
+ return SbxCLASS_METHOD;
+}
+
+SbxClassType SbxProperty::GetClass() const
+{
+ return SbxCLASS_PROPERTY;
+}
+
+void SbxObject::GarbageCollection( ULONG /*nObjects*/ )
+
+/* [Beschreibung]
+
+ Diese statische Methode durchsucht die n"achsten 'nObjects' der zur Zeit
+ existierenden <SbxObject>-Instanzen nach zyklischen Referenzen, die sich
+ nur noch selbst am Leben erhalten. Ist 'nObjects==0', dann werden
+ alle existierenden durchsucht.
+
+ zur Zeit nur implementiert: Object -> Parent-Property -> Parent -> Object
+*/
+
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxres.cxx b/basic/source/sbx/sbxres.cxx
new file mode 100644
index 000000000000..612911aaad04
--- /dev/null
+++ b/basic/source/sbx/sbxres.cxx
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+
+#include "sbxres.hxx"
+
+static const char* pSbxRes[] = {
+ "Empty",
+ "Null",
+ "Integer",
+ "Long",
+ "Single",
+ "Double",
+ "Currency",
+ "Date",
+ "String",
+ "Object",
+ "Error",
+ "Boolean",
+ "Variant",
+ "Any",
+ "Type14",
+ "Type15",
+ "Char",
+ "Byte",
+ "UShort",
+ "ULong",
+ "Long64",
+ "ULong64",
+ "Int",
+ "UInt",
+ "Void",
+ "HResult",
+ "Pointer",
+ "DimArray",
+ "CArray",
+ "Any",
+ "LpStr",
+ "LpWStr",
+ " As ",
+ "Optional ",
+ "Byref ",
+
+ "Name",
+ "Parent",
+ "Application",
+ "Count",
+ "Add",
+ "Item",
+ "Remove",
+
+ "Error ", // with blank!
+ "False",
+ "True"
+};
+
+const char* GetSbxRes( USHORT nId )
+{
+ return ( ( nId > SBXRES_MAX ) ? "???" : pSbxRes[ nId ] );
+}
+
+SbxRes::SbxRes( USHORT nId )
+ : ::rtl::OUString( ::rtl::OUString::createFromAscii( GetSbxRes( nId ) ) )
+{}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxres.hxx b/basic/source/sbx/sbxres.hxx
new file mode 100644
index 000000000000..eb2e20266503
--- /dev/null
+++ b/basic/source/sbx/sbxres.hxx
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _SBXRES_HXX
+#define _SBXRES_HXX
+
+#include <tools/string.hxx>
+
+// Currently there are no resources provided in the SVTOOLS-Project.
+// Because it is non-critical resources (BASIC-Keywords),
+// we can work with dummies.
+
+#define STRING_TYPES 0
+#define STRING_EMPTY 0
+#define STRING_NULL 1
+#define STRING_INTEGER 2
+#define STRING_LONG 3
+#define STRING_SINGLE 4
+#define STRING_DOUBLE 5
+#define STRING_CURRENCY 6
+#define STRING_DATE 7
+#define STRING_STRING 8
+#define STRING_OBJECT 9
+#define STRING_ERROR 10
+#define STRING_BOOL 11
+#define STRING_VARIANT 12
+#define STRING_ANY 13
+#define STRING_CHAR 16
+#define STRING_BYTE 17
+#define STRING_USHORT 18
+#define STRING_ULONG 19
+#define STRING_INT 22
+#define STRING_UINT 23
+#define STRING_LPSTR 30
+#define STRING_LPWSTR 31
+#define STRING_AS 32
+#define STRING_OPTIONAL 33
+#define STRING_BYREF 34
+
+#define STRING_NAMEPROP 35
+#define STRING_PARENTPROP 36
+#define STRING_APPLPROP 37
+#define STRING_COUNTPROP 38
+#define STRING_ADDMETH 39
+#define STRING_ITEMMETH 40
+#define STRING_REMOVEMETH 41
+
+#define STRING_ERRORMSG 42
+#define STRING_FALSE 43
+#define STRING_TRUE 44
+
+#define SBXRES_MAX 44
+
+class SbxRes : public ::rtl::OUString
+{
+public:
+ SbxRes( USHORT );
+};
+
+const char* GetSbxRes( USHORT );
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxscan.cxx b/basic/source/sbx/sbxscan.cxx
new file mode 100644
index 000000000000..aeff9a4108e7
--- /dev/null
+++ b/basic/source/sbx/sbxscan.cxx
@@ -0,0 +1,968 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+#include <tools/errcode.hxx>
+#include <basic/sbx.hxx>
+#include "sbxconv.hxx"
+
+#include "unotools/syslocale.hxx"
+
+#if defined ( UNX )
+#include <stdlib.h>
+#endif
+
+#include <vcl/svapp.hxx>
+#include <math.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "sbxres.hxx"
+#include <basic/sbxbase.hxx>
+#include <basic/sbxform.hxx>
+#include <svtools/svtools.hrc>
+
+#include "basrid.hxx"
+#include "runtime.hxx"
+
+#include <svl/zforlist.hxx>
+#include <comphelper/processfactory.hxx>
+
+
+void ImpGetIntntlSep( sal_Unicode& rcDecimalSep, sal_Unicode& rcThousandSep )
+{
+ SvtSysLocale aSysLocale;
+ const LocaleDataWrapper& rData = aSysLocale.GetLocaleData();
+ rcDecimalSep = rData.getNumDecimalSep().GetBuffer()[0];
+ rcThousandSep = rData.getNumThousandSep().GetBuffer()[0];
+}
+
+// Scannen eines Strings nach BASIC-Konventionen
+// Dies entspricht den ueblichen Konventionen, nur dass der Exponent
+// auch ein D sein darf, was den Datentyp auf SbxDOUBLE festlegt.
+// Die Routine versucht, den Datentyp so klein wie moeglich zu gestalten.
+// Das ganze gibt auch noch einen Konversionsfehler, wenn der Datentyp
+// Fixed ist und das ganze nicht hineinpasst!
+
+SbxError ImpScan( const ::rtl::OUString& rWSrc, double& nVal, SbxDataType& rType,
+ USHORT* pLen, BOOL bAllowIntntl, BOOL bOnlyIntntl )
+{
+ ::rtl::OString aBStr( ::rtl::OUStringToOString( rWSrc, RTL_TEXTENCODING_ASCII_US ) );
+
+ // Bei International Komma besorgen
+ char cIntntlComma, cIntntl1000;
+ char cNonIntntlComma = '.';
+
+ sal_Unicode cDecimalSep, cThousandSep = 0;
+ if( bAllowIntntl || bOnlyIntntl )
+ {
+ ImpGetIntntlSep( cDecimalSep, cThousandSep );
+ cIntntlComma = (char)cDecimalSep;
+ cIntntl1000 = (char)cThousandSep;
+ }
+ // Sonst einfach auch auf . setzen
+ else
+ {
+ cIntntlComma = cNonIntntlComma;
+ cIntntl1000 = cNonIntntlComma; // Unschaedlich machen
+ }
+ // Nur International -> IntnlComma uebernehmen
+ if( bOnlyIntntl )
+ {
+ cNonIntntlComma = cIntntlComma;
+ cIntntl1000 = (char)cThousandSep;
+ }
+
+ const char* pStart = aBStr.getStr();
+ const char* p = pStart;
+ char buf[ 80 ], *q = buf;
+ BOOL bRes = TRUE;
+ BOOL bMinus = FALSE;
+ nVal = 0;
+ SbxDataType eScanType = SbxSINGLE;
+ // Whitespace wech
+ while( *p &&( *p == ' ' || *p == '\t' ) ) p++;
+ // Zahl? Dann einlesen und konvertieren.
+ if( *p == '-' )
+ p++, bMinus = TRUE;
+ if( isdigit( *p ) ||( (*p == cNonIntntlComma || *p == cIntntlComma ||
+ *p == cIntntl1000) && isdigit( *(p+1 ) ) ) )
+ {
+ short exp = 0; // >0: Exponentteil
+ short comma = 0; // >0: Nachkomma
+ short ndig = 0; // Anzahl Ziffern
+ short ncdig = 0; // Anzahl Ziffern nach Komma
+ ByteString aSearchStr( "0123456789DEde" );
+ // Kommas ergaenzen
+ aSearchStr += cNonIntntlComma;
+ if( cIntntlComma != cNonIntntlComma )
+ aSearchStr += cIntntlComma;
+ if( bOnlyIntntl )
+ aSearchStr += cIntntl1000;
+ const char* pSearchStr = aSearchStr.GetBuffer();
+ while( strchr( pSearchStr, *p ) && *p )
+ {
+ // 1000er-Trenner ueberlesen
+ if( bOnlyIntntl && *p == cIntntl1000 )
+ {
+ p++;
+ continue;
+ }
+
+ // Komma oder Exponent?
+ if( *p == cNonIntntlComma || *p == cIntntlComma )
+ {
+ // Immer '.' einfuegen, damit atof funktioniert
+ p++;
+ if( ++comma > 1 )
+ continue;
+ else
+ *q++ = '.';
+ }
+ else if( strchr( "DdEe", *p ) )
+ {
+ if( ++exp > 1 )
+ {
+ p++; continue;
+ }
+ if( toupper( *p ) == 'D' )
+ eScanType = SbxDOUBLE;
+ *q++ = 'E'; p++;
+ // Vorzeichen hinter Exponent?
+ if( *p == '+' )
+ p++;
+ else
+ if( *p == '-' )
+ *q++ = *p++;
+ }
+ else
+ {
+ *q++ = *p++;
+ if( comma && !exp ) ncdig++;
+ }
+ if( !exp ) ndig++;
+ }
+ *q = 0;
+ // Komma, Exponent mehrfach vorhanden?
+ if( comma > 1 || exp > 1 )
+ bRes = FALSE;
+ // Kann auf Integer gefaltet werden?
+ if( !comma && !exp )
+ {
+ if( nVal >= SbxMININT && nVal <= SbxMAXINT )
+ eScanType = SbxINTEGER;
+ else if( nVal >= SbxMINLNG && nVal <= SbxMAXLNG )
+ eScanType = SbxLONG;
+ }
+
+ nVal = atof( buf );
+ ndig = ndig - comma;
+ // zu viele Zahlen fuer SINGLE?
+ if( ndig > 15 || ncdig > 6 )
+ eScanType = SbxDOUBLE;
+
+ // Typkennung?
+ if( strchr( "%!&#", *p ) && *p ) p++;
+ }
+ // Hex/Oktalzahl? Einlesen und konvertieren:
+ else if( *p == '&' )
+ {
+ p++;
+ eScanType = SbxLONG;
+ const char *cmp = "0123456789ABCDEF";
+ char base = 16;
+ char ndig = 8;
+ char xch = *p++;
+ switch( toupper( xch ) )
+ {
+ case 'O': cmp = "01234567"; base = 8; ndig = 11; break;
+ case 'H': break;
+ default : bRes = FALSE;
+ }
+ long l = 0;
+ int i;
+ while( isalnum( *p ) )
+ {
+ char ch = sal::static_int_cast< char >( toupper( *p ) );
+ p++;
+ if( strchr( cmp, ch ) ) *q++ = ch;
+ else bRes = FALSE;
+ }
+ *q = 0;
+ for( q = buf; *q; q++ )
+ {
+ i =( *q & 0xFF ) - '0';
+ if( i > 9 ) i -= 7;
+ l =( l * base ) + i;
+ if( !ndig-- )
+ bRes = FALSE;
+ }
+ if( *p == '&' ) p++;
+ nVal = (double) l;
+ if( l >= SbxMININT && l <= SbxMAXINT )
+ eScanType = SbxINTEGER;
+ }
+ else if ( SbiRuntime::isVBAEnabled() )
+ {
+ OSL_TRACE("Reporting error converting");
+ return SbxERR_CONVERSION;
+ }
+ if( pLen )
+ *pLen = (USHORT) ( p - pStart );
+ if( !bRes )
+ return SbxERR_CONVERSION;
+ if( bMinus )
+ nVal = -nVal;
+ rType = eScanType;
+ return SbxERR_OK;
+}
+
+// Schnittstelle fuer CDbl im Basic
+SbxError SbxValue::ScanNumIntnl( const String& rSrc, double& nVal, BOOL bSingle )
+{
+ SbxDataType t;
+ USHORT nLen = 0;
+ SbxError nRetError = ImpScan( rSrc, nVal, t, &nLen,
+ /*bAllowIntntl*/FALSE, /*bOnlyIntntl*/TRUE );
+ // Komplett gelesen?
+ if( nRetError == SbxERR_OK && nLen != rSrc.Len() )
+ nRetError = SbxERR_CONVERSION;
+
+ if( bSingle )
+ {
+ SbxValues aValues( nVal );
+ nVal = (double)ImpGetSingle( &aValues ); // Hier Error bei Overflow
+ }
+ return nRetError;
+}
+
+////////////////////////////////////////////////////////////////////////////
+
+static double roundArray[] = {
+ 5.0e+0, 0.5e+0, 0.5e-1, 0.5e-2, 0.5e-3, 0.5e-4, 0.5e-5, 0.5e-6, 0.5e-7,
+ 0.5e-8, 0.5e-9, 0.5e-10,0.5e-11,0.5e-12,0.5e-13,0.5e-14,0.5e-15 };
+
+/***************************************************************************
+|*
+|* void myftoa( double, char *, short, short, BOOL, BOOL )
+|*
+|* Beschreibung: Konversion double --> ASCII
+|* Parameter: double die Zahl.
+|* char * der Zielpuffer
+|* short Anzahl Nachkommastellen
+|* short Weite des Exponenten( 0=kein E )
+|* BOOL TRUE: mit 1000er Punkten
+|* BOOL TRUE: formatfreie Ausgabe
+|*
+***************************************************************************/
+
+static void myftoa( double nNum, char * pBuf, short nPrec, short nExpWidth,
+ BOOL bPt, BOOL bFix, sal_Unicode cForceThousandSep = 0 )
+{
+
+ short nExp = 0; // Exponent
+ short nDig = nPrec + 1; // Anzahl Digits in Zahl
+ short nDec; // Anzahl Vorkommastellen
+ register int i, digit;
+
+ // Komma besorgen
+ sal_Unicode cDecimalSep, cThousandSep;
+ ImpGetIntntlSep( cDecimalSep, cThousandSep );
+ if( cForceThousandSep )
+ cThousandSep = cForceThousandSep;
+
+ // Exponentberechnung:
+ nExp = 0;
+ if( nNum > 0.0 )
+ {
+ while( nNum < 1.0 ) nNum *= 10.0, nExp--;
+ while( nNum >= 10.0 ) nNum /= 10.0, nExp++;
+ }
+ if( !bFix && !nExpWidth )
+ nDig = nDig + nExp;
+ else if( bFix && !nPrec )
+ nDig = nExp + 1;
+
+ // Zahl runden:
+ if( (nNum += roundArray [( nDig > 16 ) ? 16 : nDig] ) >= 10.0 )
+ {
+ nNum = 1.0;
+ ++nExp;
+ if( !nExpWidth ) ++nDig;
+ }
+
+ // Bestimmung der Vorkommastellen:
+ if( !nExpWidth )
+ {
+ if( nExp < 0 )
+ {
+ // #41691: Auch bei bFix eine 0 spendieren
+ *pBuf++ = '0';
+ if( nPrec ) *pBuf++ = (char)cDecimalSep;
+ i = -nExp - 1;
+ if( nDig <= 0 ) i = nPrec;
+ while( i-- ) *pBuf++ = '0';
+ nDec = 0;
+ }
+ else
+ nDec = nExp+1;
+ }
+ else
+ nDec = 1;
+
+ // Zahl ausgeben:
+ if( nDig > 0 )
+ {
+ for( i = 0 ; ; ++i )
+ {
+ if( i < 16 )
+ {
+ digit = (int) nNum;
+ *pBuf++ = sal::static_int_cast< char >(digit + '0');
+ nNum =( nNum - digit ) * 10.0;
+ } else
+ *pBuf++ = '0';
+ if( --nDig == 0 ) break;
+ if( nDec )
+ {
+ nDec--;
+ if( !nDec )
+ *pBuf++ = (char)cDecimalSep;
+ else if( !(nDec % 3 ) && bPt )
+ *pBuf++ = (char)cThousandSep;
+ }
+ }
+ }
+
+ // Exponent ausgeben:
+ if( nExpWidth )
+ {
+ if( nExpWidth < 3 ) nExpWidth = 3;
+ nExpWidth -= 2;
+ *pBuf++ = 'E';
+ *pBuf++ =( nExp < 0 ) ?( (nExp = -nExp ), '-' ) : '+';
+ while( nExpWidth > 3 ) *pBuf++ = '0', nExpWidth--;
+ if( nExp >= 100 || nExpWidth == 3 )
+ {
+ *pBuf++ = sal::static_int_cast< char >(nExp/100 + '0');
+ nExp %= 100;
+ }
+ if( nExp/10 || nExpWidth >= 2 )
+ *pBuf++ = sal::static_int_cast< char >(nExp/10 + '0');
+ *pBuf++ = sal::static_int_cast< char >(nExp%10 + '0');
+ }
+ *pBuf = 0;
+}
+
+// Die Zahl wird unformatiert mit der angegebenen Anzahl NK-Stellen
+// aufbereitet. Evtl. wird ein Minus vorangestellt.
+// Diese Routine ist public, weil sie auch von den Put-Funktionen
+// der Klasse SbxImpSTRING verwendet wird.
+
+#ifdef _MSC_VER
+#pragma optimize( "", off )
+#pragma warning(disable: 4748) // "... because optimizations are disabled ..."
+#endif
+
+void ImpCvtNum( double nNum, short nPrec, ::rtl::OUString& rRes, BOOL bCoreString )
+{
+ char *q;
+ char cBuf[ 40 ], *p = cBuf;
+
+ sal_Unicode cDecimalSep, cThousandSep;
+ ImpGetIntntlSep( cDecimalSep, cThousandSep );
+ if( bCoreString )
+ cDecimalSep = '.';
+
+ if( nNum < 0.0 ) {
+ nNum = -nNum;
+ *p++ = '-';
+ }
+ double dMaxNumWithoutExp = (nPrec == 6) ? 1E6 : 1E14;
+ myftoa( nNum, p, nPrec,( nNum &&( nNum < 1E-1 || nNum >= dMaxNumWithoutExp ) ) ? 4:0,
+ FALSE, TRUE, cDecimalSep );
+ // Trailing Zeroes weg:
+ for( p = cBuf; *p &&( *p != 'E' ); p++ ) {}
+ q = p; p--;
+ while( nPrec && *p == '0' ) nPrec--, p--;
+ if( *p == cDecimalSep ) p--;
+ while( *q ) *++p = *q++;
+ *++p = 0;
+ rRes = ::rtl::OUString::createFromAscii( cBuf );
+}
+
+#ifdef _MSC_VER
+#pragma optimize( "", on )
+#endif
+
+BOOL ImpConvStringExt( ::rtl::OUString& rSrc, SbxDataType eTargetType )
+{
+ // Merken, ob ueberhaupt was geaendert wurde
+ BOOL bChanged = FALSE;
+ ::rtl::OUString aNewString;
+
+ // Nur Spezial-Fälle behandeln, als Default tun wir nichts
+ switch( eTargetType )
+ {
+ // Bei Fliesskomma International beruecksichtigen
+ case SbxSINGLE:
+ case SbxDOUBLE:
+ case SbxCURRENCY:
+ {
+ ::rtl::OString aBStr( ::rtl::OUStringToOString( rSrc, RTL_TEXTENCODING_ASCII_US ) );
+
+ // Komma besorgen
+ sal_Unicode cDecimalSep, cThousandSep;
+ ImpGetIntntlSep( cDecimalSep, cThousandSep );
+ aNewString = rSrc;
+
+ // Ersetzen, wenn DecimalSep kein '.' (nur den ersten)
+ if( cDecimalSep != (sal_Unicode)'.' )
+ {
+ sal_Int32 nPos = aNewString.indexOf( cDecimalSep );
+ if( nPos != -1 )
+ {
+ sal_Unicode* pStr = (sal_Unicode*)aNewString.getStr();
+ pStr[nPos] = (sal_Unicode)'.';
+ bChanged = TRUE;
+ }
+ }
+ break;
+ }
+
+ // Bei BOOL TRUE und FALSE als String pruefen
+ case SbxBOOL:
+ {
+ if( rSrc.equalsIgnoreAsciiCaseAscii( "true" ) )
+ {
+ aNewString = ::rtl::OUString::valueOf( (sal_Int32)SbxTRUE );
+ bChanged = TRUE;
+ }
+ else
+ if( rSrc.equalsIgnoreAsciiCaseAscii( "false" ) )
+ {
+ aNewString = ::rtl::OUString::valueOf( (sal_Int32)SbxFALSE );
+ bChanged = TRUE;
+ }
+ break;
+ }
+ default: break;
+ }
+ // String bei Aenderung uebernehmen
+ if( bChanged )
+ rSrc = aNewString;
+ return bChanged;
+}
+
+
+// Formatierte Zahlenausgabe
+// Der Returnwert ist die Anzahl Zeichen, die aus dem
+// Format verwendt wurden.
+
+#ifdef _old_format_code_
+// lasse diesen Code vorl"aufig drin, zum 'abgucken'
+// der bisherigen Implementation
+
+static USHORT printfmtnum( double nNum, XubString& rRes, const XubString& rWFmt )
+{
+ const String& rFmt = rWFmt;
+ char cFill = ' '; // Fuellzeichen
+ char cPre = 0; // Startzeichen( evtl. "$" )
+ short nExpDig= 0; // Anzahl Exponentstellen
+ short nPrec = 0; // Anzahl Nachkommastellen
+ short nWidth = 0; // Zahlenweite gesamnt
+ short nLen; // Laenge konvertierte Zahl
+ BOOL bPoint = FALSE; // TRUE: mit 1000er Kommas
+ BOOL bTrail = FALSE; // TRUE, wenn folgendes Minus
+ BOOL bSign = FALSE; // TRUE: immer mit Vorzeichen
+ BOOL bNeg = FALSE; // TRUE: Zahl ist negativ
+ char cBuf [1024]; // Zahlenpuffer
+ char * p;
+ const char* pFmt = rFmt;
+ rRes.Erase();
+ // $$ und ** abfangen. Einfach wird als Zeichen ausgegeben.
+ if( *pFmt == '$' )
+ if( *++pFmt != '$' ) rRes += '$';
+ if( *pFmt == '*' )
+ if( *++pFmt != '*' ) rRes += '*';
+
+ switch( *pFmt++ )
+ {
+ case 0:
+ break;
+ case '+':
+ bSign = TRUE; nWidth++; break;
+ case '*':
+ nWidth++; cFill = '*';
+ if( *pFmt == '$' ) nWidth++, pFmt++, cPre = '$';
+ break;
+ case '$':
+ nWidth++; cPre = '$'; break;
+ case '#':
+ case '.':
+ case ',':
+ pFmt--; break;
+ }
+ // Vorkomma:
+ for( ;; )
+ {
+ while( *pFmt == '#' ) pFmt++, nWidth++;
+ // 1000er Kommas?
+ if( *pFmt == ',' )
+ {
+ nWidth++; pFmt++; bPoint = TRUE;
+ } else break;
+ }
+ // Nachkomma:
+ if( *pFmt == '.' )
+ {
+ while( *++pFmt == '#' ) nPrec++;
+ nWidth += nPrec + 1;
+ }
+ // Exponent:
+ while( *pFmt == '^' )
+ pFmt++, nExpDig++, nWidth++;
+ // Folgendes Minus:
+ if( !bSign && *pFmt == '-' )
+ pFmt++, bTrail = TRUE;
+
+ // Zahl konvertieren:
+ if( nPrec > 15 ) nPrec = 15;
+ if( nNum < 0.0 ) nNum = -nNum, bNeg = TRUE;
+ p = cBuf;
+ if( bSign ) *p++ = bNeg ? '-' : '+';
+ myftoa( nNum, p, nPrec, nExpDig, bPoint, FALSE );
+ nLen = strlen( cBuf );
+
+ // Ueberlauf?
+ if( cPre ) nLen++;
+ if( nLen > nWidth ) rRes += '%';
+ else {
+ nWidth -= nLen;
+ while( nWidth-- ) rRes += (xub_Unicode)cFill;
+ if( cPre ) rRes += (xub_Unicode)cPre;
+ }
+ rRes += (xub_Unicode*)&(cBuf[0]);
+ if( bTrail )
+ rRes += bNeg ? '-' : ' ';
+
+ return (USHORT) ( pFmt - (const char*) rFmt );
+}
+
+#endif //_old_format_code_
+
+static USHORT printfmtstr( const XubString& rStr, XubString& rRes, const XubString& rFmt )
+{
+ const xub_Unicode* pStr = rStr.GetBuffer();
+ const xub_Unicode* pFmtStart = rFmt.GetBuffer();
+ const xub_Unicode* pFmt = pFmtStart;
+ rRes.Erase();
+ switch( *pFmt )
+ {
+ case '!':
+ rRes += *pStr++; pFmt++; break;
+ case '\\':
+ do
+ {
+ rRes += *pStr ? *pStr++ : static_cast< xub_Unicode >(' ');
+ pFmt++;
+ } while( *pFmt != '\\' );
+ rRes += *pStr ? *pStr++ : static_cast< xub_Unicode >(' ');
+ pFmt++; break;
+ case '&':
+ rRes = rStr;
+ pFmt++; break;
+ default:
+ rRes = rStr;
+ break;
+ }
+ return (USHORT) ( pFmt - pFmtStart );
+}
+
+/////////////////////////////////////////////////////////////////////////
+
+BOOL SbxValue::Scan( const XubString& rSrc, USHORT* pLen )
+{
+ SbxError eRes = SbxERR_OK;
+ if( !CanWrite() )
+ eRes = SbxERR_PROP_READONLY;
+ else
+ {
+ double n;
+ SbxDataType t;
+ eRes = ImpScan( rSrc, n, t, pLen );
+ if( eRes == SbxERR_OK )
+ {
+ if( !IsFixed() )
+ SetType( t );
+ PutDouble( n );
+ }
+ }
+ if( eRes )
+ {
+ SetError( eRes ); return FALSE;
+ }
+ else
+ return TRUE;
+}
+
+
+ResMgr* implGetResMgr( void )
+{
+ static ResMgr* pResMgr = NULL;
+ if( !pResMgr )
+ {
+ ::com::sun::star::lang::Locale aLocale = Application::GetSettings().GetUILocale();
+ pResMgr = ResMgr::CreateResMgr(CREATEVERSIONRESMGR_NAME(sb), aLocale );
+ }
+ return pResMgr;
+}
+
+class SbxValueFormatResId : public ResId
+{
+public:
+ SbxValueFormatResId( USHORT nId )
+ : ResId( nId, *implGetResMgr() )
+ {}
+};
+
+
+enum VbaFormatType
+{
+ VBA_FORMAT_TYPE_OFFSET, // standard number format
+ VBA_FORMAT_TYPE_USERDEFINED, // user defined number format
+ VBA_FORMAT_TYPE_NULL
+};
+
+struct VbaFormatInfo
+{
+ VbaFormatType meType;
+ const char* mpVbaFormat; // Format string in vba
+ NfIndexTableOffset meOffset; // SvNumberFormatter format index, if meType = VBA_FORMAT_TYPE_OFFSET
+ const char* mpOOoFormat; // if meType = VBA_FORMAT_TYPE_USERDEFINED
+};
+
+#define VBA_FORMAT_OFFSET( pcUtf8, eOffset ) \
+ { VBA_FORMAT_TYPE_OFFSET, pcUtf8, eOffset, 0 }
+
+#define VBA_FORMAT_USERDEFINED( pcUtf8, pcDefinedUtf8 ) \
+ { VBA_FORMAT_TYPE_USERDEFINED, pcUtf8, NF_NUMBER_STANDARD, pcDefinedUtf8 }
+
+static VbaFormatInfo pFormatInfoTable[] =
+{
+ VBA_FORMAT_OFFSET( "Long Date", NF_DATE_SYSTEM_LONG ),
+ VBA_FORMAT_USERDEFINED( "Medium Date", "DD-MMM-YY" ),
+ VBA_FORMAT_OFFSET( "Short Date", NF_DATE_SYSTEM_SHORT ),
+ VBA_FORMAT_USERDEFINED( "Long Time", "H:MM:SS AM/PM" ),
+ VBA_FORMAT_OFFSET( "Medium Time", NF_TIME_HHMMAMPM ),
+ VBA_FORMAT_OFFSET( "Short Time", NF_TIME_HHMM ),
+ VBA_FORMAT_OFFSET( "ddddd", NF_DATE_SYSTEM_SHORT ),
+ VBA_FORMAT_OFFSET( "dddddd", NF_DATE_SYSTEM_LONG ),
+ VBA_FORMAT_USERDEFINED( "ttttt", "H:MM:SS AM/PM" ),
+ VBA_FORMAT_OFFSET( "ww", NF_DATE_WW ),
+ { VBA_FORMAT_TYPE_NULL, 0, NF_INDEX_TABLE_ENTRIES, 0 }
+};
+
+VbaFormatInfo* getFormatInfo( const String& rFmt )
+{
+ VbaFormatInfo* pInfo = NULL;
+ INT16 i = 0;
+ while( (pInfo = pFormatInfoTable + i )->mpVbaFormat != NULL )
+ {
+ if( rFmt.EqualsIgnoreCaseAscii( pInfo->mpVbaFormat ) )
+ break;
+ i++;
+ }
+ return pInfo;
+}
+
+#define VBAFORMAT_GENERALDATE "General Date"
+#define VBAFORMAT_C "c"
+#define VBAFORMAT_N "n"
+#define VBAFORMAT_NN "nn"
+#define VBAFORMAT_W "w"
+#define VBAFORMAT_Y "y"
+#define VBAFORMAT_LOWERCASE "<"
+#define VBAFORMAT_UPPERCASE ">"
+
+// From methods1.cxx
+INT16 implGetWeekDay( double aDate, bool bFirstDayParam = false, INT16 nFirstDay = 0 );
+// from methods.cxx
+INT16 implGetMinute( double dDate );
+INT16 implGetDateYear( double aDate );
+BOOL implDateSerial( INT16 nYear, INT16 nMonth, INT16 nDay, double& rdRet );
+
+void SbxValue::Format( XubString& rRes, const XubString* pFmt ) const
+{
+ short nComma = 0;
+ double d = 0;
+
+ // pflin, It is better to use SvNumberFormatter to handle the date/time/number format.
+ // the SvNumberFormatter output is mostly compatible with
+ // VBA output besides the OOo-basic output
+ if( pFmt && !SbxBasicFormater::isBasicFormat( *pFmt ) )
+ {
+ String aStr = GetString();
+
+ if( pFmt->EqualsIgnoreCaseAscii( VBAFORMAT_LOWERCASE ) )
+ {
+ rRes = aStr.ToLowerAscii();
+ return;
+ }
+ if( pFmt->EqualsIgnoreCaseAscii( VBAFORMAT_UPPERCASE ) )
+ {
+ rRes = aStr.ToUpperAscii();
+ return;
+ }
+
+ LanguageType eLangType = GetpApp()->GetSettings().GetLanguage();
+ com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >
+ xFactory = comphelper::getProcessServiceFactory();
+ SvNumberFormatter aFormatter( xFactory, eLangType );
+
+ sal_uInt32 nIndex;
+ xub_StrLen nCheckPos = 0;
+ short nType;
+ double nNumber;
+ Color* pCol;
+
+ BOOL bSuccess = aFormatter.IsNumberFormat( aStr, nIndex, nNumber );
+
+ // number format, use SvNumberFormatter to handle it.
+ if( bSuccess )
+ {
+ String aFmtStr = *pFmt;
+ VbaFormatInfo* pInfo = getFormatInfo( aFmtStr );
+ if( pInfo && pInfo->meType != VBA_FORMAT_TYPE_NULL )
+ {
+ if( pInfo->meType == VBA_FORMAT_TYPE_OFFSET )
+ {
+ nIndex = aFormatter.GetFormatIndex( pInfo->meOffset, eLangType );
+ }
+ else
+ {
+ aFmtStr.AssignAscii( pInfo->mpOOoFormat );
+ aFormatter.PutandConvertEntry( aFmtStr, nCheckPos, nType, nIndex, LANGUAGE_ENGLISH, eLangType );
+ }
+ aFormatter.GetOutputString( nNumber, nIndex, rRes, &pCol );
+ }
+ else if( aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_GENERALDATE )
+ || aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_C ))
+ {
+ if( nNumber <=-1.0 || nNumber >= 1.0 )
+ {
+ // short date
+ nIndex = aFormatter.GetFormatIndex( NF_DATE_SYSTEM_SHORT, eLangType );
+ aFormatter.GetOutputString( nNumber, nIndex, rRes, &pCol );
+
+ // long time
+ if( floor( nNumber ) != nNumber )
+ {
+ aFmtStr.AssignAscii( "H:MM:SS AM/PM" );
+ aFormatter.PutandConvertEntry( aFmtStr, nCheckPos, nType, nIndex, LANGUAGE_ENGLISH, eLangType );
+ String aTime;
+ aFormatter.GetOutputString( nNumber, nIndex, aTime, &pCol );
+ rRes.AppendAscii(" ");
+ rRes += aTime;
+ }
+ }
+ else
+ {
+ // long time only
+ aFmtStr.AssignAscii( "H:MM:SS AM/PM" );
+ aFormatter.PutandConvertEntry( aFmtStr, nCheckPos, nType, nIndex, LANGUAGE_ENGLISH, eLangType );
+ aFormatter.GetOutputString( nNumber, nIndex, rRes, &pCol );
+ }
+ }
+ else if( aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_N )
+ || aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_NN ))
+ {
+ INT32 nMin = implGetMinute( nNumber );
+ if( nMin < 10 && aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_NN ) )
+ {
+ // Minute in two digits
+ sal_Unicode* p = rRes.AllocBuffer( 2 );
+ *p++ = '0';
+ *p = sal_Unicode( '0' + nMin );
+ }
+ else
+ {
+ rRes = String::CreateFromInt32( nMin );
+ }
+ }
+ else if( aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_W ))
+ {
+ INT32 nWeekDay = implGetWeekDay( nNumber );
+ rRes = String::CreateFromInt32( nWeekDay );
+ }
+ else if( aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_Y ))
+ {
+ INT16 nYear = implGetDateYear( nNumber );
+ double dBaseDate;
+ implDateSerial( nYear, 1, 1, dBaseDate );
+ INT32 nYear32 = 1 + INT32( nNumber - dBaseDate );
+ rRes = String::CreateFromInt32( nYear32 );
+ }
+ else
+ {
+ aFormatter.PutandConvertEntry( aFmtStr, nCheckPos, nType, nIndex, LANGUAGE_ENGLISH, eLangType );
+ aFormatter.GetOutputString( nNumber, nIndex, rRes, &pCol );
+ }
+
+ return;
+ }
+ }
+
+ SbxDataType eType = GetType();
+ switch( eType )
+ {
+ case SbxCHAR:
+ case SbxBYTE:
+ case SbxINTEGER:
+ case SbxUSHORT:
+ case SbxLONG:
+ case SbxULONG:
+ case SbxINT:
+ case SbxUINT:
+ case SbxNULL: // #45929 NULL mit durchschummeln
+ nComma = 0; goto cvt;
+ case SbxSINGLE:
+ nComma = 6; goto cvt;
+ case SbxDOUBLE:
+ nComma = 14;
+
+ cvt:
+ if( eType != SbxNULL )
+ d = GetDouble();
+
+ // #45355 weiterer Einsprungpunkt fuer isnumeric-String
+ cvt2:
+ if( pFmt )
+ {
+ // hole die 'statischen' Daten f"ur Sbx
+ SbxAppData* pData = GetSbxData_Impl();
+
+ LanguageType eLangType = GetpApp()->GetSettings().GetLanguage();
+ if( pData->pBasicFormater )
+ {
+ if( pData->eBasicFormaterLangType != eLangType )
+ {
+ delete pData->pBasicFormater;
+ pData->pBasicFormater = NULL;
+ }
+ }
+ pData->eBasicFormaterLangType = eLangType;
+
+ // falls bisher noch kein BasicFormater-Objekt
+ // existiert, so erzeuge dieses
+ if( !pData->pBasicFormater )
+ {
+ SvtSysLocale aSysLocale;
+ const LocaleDataWrapper& rData = aSysLocale.GetLocaleData();
+ sal_Unicode cComma = rData.getNumDecimalSep().GetBuffer()[0];
+ sal_Unicode c1000 = rData.getNumThousandSep().GetBuffer()[0];
+ String aCurrencyStrg = rData.getCurrSymbol();
+
+ // Initialisierung des Basic-Formater-Hilfsobjekts:
+ // hole die Resourcen f"ur die vordefinierten Ausgaben
+ // des Format()-Befehls, z.B. f"ur "On/Off".
+ String aOnStrg = String( SbxValueFormatResId(
+ STR_BASICKEY_FORMAT_ON ) );
+ String aOffStrg = String( SbxValueFormatResId(
+ STR_BASICKEY_FORMAT_OFF) );
+ String aYesStrg = String( SbxValueFormatResId(
+ STR_BASICKEY_FORMAT_YES) );
+ String aNoStrg = String( SbxValueFormatResId(
+ STR_BASICKEY_FORMAT_NO) );
+ String aTrueStrg = String( SbxValueFormatResId(
+ STR_BASICKEY_FORMAT_TRUE) );
+ String aFalseStrg = String( SbxValueFormatResId(
+ STR_BASICKEY_FORMAT_FALSE) );
+ String aCurrencyFormatStrg = String( SbxValueFormatResId(
+ STR_BASICKEY_FORMAT_CURRENCY) );
+ // erzeuge das Basic-Formater-Objekt
+ pData->pBasicFormater
+ = new SbxBasicFormater( cComma,c1000,aOnStrg,aOffStrg,
+ aYesStrg,aNoStrg,aTrueStrg,aFalseStrg,
+ aCurrencyStrg,aCurrencyFormatStrg );
+ }
+ // Bem.: Aus Performance-Gr"unden wird nur EIN BasicFormater-
+ // Objekt erzeugt und 'gespeichert', dadurch erspart man
+ // sich das teure Resourcen-Laden (f"ur landesspezifische
+ // vordefinierte Ausgaben, z.B. "On/Off") und die st"andige
+ // String-Erzeugungs Operationen.
+ // ABER: dadurch ist dieser Code NICHT multithreading f"ahig !
+
+ // hier gibt es Probleme mit ;;;Null, da diese Methode nur aufgerufen
+ // wird, wenn der SbxValue eine Zahl ist !!!
+ // dazu koennte: pData->pBasicFormater->BasicFormatNull( *pFmt ); aufgerufen werden !
+ if( eType != SbxNULL )
+ {
+ rRes = pData->pBasicFormater->BasicFormat( d ,*pFmt );
+ }
+ else
+ {
+ rRes = pData->pBasicFormater->BasicFormatNull( *pFmt );
+ }
+
+ // Die alte Implementierung:
+ //old: printfmtnum( GetDouble(), rRes, *pFmt );
+ }
+ else
+ {
+ ::rtl::OUString aTmpString( rRes );
+ ImpCvtNum( GetDouble(), nComma, aTmpString );
+ rRes = aTmpString;
+ }
+ break;
+ case SbxSTRING:
+ if( pFmt )
+ {
+ // #45355 wenn es numerisch ist, muss gewandelt werden
+ if( IsNumericRTL() )
+ {
+ ScanNumIntnl( GetString(), d, /*bSingle*/FALSE );
+ goto cvt2;
+ }
+ else
+ {
+ // Sonst String-Formatierung
+ printfmtstr( GetString(), rRes, *pFmt );
+ }
+ }
+ else
+ rRes = GetString();
+ break;
+ default:
+ rRes = GetString();
+ }
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxsng.cxx b/basic/source/sbx/sbxsng.cxx
new file mode 100644
index 000000000000..21dd38f44424
--- /dev/null
+++ b/basic/source/sbx/sbxsng.cxx
@@ -0,0 +1,361 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+#include <tools/errcode.hxx>
+#include <basic/sbx.hxx>
+#include "sbxconv.hxx"
+
+float ImpGetSingle( const SbxValues* p )
+{
+ SbxValues aTmp;
+ float nRes;
+start:
+ switch( +p->eType )
+ {
+ case SbxNULL:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ case SbxEMPTY:
+ nRes = 0; break;
+ case SbxCHAR:
+ nRes = p->nChar; break;
+ case SbxBYTE:
+ nRes = p->nByte; break;
+ case SbxINTEGER:
+ case SbxBOOL:
+ nRes = p->nInteger; break;
+ case SbxERROR:
+ case SbxUSHORT:
+ nRes = p->nUShort; break;
+ case SbxLONG:
+ nRes = (float) p->nLong; break;
+ case SbxULONG:
+ nRes = (float) p->nULong; break;
+ case SbxSINGLE:
+ nRes = p->nSingle; break;
+ case SbxSALINT64:
+ nRes = (float) p->nInt64; break;
+ case SbxSALUINT64:
+ nRes = (float) ImpSalUInt64ToDouble( p->uInt64 ); break;
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ if( p->pDecimal )
+ p->pDecimal->getSingle( nRes );
+ else
+ nRes = 0.0;
+ break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ case SbxLONG64:
+ case SbxULONG64:
+ case SbxCURRENCY:
+ {
+ double dVal;
+ if( p->eType == SbxCURRENCY )
+ dVal = ImpCurrencyToDouble( p->nLong64 );
+ else if( p->eType == SbxLONG64 )
+ dVal = ImpINT64ToDouble( p->nLong64 );
+ else if( p->eType == SbxULONG64 )
+ dVal = ImpUINT64ToDouble( p->nULong64 );
+ else
+ dVal = p->nDouble;
+
+ if( dVal > SbxMAXSNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ nRes = static_cast< float >(SbxMAXSNG);
+ }
+ else if( dVal < SbxMINSNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ nRes = static_cast< float >(SbxMINSNG);
+ }
+ else if( dVal > 0 && dVal < SbxMAXSNG2 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ nRes = static_cast< float >(SbxMAXSNG2);
+ }
+ else if( dVal < 0 && dVal > SbxMINSNG2 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ nRes = static_cast< float >(SbxMINSNG2);
+ }
+ else
+ nRes = (float) dVal;
+ break;
+ }
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+ if( !p->pOUString )
+ nRes = 0;
+ else
+ {
+ double d;
+ SbxDataType t;
+ if( ImpScan( *p->pOUString, d, t, NULL ) != SbxERR_OK )
+ nRes = 0;
+ else if( d > SbxMAXSNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ nRes = static_cast< float >(SbxMAXSNG);
+ }
+ else if( d < SbxMINSNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ nRes = static_cast< float >(SbxMINSNG);
+ }
+ else
+ nRes = (float) d;
+ }
+ break;
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ nRes = pVal->GetSingle();
+ else
+ {
+ SbxBase::SetError( SbxERR_NO_OBJECT ); nRes = 0;
+ }
+ break;
+ }
+
+ case SbxBYREF | SbxCHAR:
+ nRes = *p->pChar; break;
+ case SbxBYREF | SbxBYTE:
+ nRes = *p->pByte; break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ nRes = *p->pInteger; break;
+ case SbxBYREF | SbxLONG:
+ nRes = (float) *p->pLong; break;
+ case SbxBYREF | SbxULONG:
+ nRes = (float) *p->pULong; break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ nRes = *p->pUShort; break;
+ case SbxBYREF | SbxSINGLE:
+ nRes = *p->pSingle; break;
+ // from here had to be tested
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ aTmp.nDouble = *p->pDouble; goto ref;
+ case SbxBYREF | SbxULONG64:
+ aTmp.nULong64 = *p->pULong64; goto ref;
+ case SbxBYREF | SbxLONG64:
+ case SbxBYREF | SbxSALINT64:
+ nRes = (float) *p->pnInt64; break;
+ case SbxBYREF | SbxSALUINT64:
+ nRes = (float) ImpSalUInt64ToDouble( *p->puInt64 ); break;
+ case SbxBYREF | SbxCURRENCY:
+ aTmp.nLong64 = *p->pLong64; goto ref;
+ ref:
+ aTmp.eType = SbxDataType( p->eType & 0x0FFF );
+ p = &aTmp; goto start;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0;
+ }
+ return nRes;
+}
+
+void ImpPutSingle( SbxValues* p, float n )
+{
+ SbxValues aTmp;
+start:
+ switch( +p->eType )
+ {
+ case SbxCHAR:
+ aTmp.pChar = &p->nChar; goto direct;
+ case SbxBYTE:
+ aTmp.pByte = &p->nByte; goto direct;
+ case SbxINTEGER:
+ case SbxBOOL:
+ aTmp.pInteger = &p->nInteger; goto direct;
+ case SbxLONG:
+ aTmp.pLong = &p->nLong; goto direct;
+ case SbxULONG:
+ aTmp.pULong = &p->nULong; goto direct;
+ case SbxERROR:
+ case SbxUSHORT:
+ aTmp.pUShort = &p->nUShort; goto direct;
+ case SbxULONG64:
+ aTmp.pULong64 = &p->nULong64; goto direct;
+ case SbxLONG64:
+ case SbxCURRENCY:
+ aTmp.pLong64 = &p->nLong64; goto direct;
+ case SbxSALINT64:
+ aTmp.pnInt64 = &p->nInt64; goto direct;
+ case SbxSALUINT64:
+ aTmp.puInt64 = &p->uInt64; goto direct;
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ {
+ SbxDecimal* pDec = ImpCreateDecimal( p );
+ if( !pDec->setSingle( n ) )
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ break;
+ }
+ direct:
+ aTmp.eType = SbxDataType( p->eType | SbxBYREF );
+ p = &aTmp; goto start;
+
+ // from here no tests
+ case SbxSINGLE:
+ p->nSingle = n; break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ p->nDouble = n; break;
+
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+ {
+ if( !p->pOUString )
+ p->pOUString = new ::rtl::OUString;
+ ImpCvtNum( (double) n, 6, *p->pOUString );
+ break;
+ }
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ pVal->PutSingle( n );
+ else
+ SbxBase::SetError( SbxERR_NO_OBJECT );
+ break;
+ }
+ case SbxBYREF | SbxCHAR:
+ if( n > SbxMAXCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXCHAR;
+ }
+ else if( n < SbxMINCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINCHAR;
+ }
+ *p->pChar = (xub_Unicode) n; break;
+ case SbxBYREF | SbxBYTE:
+ if( n > SbxMAXBYTE )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXBYTE;
+ }
+ else if( n < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = 0;
+ }
+ *p->pByte = (BYTE) n; break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ if( n > SbxMAXINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXINT;
+ }
+ else if( n < SbxMININT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMININT;
+ }
+ *p->pInteger = (INT16) n; break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ if( n > SbxMAXUINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXUINT;
+ }
+ else if( n < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = 0;
+ }
+ *p->pUShort = (UINT16) n; break;
+ case SbxBYREF | SbxLONG:
+ {
+ INT32 i;
+ if( n > SbxMAXLNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); i = SbxMAXLNG;
+ }
+ else if( n < SbxMINLNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); i = SbxMINLNG;
+ }
+ else
+ {
+ i = sal::static_int_cast< INT32 >(n);
+ }
+ *p->pLong = i; break;
+ }
+ case SbxBYREF | SbxULONG:
+ {
+ UINT32 i;
+ if( n > SbxMAXULNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); i = SbxMAXULNG;
+ }
+ else if( n < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); i = 0;
+ }
+ else
+ {
+ i = sal::static_int_cast< UINT32 >(n);
+ }
+ *p->pULong = i; break;
+ }
+ case SbxBYREF | SbxSINGLE:
+ *p->pSingle = n; break;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ *p->pDouble = (double) n; break;
+ case SbxBYREF | SbxSALINT64:
+ *p->pnInt64 = ImpDoubleToSalInt64( (double) n ); break;
+ case SbxBYREF | SbxSALUINT64:
+ *p->puInt64 = ImpDoubleToSalUInt64( (double) n ); break;
+ case SbxBYREF | SbxCURRENCY:
+ double d;
+ if( n > SbxMAXCURR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); d = SbxMAXCURR;
+ }
+ else if( n < SbxMINCURR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); d = SbxMINCURR;
+ }
+ else
+ {
+ d = n;
+ }
+ *p->pLong64 = ImpDoubleToCurrency( n ); break;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxstr.cxx b/basic/source/sbx/sbxstr.cxx
new file mode 100644
index 000000000000..ebfc7a01c23b
--- /dev/null
+++ b/basic/source/sbx/sbxstr.cxx
@@ -0,0 +1,315 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+#include <tools/errcode.hxx>
+#include <basic/sbx.hxx>
+#include "sbxconv.hxx"
+#include "sbxres.hxx"
+#include "runtime.hxx"
+#include <rtl/ustrbuf.hxx>
+
+// Die Konversion eines Items auf String wird ueber die Put-Methoden
+// der einzelnen Datentypen abgewickelt, um doppelten Code zu vermeiden.
+
+::rtl::OUString ImpGetString( const SbxValues* p )
+{
+ SbxValues aTmp;
+ ::rtl::OUString aRes;
+ aTmp.eType = SbxSTRING;
+ aTmp.pOUString = &aRes;
+ switch( +p->eType )
+ {
+ case SbxNULL:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ case SbxEMPTY:
+ break;
+ case SbxCHAR:
+ ImpPutChar( &aTmp, p->nChar ); break;
+ case SbxBYTE:
+ ImpPutByte( &aTmp, p->nByte ); break;
+ case SbxINTEGER:
+ ImpPutInteger( &aTmp, p->nInteger ); break;
+ case SbxBOOL:
+ ImpPutBool( &aTmp, p->nUShort ); break;
+ case SbxUSHORT:
+ ImpPutUShort( &aTmp, p->nUShort ); break;
+ case SbxLONG:
+ ImpPutLong( &aTmp, p->nLong ); break;
+ case SbxULONG:
+ ImpPutULong( &aTmp, p->nULong ); break;
+ case SbxSINGLE:
+ ImpPutSingle( &aTmp, p->nSingle ); break;
+ case SbxDOUBLE:
+ ImpPutDouble( &aTmp, p->nDouble ); break;
+ case SbxCURRENCY:
+ ImpPutCurrency( &aTmp, p->nLong64 ); break;
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ ImpPutDecimal( &aTmp, p->pDecimal ); break;
+ case SbxSALINT64:
+ ImpPutInt64( &aTmp, p->nInt64 ); break;
+ case SbxSALUINT64:
+ ImpPutUInt64( &aTmp, p->uInt64 ); break;
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+ if ( p->pOUString )
+ *aTmp.pOUString = *p->pOUString;
+ break;
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ aRes = pVal->GetString();
+ else if( p->pObj && p->pObj->IsFixed()
+ && (p->pObj->GetType() == (SbxARRAY | SbxBYTE )) )
+ {
+ // convert byte array to string
+ SbxArray* pArr = PTR_CAST(SbxArray, p->pObj);
+ if( pArr )
+ aRes = ByteArrayToString( pArr );
+ }
+ else
+ SbxBase::SetError( SbxERR_NO_OBJECT );
+ break;
+ }
+ case SbxERROR:
+ // Hier wird der String "Error n" erzeugt
+ aRes = SbxRes( STRING_ERRORMSG );
+ aRes += ::rtl::OUString( p->nUShort ); break;
+ case SbxDATE:
+ ImpPutDate( &aTmp, p->nDouble ); break;
+
+ case SbxBYREF | SbxCHAR:
+ ImpPutChar( &aTmp, *p->pChar ); break;
+ case SbxBYREF | SbxBYTE:
+ ImpPutByte( &aTmp, *p->pByte ); break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ ImpPutInteger( &aTmp, *p->pInteger ); break;
+ case SbxBYREF | SbxLONG:
+ ImpPutLong( &aTmp, *p->pLong ); break;
+ case SbxBYREF | SbxULONG:
+ ImpPutULong( &aTmp, *p->pULong ); break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ ImpPutUShort( &aTmp, *p->pUShort ); break;
+ case SbxBYREF | SbxSINGLE:
+ ImpPutSingle( &aTmp, *p->pSingle ); break;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ ImpPutDouble( &aTmp, *p->pDouble ); break;
+ case SbxBYREF | SbxCURRENCY:
+ ImpPutCurrency( &aTmp, *p->pLong64 ); break;
+ case SbxBYREF | SbxSALINT64:
+ ImpPutInt64( &aTmp, *p->pnInt64 ); break;
+ case SbxBYREF | SbxSALUINT64:
+ ImpPutUInt64( &aTmp, *p->puInt64 ); break;
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ }
+ return aRes;
+}
+
+// AB 10.4.97, neue Funktion fuer SbxValue::GetCoreString()
+::rtl::OUString ImpGetCoreString( const SbxValues* p )
+{
+ // Vorerst nur fuer double
+ if( ( p->eType & (~SbxBYREF) ) == SbxDOUBLE )
+ {
+ SbxValues aTmp;
+ XubString aRes;
+ aTmp.eType = SbxSTRING;
+ if( p->eType == SbxDOUBLE )
+ ImpPutDouble( &aTmp, p->nDouble, /*bCoreString=*/TRUE );
+ else
+ ImpPutDouble( &aTmp, *p->pDouble, /*bCoreString=*/TRUE );
+ return aRes;
+ }
+ else
+ return ImpGetString( p );
+}
+
+void ImpPutString( SbxValues* p, const ::rtl::OUString* n )
+{
+ SbxValues aTmp;
+ aTmp.eType = SbxSTRING;
+ ::rtl::OUString* pTmp = NULL;
+ // Sicherheitshalber, falls ein NULL-Ptr kommt
+ if( !n )
+ n = pTmp = new ::rtl::OUString;
+ aTmp.pOUString = (::rtl::OUString*)n;
+ switch( +p->eType )
+ {
+ case SbxCHAR:
+ p->nChar = ImpGetChar( &aTmp ); break;
+ case SbxBYTE:
+ p->nByte = ImpGetByte( &aTmp ); break;
+ case SbxINTEGER:
+ case SbxBOOL:
+ p->nInteger = ImpGetInteger( &aTmp ); break;
+ case SbxLONG:
+ p->nLong = ImpGetLong( &aTmp ); break;
+ case SbxULONG:
+ p->nULong = ImpGetULong( &aTmp ); break;
+ case SbxERROR:
+ case SbxUSHORT:
+ p->nUShort = ImpGetUShort( &aTmp ); break;
+ case SbxSINGLE:
+ p->nSingle = ImpGetSingle( &aTmp ); break;
+ case SbxDATE:
+ p->nDouble = ImpGetDate( &aTmp ); break;
+ case SbxDOUBLE:
+ p->nDouble = ImpGetDouble( &aTmp ); break;
+ case SbxULONG64:
+ p->nLong64 = ImpGetCurrency( &aTmp ); break;
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ releaseDecimalPtr( p->pDecimal );
+ p->pDecimal = ImpGetDecimal( &aTmp ); break;
+ case SbxSALINT64:
+ p->nInt64 = ImpGetInt64( &aTmp ); break;
+ case SbxSALUINT64:
+ p->uInt64 = ImpGetUInt64( &aTmp ); break;
+
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+ if( n->getLength() )
+ {
+ if( !p->pOUString )
+ p->pOUString = new ::rtl::OUString( *n );
+ else
+ *p->pOUString = *n;
+ }
+ else
+ delete p->pOUString, p->pOUString = NULL;
+ break;
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ pVal->PutString( *n );
+ else
+ SbxBase::SetError( SbxERR_NO_OBJECT );
+ break;
+ }
+ case SbxBYREF | SbxCHAR:
+ *p->pChar = ImpGetChar( p ); break;
+ case SbxBYREF | SbxBYTE:
+ *p->pByte = ImpGetByte( p ); break;
+ case SbxBYREF | SbxINTEGER:
+ *p->pInteger = ImpGetInteger( p ); break;
+ case SbxBYREF | SbxBOOL:
+ *p->pUShort = sal::static_int_cast< UINT16 >( ImpGetBool( p ) );
+ break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ *p->pUShort = ImpGetUShort( p ); break;
+ case SbxBYREF | SbxLONG:
+ *p->pLong = ImpGetLong( p ); break;
+ case SbxBYREF | SbxULONG:
+ *p->pULong = ImpGetULong( p ); break;
+ case SbxBYREF | SbxSINGLE:
+ *p->pSingle = ImpGetSingle( p ); break;
+ case SbxBYREF | SbxDATE:
+ *p->pDouble = ImpGetDate( p ); break;
+ case SbxBYREF | SbxDOUBLE:
+ *p->pDouble = ImpGetDouble( p ); break;
+ case SbxBYREF | SbxCURRENCY:
+ *p->pLong64 = ImpGetCurrency( p ); break;
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ }
+ delete pTmp;
+}
+
+// Convert string to an array of bytes, preserving unicode (2bytes per character)
+SbxArray* StringToByteArray(const ::rtl::OUString& rStr)
+{
+ sal_Int32 nArraySize = rStr.getLength() * 2;
+ const sal_Unicode* pSrc = rStr.getStr();
+ SbxDimArray* pArray = new SbxDimArray(SbxBYTE);
+ bool bIncIndex = ( IsBaseIndexOne() && SbiRuntime::isVBAEnabled() );
+ if( nArraySize )
+ {
+ if( bIncIndex )
+ pArray->AddDim32( 1, nArraySize );
+ else
+ pArray->AddDim32( 0, nArraySize-1 );
+ }
+ else
+ {
+ pArray->unoAddDim( 0, -1 );
+ }
+
+ for( USHORT i=0; i< nArraySize; i++)
+ {
+ SbxVariable* pNew = new SbxVariable( SbxBYTE );
+ BYTE aByte = static_cast< BYTE >( i%2 ? ((*pSrc) >> 8) & 0xff : (*pSrc) & 0xff );
+ pNew->PutByte( aByte );
+ pNew->SetFlag( SBX_WRITE );
+ pArray->Put( pNew, i );
+ if( i%2 )
+ pSrc++;
+ }
+ return pArray;
+}
+
+// Convert an array of bytes to string (2bytes per character)
+::rtl::OUString ByteArrayToString(SbxArray* pArr)
+{
+ USHORT nCount = pArr->Count();
+ ::rtl::OUStringBuffer aStrBuf;
+ sal_Unicode aChar = 0;
+ for( USHORT i = 0 ; i < nCount ; i++ )
+ {
+ sal_Unicode aTempChar = pArr->Get(i)->GetByte();
+ if( i%2 )
+ {
+ aChar = (aTempChar << 8 ) | aChar;
+ aStrBuf.append(aChar);
+ aChar = 0;
+ }
+ else
+ {
+ aChar = aTempChar;
+ }
+ }
+
+ if( nCount%2 )
+ {
+ aStrBuf.append(aChar);
+ }
+
+ return aStrBuf.makeStringAndClear();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxuint.cxx b/basic/source/sbx/sbxuint.cxx
new file mode 100644
index 000000000000..d5123b814a34
--- /dev/null
+++ b/basic/source/sbx/sbxuint.cxx
@@ -0,0 +1,333 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+#include <tools/errcode.hxx>
+#include <basic/sbx.hxx>
+#include "sbxconv.hxx"
+
+UINT16 ImpGetUShort( const SbxValues* p )
+{
+ SbxValues aTmp;
+ UINT16 nRes;
+start:
+ switch( +p->eType )
+ {
+ case SbxNULL:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ case SbxEMPTY:
+ nRes = 0; break;
+ case SbxCHAR:
+ nRes = p->nChar;
+ break;
+ case SbxBYTE:
+ nRes = p->nByte; break;
+ case SbxINTEGER:
+ case SbxBOOL:
+ if( p->nInteger < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0;
+ }
+ else
+ nRes = p->nInteger;
+ break;
+ case SbxERROR:
+ case SbxUSHORT:
+ nRes = p->nUShort;
+ break;
+ case SbxLONG:
+ if( p->nLong > SbxMAXUINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXUINT;
+ }
+ else if( p->nLong < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0;
+ }
+ else
+ nRes = (UINT16) p->nLong;
+ break;
+ case SbxULONG:
+ if( p->nULong > SbxMAXUINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXUINT;
+ }
+ else
+ nRes = (UINT16) p->nULong;
+ break;
+ case SbxSALINT64:
+ if( p->nInt64 > SbxMAXUINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXUINT;
+ }
+ else if( p->nInt64 < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0;
+ }
+ else
+ nRes = (UINT16) p->nInt64;
+ break;
+ case SbxSALUINT64:
+ if( p->uInt64 > SbxMAXUINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXUINT;
+ }
+ else
+ nRes = (UINT16) p->uInt64;
+ break;
+ case SbxSINGLE:
+ if( p->nSingle > SbxMAXUINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXUINT;
+ }
+ else if( p->nSingle < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0;
+ }
+ else
+ nRes = (UINT16) ( p->nSingle + 0.5 );
+ break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ case SbxLONG64:
+ case SbxULONG64:
+ case SbxCURRENCY:
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ {
+ double dVal;
+ if( p->eType == SbxCURRENCY )
+ dVal = ImpCurrencyToDouble( p->nLong64 );
+ else if( p->eType == SbxLONG64 )
+ dVal = ImpINT64ToDouble( p->nLong64 );
+ else if( p->eType == SbxULONG64 )
+ dVal = ImpUINT64ToDouble( p->nULong64 );
+ else if( p->eType == SbxDECIMAL )
+ {
+ dVal = 0.0;
+ if( p->pDecimal )
+ p->pDecimal->getDouble( dVal );
+ }
+ else
+ dVal = p->nDouble;
+
+ if( dVal > SbxMAXUINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXUINT;
+ }
+ else if( dVal < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0;
+ }
+ else
+ nRes = (UINT16) ( dVal + 0.5 );
+ break;
+ }
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+ if( !p->pOUString )
+ nRes = 0;
+ else
+ {
+ double d;
+ SbxDataType t;
+ if( ImpScan( *p->pOUString, d, t, NULL ) != SbxERR_OK )
+ nRes = 0;
+ else if( d > SbxMAXUINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXUINT;
+ }
+ else if( d < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0;
+ }
+ else
+ nRes = (UINT16) ( d + 0.5 );
+ }
+ break;
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ nRes = pVal->GetUShort();
+ else
+ {
+ SbxBase::SetError( SbxERR_NO_OBJECT ); nRes = 0;
+ }
+ break;
+ }
+
+ case SbxBYREF | SbxBYTE:
+ nRes = *p->pByte; break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ nRes = *p->pUShort; break;
+
+ // ab hier wird getestet
+ case SbxBYREF | SbxCHAR:
+ aTmp.nChar = *p->pChar; goto ref;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ aTmp.nInteger = *p->pInteger; goto ref;
+ case SbxBYREF | SbxLONG:
+ aTmp.nLong = *p->pLong; goto ref;
+ case SbxBYREF | SbxULONG:
+ aTmp.nULong = *p->pULong; goto ref;
+ case SbxBYREF | SbxSINGLE:
+ aTmp.nSingle = *p->pSingle; goto ref;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ aTmp.nDouble = *p->pDouble; goto ref;
+ case SbxBYREF | SbxULONG64:
+ aTmp.nULong64 = *p->pULong64; goto ref;
+ case SbxBYREF | SbxLONG64:
+ case SbxBYREF | SbxCURRENCY:
+ aTmp.nLong64 = *p->pLong64; goto ref;
+ case SbxBYREF | SbxSALINT64:
+ aTmp.nInt64 = *p->pnInt64; goto ref;
+ case SbxBYREF | SbxSALUINT64:
+ aTmp.uInt64 = *p->puInt64; goto ref;
+ ref:
+ aTmp.eType = SbxDataType( p->eType & 0x0FFF );
+ p = &aTmp; goto start;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0;
+ }
+ return nRes;
+}
+
+void ImpPutUShort( SbxValues* p, UINT16 n )
+{
+ SbxValues aTmp;
+
+start:
+ switch( +p->eType )
+ {
+ case SbxERROR:
+ case SbxUSHORT:
+ p->nUShort = n; break;
+ case SbxLONG:
+ p->nLong = n; break;
+ case SbxULONG:
+ p->nULong = n; break;
+ case SbxSINGLE:
+ p->nSingle = n; break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ p->nDouble = n; break;
+ case SbxSALINT64:
+ p->nInt64 = n; break;
+ case SbxSALUINT64:
+ p->uInt64 = n; break;
+ case SbxULONG64:
+ p->nULong64 = ImpDoubleToUINT64( (double)n ); break;
+ case SbxLONG64:
+ p->nLong64 = ImpDoubleToINT64( (double)n ); break;
+ case SbxCURRENCY:
+ p->nLong64 = ImpDoubleToCurrency( (double)n ); break;
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ ImpCreateDecimal( p )->setUInt( n );
+ break;
+
+ // Tests ab hier
+ case SbxCHAR:
+ aTmp.pChar = &p->nChar; goto direct;
+ case SbxBYTE:
+ aTmp.pByte = &p->nByte; goto direct;
+ case SbxINTEGER:
+ case SbxBOOL:
+ aTmp.pInteger = &p->nInteger;
+ direct:
+ aTmp.eType = SbxDataType( p->eType | SbxBYREF );
+ p = &aTmp; goto start;
+
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+ if( !p->pOUString )
+ p->pOUString = new ::rtl::OUString;
+ ImpCvtNum( (double) n, 0, *p->pOUString );
+ break;
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ pVal->PutUShort( n );
+ else
+ SbxBase::SetError( SbxERR_NO_OBJECT );
+ break;
+ }
+
+ case SbxBYREF | SbxCHAR:
+ *p->pChar = (xub_Unicode) n; break;
+ case SbxBYREF | SbxBYTE:
+ if( n > SbxMAXBYTE )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXBYTE;
+ }
+ *p->pByte = (BYTE) n; break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ if( n > SbxMAXINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXINT;
+ }
+ *p->pInteger = (INT16) n; break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ *p->pUShort = n; break;
+ case SbxBYREF | SbxLONG:
+ *p->pLong = n; break;
+ case SbxBYREF | SbxULONG:
+ *p->pULong = n; break;
+ case SbxBYREF | SbxSINGLE:
+ *p->pSingle = n; break;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ *p->pDouble = n; break;
+ case SbxBYREF | SbxSALINT64:
+ *p->pnInt64 = n; break;
+ case SbxBYREF | SbxSALUINT64:
+ *p->puInt64 = n; break;
+ case SbxBYREF | SbxULONG64:
+ *p->pULong64 = ImpDoubleToUINT64( (double)n ); break;
+ case SbxBYREF | SbxLONG64:
+ *p->pLong64 = ImpDoubleToINT64( (double)n ); break;
+ case SbxBYREF | SbxCURRENCY:
+ *p->pLong64 = ImpDoubleToCurrency( (double)n ); break;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxulng.cxx b/basic/source/sbx/sbxulng.cxx
new file mode 100644
index 000000000000..13c91f8e5213
--- /dev/null
+++ b/basic/source/sbx/sbxulng.cxx
@@ -0,0 +1,323 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+#include <tools/errcode.hxx>
+#include <basic/sbx.hxx>
+#include "sbxconv.hxx"
+
+UINT32 ImpGetULong( const SbxValues* p )
+{
+ SbxValues aTmp;
+ UINT32 nRes;
+start:
+ switch( +p->eType )
+ {
+ case SbxNULL:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ case SbxEMPTY:
+ nRes = 0; break;
+ case SbxCHAR:
+ nRes = p->nChar;
+ break;
+ case SbxBYTE:
+ nRes = p->nByte; break;
+ case SbxINTEGER:
+ case SbxBOOL:
+ if( p->nInteger < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0;
+ }
+ else
+ nRes = p->nInteger;
+ break;
+ case SbxERROR:
+ case SbxUSHORT:
+ nRes = p->nUShort;
+ break;
+ case SbxLONG:
+ if( p->nLong < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0;
+ }
+ else
+ nRes = p->nLong;
+ break;
+ case SbxULONG:
+ nRes = p->nULong; break;
+ case SbxSINGLE:
+ if( p->nSingle > SbxMAXULNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXULNG;
+ }
+ else if( p->nSingle < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0;
+ }
+ else
+ nRes = (UINT32) ( p->nSingle + 0.5 );
+ break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ case SbxLONG64:
+ case SbxULONG64:
+ case SbxSALINT64:
+ case SbxSALUINT64:
+ case SbxCURRENCY:
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ {
+ double dVal;
+ if( p->eType == SbxCURRENCY )
+ dVal = ImpCurrencyToDouble( p->nLong64 );
+ else if( p->eType == SbxLONG64 )
+ dVal = ImpINT64ToDouble( p->nLong64 );
+ else if( p->eType == SbxULONG64 )
+ dVal = ImpUINT64ToDouble( p->nULong64 );
+ else if( p->eType == SbxSALINT64 )
+ dVal = static_cast< double >(p->nInt64);
+ else if( p->eType == SbxSALUINT64 )
+ dVal = ImpSalUInt64ToDouble( p->uInt64 );
+ else if( p->eType == SbxDECIMAL )
+ {
+ dVal = 0.0;
+ if( p->pDecimal )
+ p->pDecimal->getDouble( dVal );
+ }
+ else
+ dVal = p->nDouble;
+
+ if( dVal > SbxMAXULNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXULNG;
+ }
+ else if( dVal < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0;
+ }
+ else
+ nRes = (UINT32) ( dVal + 0.5 );
+ break;
+ }
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+ if( !p->pOUString )
+ nRes = 0;
+ else
+ {
+ double d;
+ SbxDataType t;
+ if( ImpScan( *p->pOUString, d, t, NULL ) != SbxERR_OK )
+ nRes = 0;
+ else if( d > SbxMAXULNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXULNG;
+ }
+ else if( d < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0;
+ }
+ else
+ nRes = (UINT32) ( d + 0.5 );
+ }
+ break;
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ nRes = pVal->GetULong();
+ else
+ {
+ SbxBase::SetError( SbxERR_NO_OBJECT ); nRes = 0;
+ }
+ break;
+ }
+
+ case SbxBYREF | SbxBYTE:
+ nRes = *p->pByte; break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ nRes = *p->pUShort; break;
+ case SbxBYREF | SbxULONG:
+ nRes = *p->pULong; break;
+
+ // Tests ab hier
+ case SbxBYREF | SbxCHAR:
+ aTmp.nChar = *p->pChar; goto ref;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ aTmp.nInteger = *p->pInteger; goto ref;
+ case SbxBYREF | SbxLONG:
+ aTmp.nLong = *p->pLong; goto ref;
+ case SbxBYREF | SbxSINGLE:
+ aTmp.nSingle = *p->pSingle; goto ref;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ aTmp.nDouble = *p->pDouble; goto ref;
+ case SbxBYREF | SbxSALINT64:
+ aTmp.nInt64 = *p->pnInt64; goto ref;
+ case SbxBYREF | SbxSALUINT64:
+ aTmp.uInt64 = *p->puInt64; goto ref;
+ case SbxBYREF | SbxULONG64:
+ aTmp.nULong64 = *p->pULong64; goto ref;
+ case SbxBYREF | SbxLONG64:
+ case SbxBYREF | SbxCURRENCY:
+ aTmp.nLong64 = *p->pLong64; goto ref;
+ ref:
+ aTmp.eType = SbxDataType( p->eType & 0x0FFF );
+ p = &aTmp; goto start;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0;
+ }
+ return nRes;
+}
+
+void ImpPutULong( SbxValues* p, UINT32 n )
+{
+ SbxValues aTmp;
+start:
+ switch( +p->eType )
+ {
+ case SbxULONG:
+ p->nULong = n; break;
+ case SbxSINGLE:
+ p->nSingle = (float) n; break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ p->nDouble = n; break;
+ case SbxSALINT64:
+ p->nInt64 = n; break;
+ case SbxSALUINT64:
+ p->uInt64 = n; break;
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ ImpCreateDecimal( p )->setULong( n );
+ break;
+
+ // Tests ab hier
+ case SbxCHAR:
+ aTmp.pChar = &p->nChar; goto direct;
+ case SbxUINT:
+ aTmp.pByte = &p->nByte; goto direct;
+ case SbxINTEGER:
+ case SbxBOOL:
+ aTmp.pInteger = &p->nInteger; goto direct;
+ case SbxLONG:
+ aTmp.pLong = &p->nLong; goto direct;
+ case SbxERROR:
+ case SbxUSHORT:
+ aTmp.pUShort = &p->nUShort; goto direct;
+ case SbxULONG64:
+ aTmp.pULong64 = &p->nULong64; goto direct;
+ case SbxLONG64:
+ case SbxCURRENCY:
+ aTmp.pLong64 = &p->nLong64; goto direct;
+ direct:
+ aTmp.eType = SbxDataType( p->eType | SbxBYREF );
+ p = &aTmp; goto start;
+
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+ if( !p->pOUString )
+ p->pOUString = new ::rtl::OUString;
+ ImpCvtNum( (double) n, 0, *p->pOUString );
+ break;
+ case SbxOBJECT:
+ {
+ SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
+ if( pVal )
+ pVal->PutULong( n );
+ else
+ SbxBase::SetError( SbxERR_NO_OBJECT );
+ break;
+ }
+ case SbxBYREF | SbxCHAR:
+ if( n > SbxMAXCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXCHAR;
+ }
+ *p->pChar = (xub_Unicode) n; break;
+ case SbxBYREF | SbxBYTE:
+ if( n > SbxMAXBYTE )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXBYTE;
+ }
+ *p->pByte = (BYTE) n; break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ if( n > SbxMAXINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXINT;
+ }
+ *p->pInteger = (INT16) n; break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ if( n > SbxMAXUINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXUINT;
+ }
+ *p->pUShort = (UINT16) n; break;
+ case SbxBYREF | SbxLONG:
+ if( n > SbxMAXLNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXLNG;
+ }
+ *p->pLong = (INT32) n; break;
+ case SbxBYREF | SbxULONG:
+ *p->pULong = n; break;
+ case SbxBYREF | SbxSINGLE:
+ *p->pSingle = (float) n; break;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ *p->pDouble = n; break;
+ case SbxBYREF | SbxSALINT64:
+ *p->pnInt64 = n; break;
+ case SbxBYREF | SbxSALUINT64:
+ *p->puInt64 = n; break;
+ case SbxBYREF | SbxCURRENCY:
+ double d;
+ if( n > SbxMAXCURR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); d = SbxMAXCURR;
+ }
+ else
+ {
+ d = n;
+ }
+ *p->pLong64 = ImpDoubleToCurrency( n ); break;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxvals.cxx b/basic/source/sbx/sbxvals.cxx
new file mode 100644
index 000000000000..4f08b3ba5f96
--- /dev/null
+++ b/basic/source/sbx/sbxvals.cxx
@@ -0,0 +1,112 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+
+#define _TLBIGINT_INT64
+#include <tools/bigint.hxx>
+#include <basic/sbx.hxx>
+
+///////////////////////////// BigInt/Currency //////////////////////////////
+
+SbxValues::SbxValues( const BigInt &rBig ) : eType(SbxCURRENCY)
+{
+ rBig.INT64( &nLong64 );
+}
+
+//TODO: BigInt is TOOLS_DLLPUBLIC, and its four member functions only declared
+// and defined within basic (#define _TLBIGINT_INT64) are a bad hack that causes
+// "warning C4273: 'function' : inconsistent dll linkage" on MSC; this whole
+// mess should be cleaned up properly (e.g., by completely removing Sbx[U]INT64
+// and using sal_[u]Int64 instead):
+#if defined _MSC_VER
+#pragma warning(disable: 4273)
+#endif
+
+BOOL BigInt::INT64( SbxINT64 *p ) const
+{
+ if( bIsBig ) {
+ if( nLen > 4 || (nNum[3] & 0x8000) )
+ return FALSE;
+
+ p->nLow = ((UINT32)nNum[1] << 16) | (UINT32)nNum[0];
+ p->nHigh = ((UINT32)nNum[3] << 16) | (UINT32)nNum[2];
+ if( bIsNeg )
+ p->CHS();
+ }
+ else
+ p->Set( (INT32)nVal );
+
+ return TRUE;
+}
+
+BigInt::BigInt( const SbxINT64 &r )
+{
+ BigInt a10000 = 0x10000;
+
+ *this = r.nHigh;
+ if( r.nHigh )
+ *this *= a10000;
+ *this += (USHORT)(r.nLow >> 16);
+ *this *= a10000;
+ *this += (USHORT)r.nLow;
+}
+
+BOOL BigInt::UINT64( SbxUINT64 *p ) const
+{
+ if( bIsBig ) {
+ if( bIsNeg || nLen > 4 )
+ return FALSE;
+
+ p->nLow = ((UINT32)nNum[1] << 16) | (UINT32)nNum[0];
+ p->nHigh = ((UINT32)nNum[3] << 16) | (UINT32)nNum[2];
+ }
+ else {
+ if( nVal < 0 )
+ return FALSE;
+
+ p->Set( (UINT32)nVal );
+ }
+
+ return TRUE;
+}
+
+BigInt::BigInt( const SbxUINT64 &r )
+{
+ BigInt a10000 = 0x10000;
+
+ *this = BigInt(r.nHigh);
+ if( r.nHigh )
+ *this *= a10000;
+ *this += (USHORT)(r.nLow >> 16);
+ *this *= a10000;
+ *this += (USHORT)r.nLow;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxvalue.cxx b/basic/source/sbx/sbxvalue.cxx
new file mode 100644
index 000000000000..2c22aa246f25
--- /dev/null
+++ b/basic/source/sbx/sbxvalue.cxx
@@ -0,0 +1,1862 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+
+#define _TLBIGINT_INT64
+#include <tools/bigint.hxx>
+#include <tools/stream.hxx>
+
+#include <basic/sbx.hxx>
+#include "sbxconv.hxx"
+#include <math.h>
+#include "runtime.hxx"
+
+TYPEINIT1(SbxValue,SbxBase)
+
+/////////////////////////// SbxINT64 /////////////////////////////////////
+SbxINT64 &SbxINT64::operator -= ( const SbxINT64 &r )
+{
+ BigInt b( *this );
+ b -= BigInt( r );
+ b.INT64( this );
+ return *this;
+}
+SbxINT64 &SbxINT64::operator += ( const SbxINT64 &r )
+{
+ BigInt b( *this );
+ b += BigInt( r );
+ b.INT64( this );
+ return *this;
+}
+SbxINT64 &SbxINT64::operator *= ( const SbxINT64 &r )
+{
+ BigInt b( *this );
+ b *= BigInt( r );
+ b.INT64( this );
+ return *this;
+}
+SbxINT64 &SbxINT64::operator %= ( const SbxINT64 &r )
+{
+ BigInt b( *this );
+ b %= BigInt( r );
+ b.INT64( this );
+ return *this;
+}
+SbxINT64 &SbxINT64::operator /= ( const SbxINT64 &r )
+{
+ BigInt b( *this );
+ b /= BigInt( r );
+ b.INT64( this );
+ return *this;
+}
+SbxINT64 &SbxINT64::operator &= ( const SbxINT64 &r )
+{
+ nHigh &= r.nHigh;
+ nLow &= r.nLow;
+ return *this;
+}
+SbxINT64 &SbxINT64::operator |= ( const SbxINT64 &r )
+{
+ nHigh |= r.nHigh;
+ nLow |= r.nLow;
+ return *this;
+}
+SbxINT64 &SbxINT64::operator ^= ( const SbxINT64 &r )
+{
+ nHigh ^= r.nHigh;
+ nLow ^= r.nLow;
+ return *this;
+}
+
+SbxINT64 operator - ( const SbxINT64 &l, const SbxINT64 &r )
+{
+ SbxINT64 a(l);
+ a -= r;
+ return a;
+}
+SbxINT64 operator + ( const SbxINT64 &l, const SbxINT64 &r )
+{
+ SbxINT64 a(l);
+ a += r;
+ return a;
+}
+SbxINT64 operator / ( const SbxINT64 &l, const SbxINT64 &r )
+{
+ SbxINT64 a(l);
+ a /= r;
+ return a;
+}
+SbxINT64 operator % ( const SbxINT64 &l, const SbxINT64 &r )
+{
+ SbxINT64 a(l);
+ a %= r;
+ return a;
+}
+SbxINT64 operator * ( const SbxINT64 &l, const SbxINT64 &r )
+{
+ SbxINT64 a(l);
+ a *= r;
+ return a;
+}
+SbxINT64 operator & ( const SbxINT64 &l, const SbxINT64 &r )
+{
+ SbxINT64 a;
+ a.nHigh = r.nHigh & l.nHigh;
+ a.nLow = r.nLow & l.nLow;
+ return a;
+}
+SbxINT64 operator | ( const SbxINT64 &l, const SbxINT64 &r )
+{
+ SbxINT64 a;
+ a.nHigh = r.nHigh | l.nHigh;
+ a.nLow = r.nLow | l.nLow;
+ return a;
+}
+SbxINT64 operator ^ ( const SbxINT64 &r, const SbxINT64 &l )
+{
+ SbxINT64 a;
+ a.nHigh = r.nHigh ^ l.nHigh;
+ a.nLow = r.nLow ^ l.nLow;
+ return a;
+}
+
+SbxINT64 operator - ( const SbxINT64 &r )
+{
+ SbxINT64 a( r );
+ a.CHS();
+ return a;
+}
+SbxINT64 operator ~ ( const SbxINT64 &r )
+{
+ SbxINT64 a;
+ a.nHigh = ~r.nHigh;
+ a.nLow = ~r.nLow;
+ return a;
+}
+
+SbxUINT64 &SbxUINT64::operator %= ( const SbxUINT64 &r )
+{
+ BigInt b( *this );
+ b %= BigInt( r );
+ b.UINT64( this );
+ return *this;
+}
+SbxUINT64 &SbxUINT64::operator /= ( const SbxUINT64 &r )
+{
+ BigInt b( *this );
+ b /= BigInt( r );
+ b.UINT64( this );
+ return *this;
+}
+/////////////////////////// Error processing /////////////////////////////
+
+#ifdef _USED
+// STILL Reverse ENGINEERING!
+
+// The default handling sets the error code only.
+
+#ifndef WNT
+#if defined ( UNX )
+int matherr( struct exception* p )
+#else
+int matherr( struct _exception* p )
+#endif
+{
+ switch( p->type )
+ {
+#if defined ( UNX )
+ case OVERFLOW: SbxBase::SetError( SbxERR_OVERFLOW ); break;
+#else
+ case _OVERFLOW: SbxBase::SetError( SbxERR_OVERFLOW ); break;
+#endif
+ default: SbxBase::SetError( SbxERR_NOTIMP ); break;
+ }
+ return TRUE;
+}
+#endif
+
+#endif // _USED
+
+
+///////////////////////////// constructors //////////////////////////////
+
+SbxValue::SbxValue() : SbxBase()
+{
+ aData.eType = SbxEMPTY;
+}
+
+SbxValue::SbxValue( SbxDataType t, void* p ) : SbxBase()
+{
+ int n = t & 0x0FFF;
+ if( p )
+ n |= SbxBYREF;
+ if( n == SbxVARIANT )
+ n = SbxEMPTY;
+ else
+ SetFlag( SBX_FIXED );
+ if( p )
+ switch( t & 0x0FFF )
+ {
+ case SbxINTEGER: n |= SbxBYREF; aData.pInteger = (INT16*) p; break;
+ case SbxULONG64: n |= SbxBYREF; aData.pULong64 = (SbxUINT64*) p; break;
+ case SbxLONG64:
+ case SbxCURRENCY: n |= SbxBYREF; aData.pLong64 = (SbxINT64*) p; break;
+ case SbxLONG: n |= SbxBYREF; aData.pLong = (INT32*) p; break;
+ case SbxSINGLE: n |= SbxBYREF; aData.pSingle = (float*) p; break;
+ case SbxDATE:
+ case SbxDOUBLE: n |= SbxBYREF; aData.pDouble = (double*) p; break;
+ case SbxSTRING: n |= SbxBYREF; aData.pOUString = (::rtl::OUString*) p; break;
+ case SbxERROR:
+ case SbxUSHORT:
+ case SbxBOOL: n |= SbxBYREF; aData.pUShort = (UINT16*) p; break;
+ case SbxULONG: n |= SbxBYREF; aData.pULong = (UINT32*) p; break;
+ case SbxCHAR: n |= SbxBYREF; aData.pChar = (xub_Unicode*) p; break;
+ case SbxBYTE: n |= SbxBYREF; aData.pByte = (BYTE*) p; break;
+ case SbxINT: n |= SbxBYREF; aData.pInt = (int*) p; break;
+ case SbxOBJECT:
+ aData.pObj = (SbxBase*) p;
+ if( p )
+ aData.pObj->AddRef();
+ break;
+ case SbxDECIMAL:
+ aData.pDecimal = (SbxDecimal*) p;
+ if( p )
+ aData.pDecimal->addRef();
+ break;
+ default:
+ DBG_ASSERT( !this, "Angabe eines Pointers unzulaessig" );
+ n = SbxNULL;
+ }
+ else
+ memset( &aData, 0, sizeof( SbxValues ) );
+ aData.eType = SbxDataType( n );
+}
+
+SbxValue::SbxValue( const SbxValue& r )
+ : SvRefBase( r ), SbxBase( r )
+{
+ if( !r.CanRead() )
+ {
+ SetError( SbxERR_PROP_WRITEONLY );
+ if( !IsFixed() )
+ aData.eType = SbxNULL;
+ }
+ else
+ {
+ ((SbxValue*) &r)->Broadcast( SBX_HINT_DATAWANTED );
+ aData = r.aData;
+ // Copy pointer, increment references
+ switch( aData.eType )
+ {
+ case SbxSTRING:
+ if( aData.pOUString )
+ aData.pOUString = new ::rtl::OUString( *aData.pOUString );
+ break;
+ case SbxOBJECT:
+ if( aData.pObj )
+ aData.pObj->AddRef();
+ break;
+ case SbxDECIMAL:
+ if( aData.pDecimal )
+ aData.pDecimal->addRef();
+ break;
+ default: break;
+ }
+ }
+}
+
+SbxValue& SbxValue::operator=( const SbxValue& r )
+{
+ if( &r != this )
+ {
+ if( !CanWrite() )
+ SetError( SbxERR_PROP_READONLY );
+ else
+ {
+ // string -> byte array
+ if( IsFixed() && (aData.eType == SbxOBJECT)
+ && aData.pObj && ( aData.pObj->GetType() == (SbxARRAY | SbxBYTE) )
+ && (r.aData.eType == SbxSTRING) )
+ {
+ ::rtl::OUString aStr = r.GetString();
+ SbxArray* pArr = StringToByteArray(aStr);
+ PutObject(pArr);
+ return *this;
+ }
+ // byte array -> string
+ if( r.IsFixed() && (r.aData.eType == SbxOBJECT)
+ && r.aData.pObj && ( r.aData.pObj->GetType() == (SbxARRAY | SbxBYTE) )
+ && (aData.eType == SbxSTRING) )
+ {
+ SbxBase* pObj = r.GetObject();
+ SbxArray* pArr = PTR_CAST(SbxArray, pObj);
+ if( pArr )
+ {
+ ::rtl::OUString aStr = ByteArrayToString( pArr );
+ PutString(aStr);
+ return *this;
+ }
+ }
+ // Readout the content of the variables
+ SbxValues aNew;
+ if( IsFixed() )
+ // firm: then the type had to match
+ aNew.eType = aData.eType;
+ else if( r.IsFixed() )
+ // Source firm: take over the type
+ aNew.eType = SbxDataType( r.aData.eType & 0x0FFF );
+ else
+ // both variant: then it is equal
+ aNew.eType = SbxVARIANT;
+ if( r.Get( aNew ) )
+ Put( aNew );
+ }
+ }
+ return *this;
+}
+
+SbxValue::~SbxValue()
+{
+#ifndef C50
+ Broadcast( SBX_HINT_DYING );
+ SetFlag( SBX_WRITE );
+ SbxValue::Clear();
+#else
+ // Provisional fix for the Solaris 5.0 compiler bbug
+ // at using virtual inheritance. Avoid virtual calls
+ // in the destructor. Instead of calling clear()
+ // de-allocate posible object references direct.
+ if( aData.eType == SbxOBJECT )
+ {
+ if( aData.pObj && aData.pObj != this )
+ {
+ HACK(nicht bei Parent-Prop - sonst CyclicRef)
+ SbxVariable *pThisVar = PTR_CAST(SbxVariable, this);
+ BOOL bParentProp = pThisVar && 5345 ==
+ ( (INT16) ( pThisVar->GetUserData() & 0xFFFF ) );
+ if ( !bParentProp )
+ aData.pObj->ReleaseRef();
+ }
+ }
+ else if( aData.eType == SbxDECIMAL )
+ {
+ releaseDecimalPtr( aData.pDecimal );
+ }
+#endif
+}
+
+void SbxValue::Clear()
+{
+ switch( aData.eType )
+ {
+ case SbxNULL:
+ case SbxEMPTY:
+ case SbxVOID:
+ break;
+ case SbxSTRING:
+ delete aData.pOUString; aData.pOUString = NULL;
+ break;
+ case SbxOBJECT:
+ if( aData.pObj )
+ {
+ if( aData.pObj != this )
+ {
+ HACK(nicht bei Parent-Prop - sonst CyclicRef)
+ SbxVariable *pThisVar = PTR_CAST(SbxVariable, this);
+ BOOL bParentProp = pThisVar && 5345 ==
+ ( (INT16) ( pThisVar->GetUserData() & 0xFFFF ) );
+ if ( !bParentProp )
+ aData.pObj->ReleaseRef();
+ }
+ aData.pObj = NULL;
+ }
+ break;
+ case SbxDECIMAL:
+ if( aData.eType == SbxDECIMAL )
+ releaseDecimalPtr( aData.pDecimal );
+ break;
+ case SbxDATAOBJECT:
+ aData.pData = NULL; break;
+ default:
+ {
+ SbxValues aEmpty;
+ memset( &aEmpty, 0, sizeof( SbxValues ) );
+ aEmpty.eType = GetType();
+ Put( aEmpty );
+ }
+ }
+}
+
+// Dummy
+
+void SbxValue::Broadcast( ULONG )
+{}
+
+//////////////////////////// Readout data //////////////////////////////
+
+// Detect the "right" variables. If it is an object, will be addressed either
+// the object itself or its default property.
+// If the variable contain a variable or an object, this will be
+// addressed.
+
+SbxValue* SbxValue::TheRealValue() const
+{
+ return TheRealValue( TRUE );
+}
+
+// #55226 ship additional information
+SbxValue* SbxValue::TheRealValue( BOOL bObjInObjError ) const
+{
+ SbxValue* p = (SbxValue*) this;
+ for( ;; )
+ {
+ SbxDataType t = SbxDataType( p->aData.eType & 0x0FFF );
+ if( t == SbxOBJECT )
+ {
+ // The block contains an object or a variable
+ SbxObject* pObj = PTR_CAST(SbxObject,p->aData.pObj);
+ if( pObj )
+ {
+ // Has the object a default property?
+ SbxVariable* pDflt = pObj->GetDfltProperty();
+
+ // If this is an object and contains itself,
+ // we cannot access on it
+ // #55226# The old condition to set an error
+ // is not correct, because e.g. a regular variant variable with an object
+ // could be affected thereof, if another value should be assigned.
+ // Therefore with flag.
+ if( bObjInObjError && !pDflt &&
+ ((SbxValue*) pObj)->aData.eType == SbxOBJECT &&
+ ((SbxValue*) pObj)->aData.pObj == pObj )
+ {
+ SetError( SbxERR_BAD_PROP_VALUE );
+ p = NULL;
+ }
+ else if( pDflt )
+ p = pDflt;
+ /* ALT:
+ else
+ p = pDflt ? pDflt : (SbxVariable*) pObj;
+ */
+ break;
+ }
+ // Did we have an array?
+ SbxArray* pArray = PTR_CAST(SbxArray,p->aData.pObj);
+ if( pArray )
+ {
+ // When indicated get the parameter
+ SbxArray* pPar = NULL;
+ SbxVariable* pVar = PTR_CAST(SbxVariable,p);
+ if( pVar )
+ pPar = pVar->GetParameters();
+ if( pPar )
+ {
+ // Did we have a dimensioned array?
+ SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,p->aData.pObj);
+ if( pDimArray )
+ p = pDimArray->Get( pPar );
+ else
+ p = pArray->Get( pPar->Get( 1 )->GetInteger() );
+ break;
+ }
+ }
+ // Elsewise guess a SbxValue
+ SbxValue* pVal = PTR_CAST(SbxValue,p->aData.pObj);
+ if( pVal )
+ p = pVal;
+ else
+ break;
+ }
+ else
+ break;
+ }
+ return p;
+}
+
+BOOL SbxValue::Get( SbxValues& rRes ) const
+{
+ BOOL bRes = FALSE;
+ SbxError eOld = GetError();
+ if( eOld != SbxERR_OK )
+ ResetError();
+ if( !CanRead() )
+ {
+ SetError( SbxERR_PROP_WRITEONLY );
+ rRes.pObj = NULL;
+ }
+ else
+ {
+ // If there was asked for an object or a VARIANT, don't search
+ // the real values
+ SbxValue* p = (SbxValue*) this;
+ if( rRes.eType != SbxOBJECT && rRes.eType != SbxVARIANT )
+ p = TheRealValue();
+ if( p )
+ {
+ p->Broadcast( SBX_HINT_DATAWANTED );
+ switch( rRes.eType )
+ {
+ case SbxEMPTY:
+ case SbxVOID:
+ case SbxNULL: break;
+ case SbxVARIANT: rRes = p->aData; break;
+ case SbxINTEGER: rRes.nInteger = ImpGetInteger( &p->aData ); break;
+ case SbxLONG: rRes.nLong = ImpGetLong( &p->aData ); break;
+ case SbxSALINT64: rRes.nInt64 = ImpGetInt64( &p->aData ); break;
+ case SbxSALUINT64: rRes.uInt64 = ImpGetUInt64( &p->aData ); break;
+ case SbxSINGLE: rRes.nSingle = ImpGetSingle( &p->aData ); break;
+ case SbxDOUBLE: rRes.nDouble = ImpGetDouble( &p->aData ); break;
+ case SbxCURRENCY:rRes.nLong64 = ImpGetCurrency( &p->aData ); break;
+ case SbxDECIMAL: rRes.pDecimal = ImpGetDecimal( &p->aData ); break;
+ case SbxDATE: rRes.nDouble = ImpGetDate( &p->aData ); break;
+ case SbxBOOL:
+ rRes.nUShort = sal::static_int_cast< UINT16 >(
+ ImpGetBool( &p->aData ) );
+ break;
+ case SbxCHAR: rRes.nChar = ImpGetChar( &p->aData ); break;
+ case SbxBYTE: rRes.nByte = ImpGetByte( &p->aData ); break;
+ case SbxUSHORT: rRes.nUShort = ImpGetUShort( &p->aData ); break;
+ case SbxULONG: rRes.nULong = ImpGetULong( &p->aData ); break;
+ case SbxLPSTR:
+ case SbxSTRING: p->aPic = ImpGetString( &p->aData );
+ rRes.pOUString = &p->aPic; break;
+ case SbxCoreSTRING: p->aPic = ImpGetCoreString( &p->aData );
+ rRes.pOUString = &p->aPic; break;
+ case SbxINT:
+#if SAL_TYPES_SIZEOFINT == 2
+ rRes.nInt = (int) ImpGetInteger( &p->aData );
+#else
+ rRes.nInt = (int) ImpGetLong( &p->aData );
+#endif
+ break;
+ case SbxUINT:
+#if SAL_TYPES_SIZEOFINT == 2
+ rRes.nUInt = (int) ImpGetUShort( &p->aData );
+#else
+ rRes.nUInt = (int) ImpGetULong( &p->aData );
+#endif
+ break;
+ case SbxOBJECT:
+ if( p->aData.eType == SbxOBJECT )
+ rRes.pObj = p->aData.pObj;
+ else
+ {
+ SetError( SbxERR_NO_OBJECT );
+ rRes.pObj = NULL;
+ }
+ break;
+ default:
+ if( p->aData.eType == rRes.eType )
+ rRes = p->aData;
+ else
+ {
+ SetError( SbxERR_CONVERSION );
+ rRes.pObj = NULL;
+ }
+ }
+ }
+ else
+ {
+ // Object contained itself
+ SbxDataType eTemp = rRes.eType;
+ memset( &rRes, 0, sizeof( SbxValues ) );
+ rRes.eType = eTemp;
+ }
+ }
+ if( !IsError() )
+ {
+ bRes = TRUE;
+ if( eOld != SbxERR_OK )
+ SetError( eOld );
+ }
+ return bRes;
+}
+
+BOOL SbxValue::GetNoBroadcast( SbxValues& rRes )
+{
+ USHORT nFlags_ = GetFlags();
+ SetFlag( SBX_NO_BROADCAST );
+ BOOL bRes = Get( rRes );
+ SetFlags( nFlags_ );
+ return bRes;
+}
+
+const XubString& SbxValue::GetString() const
+{
+ SbxValues aRes;
+ aRes.eType = SbxSTRING;
+ if( Get( aRes ) )
+ ((SbxValue*) this)->aToolString = *aRes.pOUString;
+ else
+ ((SbxValue*) this)->aToolString.Erase();
+
+ return aToolString;
+}
+
+const XubString& SbxValue::GetCoreString() const
+{
+ SbxValues aRes;
+ aRes.eType = SbxCoreSTRING;
+ if( Get( aRes ) )
+ ((SbxValue*) this)->aToolString = *aRes.pOUString;
+ else
+ ((SbxValue*) this)->aToolString.Erase();
+
+ return aToolString;
+}
+
+::rtl::OUString SbxValue::GetOUString() const
+{
+ ::rtl::OUString aResult;
+ SbxValues aRes;
+ aRes.eType = SbxSTRING;
+ if( Get( aRes ) )
+ aResult = *aRes.pOUString;
+
+ return aResult;
+}
+
+BOOL SbxValue::HasObject() const
+{
+ ErrCode eErr = GetError();
+ SbxValues aRes;
+ aRes.eType = SbxOBJECT;
+ Get( aRes );
+ SetError( eErr );
+ return 0 != aRes.pObj;
+}
+
+BOOL SbxValue::GetBool() const
+{
+ SbxValues aRes;
+ aRes.eType = SbxBOOL;
+ Get( aRes );
+ return BOOL( aRes.nUShort != 0 );
+}
+
+#define GET( g, e, t, m ) \
+t SbxValue::g() const { SbxValues aRes(e); Get( aRes ); return aRes.m; }
+
+GET( GetByte, SbxBYTE, BYTE, nByte )
+GET( GetChar, SbxCHAR, xub_Unicode, nChar )
+GET( GetCurrency, SbxCURRENCY, SbxINT64, nLong64 )
+GET( GetDate, SbxDATE, double, nDouble )
+GET( GetData, SbxDATAOBJECT, void*, pData )
+GET( GetDouble, SbxDOUBLE, double, nDouble )
+GET( GetErr, SbxERROR, UINT16, nUShort )
+GET( GetInt, SbxINT, int, nInt )
+GET( GetInteger, SbxINTEGER, INT16, nInteger )
+GET( GetLong, SbxLONG, INT32, nLong )
+GET( GetLong64, SbxLONG64, SbxINT64, nLong64 )
+GET( GetObject, SbxOBJECT, SbxBase*, pObj )
+GET( GetSingle, SbxSINGLE, float, nSingle )
+GET( GetULong, SbxULONG, UINT32, nULong )
+GET( GetULong64, SbxULONG64, SbxUINT64, nULong64 )
+GET( GetUShort, SbxUSHORT, UINT16, nUShort )
+GET( GetInt64, SbxSALINT64, sal_Int64, nInt64 )
+GET( GetUInt64, SbxSALUINT64, sal_uInt64, uInt64 )
+GET( GetDecimal, SbxDECIMAL, SbxDecimal*, pDecimal )
+
+
+//////////////////////////// Write data /////////////////////////////
+
+BOOL SbxValue::Put( const SbxValues& rVal )
+{
+ BOOL bRes = FALSE;
+ SbxError eOld = GetError();
+ if( eOld != SbxERR_OK )
+ ResetError();
+ if( !CanWrite() )
+ SetError( SbxERR_PROP_READONLY );
+ else if( rVal.eType & 0xF000 )
+ SetError( SbxERR_NOTIMP );
+ else
+ {
+ // If there was asked for an object, don't search
+ // the real values
+ SbxValue* p = this;
+ if( rVal.eType != SbxOBJECT )
+ p = TheRealValue( FALSE ); // #55226 Don't allow an error here
+ if( p )
+ {
+ if( !p->CanWrite() )
+ SetError( SbxERR_PROP_READONLY );
+ else if( p->IsFixed() || p->SetType( (SbxDataType) ( rVal.eType & 0x0FFF ) ) )
+ switch( rVal.eType & 0x0FFF )
+ {
+ case SbxEMPTY:
+ case SbxVOID:
+ case SbxNULL: break;
+ case SbxINTEGER: ImpPutInteger( &p->aData, rVal.nInteger ); break;
+ case SbxLONG: ImpPutLong( &p->aData, rVal.nLong ); break;
+ case SbxSALINT64: ImpPutInt64( &p->aData, rVal.nInt64 ); break;
+ case SbxSALUINT64: ImpPutUInt64( &p->aData, rVal.uInt64 ); break;
+ case SbxSINGLE: ImpPutSingle( &p->aData, rVal.nSingle ); break;
+ case SbxDOUBLE: ImpPutDouble( &p->aData, rVal.nDouble ); break;
+ case SbxCURRENCY: ImpPutCurrency( &p->aData, rVal.nLong64 ); break;
+ case SbxDECIMAL: ImpPutDecimal( &p->aData, rVal.pDecimal ); break;
+ case SbxDATE: ImpPutDate( &p->aData, rVal.nDouble ); break;
+ case SbxBOOL: ImpPutBool( &p->aData, rVal.nInteger ); break;
+ case SbxCHAR: ImpPutChar( &p->aData, rVal.nChar ); break;
+ case SbxBYTE: ImpPutByte( &p->aData, rVal.nByte ); break;
+ case SbxUSHORT: ImpPutUShort( &p->aData, rVal.nUShort ); break;
+ case SbxULONG: ImpPutULong( &p->aData, rVal.nULong ); break;
+ case SbxLPSTR:
+ case SbxSTRING: ImpPutString( &p->aData, rVal.pOUString ); break;
+ case SbxINT:
+#if SAL_TYPES_SIZEOFINT == 2
+ ImpPutInteger( &p->aData, (INT16) rVal.nInt );
+#else
+ ImpPutLong( &p->aData, (INT32) rVal.nInt );
+#endif
+ break;
+ case SbxUINT:
+#if SAL_TYPES_SIZEOFINT == 2
+ ImpPutUShort( &p->aData, (UINT16) rVal.nUInt );
+#else
+ ImpPutULong( &p->aData, (UINT32) rVal.nUInt );
+#endif
+ break;
+ case SbxOBJECT:
+ if( !p->IsFixed() || p->aData.eType == SbxOBJECT )
+ {
+ // is already inside
+ if( p->aData.eType == SbxOBJECT && p->aData.pObj == rVal.pObj )
+ break;
+
+ // Delete only the value part!
+ p->SbxValue::Clear();
+
+ // real allocation
+ p->aData.pObj = rVal.pObj;
+
+ // if necessary cont in Ref-Count
+ if( p->aData.pObj && p->aData.pObj != p )
+ {
+ if ( p != this )
+ {
+ DBG_ERROR( "TheRealValue" );
+ }
+ HACK(nicht bei Parent-Prop - sonst CyclicRef)
+ SbxVariable *pThisVar = PTR_CAST(SbxVariable, this);
+ BOOL bParentProp = pThisVar && 5345 ==
+ ( (INT16) ( pThisVar->GetUserData() & 0xFFFF ) );
+ if ( !bParentProp )
+ p->aData.pObj->AddRef();
+ }
+ }
+ else
+ SetError( SbxERR_CONVERSION );
+ break;
+ default:
+ if( p->aData.eType == rVal.eType )
+ p->aData = rVal;
+ else
+ {
+ SetError( SbxERR_CONVERSION );
+ if( !p->IsFixed() )
+ p->aData.eType = SbxNULL;
+ }
+ }
+ if( !IsError() )
+ {
+ p->SetModified( TRUE );
+ p->Broadcast( SBX_HINT_DATACHANGED );
+ if( eOld != SbxERR_OK )
+ SetError( eOld );
+ bRes = TRUE;
+ }
+ }
+ }
+ return bRes;
+}
+
+// From 1996-03-28:
+// Method to execute a pretreatment of the strings at special types.
+// In particular necessary for BASIC-IDE, so that
+// the output in the Watch-Window can be writen back with PutStringExt,
+// if Float were declared with ',' as the decimal seperator or BOOl
+// explicit with "TRUE" or "FALSE".
+// Implementation in ImpConvStringExt (SBXSCAN.CXX)
+BOOL SbxValue::PutStringExt( const ::rtl::OUString& r )
+{
+ // Copy; if it is Unicode convert it immediately
+ ::rtl::OUString aStr( r );
+
+ // Identify the own type (not as in Put() with TheRealValue(),
+ // Objects are not handled anyway)
+ SbxDataType eTargetType = SbxDataType( aData.eType & 0x0FFF );
+
+ // tinker a Source-Value
+ SbxValues aRes;
+ aRes.eType = SbxSTRING;
+
+ // Only if really something was converted, take the copy,
+ // elsewise take the original (Unicode remain)
+ BOOL bRet;
+ if( ImpConvStringExt( aStr, eTargetType ) )
+ aRes.pOUString = (::rtl::OUString*)&aStr;
+ else
+ aRes.pOUString = (::rtl::OUString*)&r;
+
+ // #34939: Set a Fixed-Flag at Strings. which contain a number, and
+ // if this has a Num-Type, so that the type will not be changed
+ USHORT nFlags_ = GetFlags();
+ if( ( eTargetType >= SbxINTEGER && eTargetType <= SbxCURRENCY ) ||
+ ( eTargetType >= SbxCHAR && eTargetType <= SbxUINT ) ||
+ eTargetType == SbxBOOL )
+ {
+ SbxValue aVal;
+ aVal.Put( aRes );
+ if( aVal.IsNumeric() )
+ SetFlag( SBX_FIXED );
+ }
+
+ Put( aRes );
+ bRet = BOOL( !IsError() );
+
+ // If it throwed an error with FIXED, set it back
+ // (UI-Action should not cast an error, but only fail)
+ if( !bRet )
+ ResetError();
+
+ SetFlags( nFlags_ );
+ return bRet;
+}
+
+BOOL SbxValue::PutString( const xub_Unicode* p )
+{
+ ::rtl::OUString aVal( p );
+ SbxValues aRes;
+ aRes.eType = SbxSTRING;
+ aRes.pOUString = &aVal;
+ Put( aRes );
+ return BOOL( !IsError() );
+}
+
+BOOL SbxValue::PutBool( BOOL b )
+{
+ SbxValues aRes;
+ aRes.eType = SbxBOOL;
+ aRes.nUShort = sal::static_int_cast< UINT16 >(b ? SbxTRUE : SbxFALSE);
+ Put( aRes );
+ return BOOL( !IsError() );
+}
+
+BOOL SbxValue::PutEmpty()
+{
+ BOOL bRet = SetType( SbxEMPTY );
+ SetModified( TRUE );
+ return bRet;
+}
+
+BOOL SbxValue::PutNull()
+{
+ BOOL bRet = SetType( SbxNULL );
+ if( bRet )
+ SetModified( TRUE );
+ return bRet;
+}
+
+
+// Special decimal methods
+BOOL SbxValue::PutDecimal( com::sun::star::bridge::oleautomation::Decimal& rAutomationDec )
+{
+ SbxValue::Clear();
+ aData.pDecimal = new SbxDecimal( rAutomationDec );
+ aData.pDecimal->addRef();
+ aData.eType = SbxDECIMAL;
+ return TRUE;
+}
+
+BOOL SbxValue::fillAutomationDecimal
+ ( com::sun::star::bridge::oleautomation::Decimal& rAutomationDec )
+{
+ SbxDecimal* pDecimal = GetDecimal();
+ if( pDecimal != NULL )
+ {
+ pDecimal->fillAutomationDecimal( rAutomationDec );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+BOOL SbxValue::PutpChar( const xub_Unicode* p )
+{
+ ::rtl::OUString aVal( p );
+ SbxValues aRes;
+ aRes.eType = SbxLPSTR;
+ aRes.pOUString = &aVal;
+ Put( aRes );
+ return BOOL( !IsError() );
+}
+
+BOOL SbxValue::PutString( const ::rtl::OUString& r )
+{
+ SbxValues aRes;
+ aRes.eType = SbxSTRING;
+ aRes.pOUString = (::rtl::OUString*) &r;
+ Put( aRes );
+ return BOOL( !IsError() );
+}
+
+
+#define PUT( p, e, t, m ) \
+BOOL SbxValue::p( t n ) \
+{ SbxValues aRes(e); aRes.m = n; Put( aRes ); return BOOL( !IsError() ); }
+
+PUT( PutByte, SbxBYTE, BYTE, nByte )
+PUT( PutChar, SbxCHAR, xub_Unicode, nChar )
+PUT( PutCurrency, SbxCURRENCY, const SbxINT64&, nLong64 )
+PUT( PutDate, SbxDATE, double, nDouble )
+PUT( PutData, SbxDATAOBJECT, void*, pData )
+PUT( PutDouble, SbxDOUBLE, double, nDouble )
+PUT( PutErr, SbxERROR, UINT16, nUShort )
+PUT( PutInt, SbxINT, int, nInt )
+PUT( PutInteger, SbxINTEGER, INT16, nInteger )
+PUT( PutLong, SbxLONG, INT32, nLong )
+PUT( PutLong64, SbxLONG64, const SbxINT64&, nLong64 )
+PUT( PutObject, SbxOBJECT, SbxBase*, pObj )
+PUT( PutSingle, SbxSINGLE, float, nSingle )
+PUT( PutULong, SbxULONG, UINT32, nULong )
+PUT( PutULong64, SbxULONG64, const SbxUINT64&, nULong64 )
+PUT( PutUShort, SbxUSHORT, UINT16, nUShort )
+PUT( PutInt64, SbxSALINT64, sal_Int64, nInt64 )
+PUT( PutUInt64, SbxSALUINT64, sal_uInt64, uInt64 )
+PUT( PutDecimal, SbxDECIMAL, SbxDecimal*, pDecimal )
+
+
+////////////////////////// Setting of the data type ///////////////////////////
+
+BOOL SbxValue::IsFixed() const
+{
+ return ( (GetFlags() & SBX_FIXED) | (aData.eType & SbxBYREF) ) != 0;
+}
+
+// A variable is numeric, if it is EMPTY or realy numeric
+// or if it contains a complete convertible String
+
+// #41692, implement it for RTL and Basic-Core seperably
+BOOL SbxValue::IsNumeric() const
+{
+ return ImpIsNumeric( /*bOnlyIntntl*/FALSE );
+}
+
+BOOL SbxValue::IsNumericRTL() const
+{
+ return ImpIsNumeric( /*bOnlyIntntl*/TRUE );
+}
+
+BOOL SbxValue::ImpIsNumeric( BOOL bOnlyIntntl ) const
+{
+
+ if( !CanRead() )
+ {
+ SetError( SbxERR_PROP_WRITEONLY ); return FALSE;
+ }
+ // Test downcast!!!
+ if( this->ISA(SbxVariable) )
+ ((SbxVariable*)this)->Broadcast( SBX_HINT_DATAWANTED );
+ SbxDataType t = GetType();
+ if( t == SbxSTRING )
+ {
+ if( aData.pOUString )
+ {
+ ::rtl::OUString s( *aData.pOUString );
+ double n;
+ SbxDataType t2;
+ USHORT nLen = 0;
+ if( ImpScan( s, n, t2, &nLen, /*bAllowIntntl*/FALSE, bOnlyIntntl ) == SbxERR_OK )
+ return BOOL( nLen == s.getLength() );
+ }
+ return FALSE;
+ }
+ else
+ return BOOL( t == SbxEMPTY
+ || ( t >= SbxINTEGER && t <= SbxCURRENCY )
+ || ( t >= SbxCHAR && t <= SbxUINT ) );
+}
+
+SbxClassType SbxValue::GetClass() const
+{
+ return SbxCLASS_VALUE;
+}
+
+SbxDataType SbxValue::GetType() const
+{
+ return SbxDataType( aData.eType & 0x0FFF );
+}
+
+SbxDataType SbxValue::GetFullType() const
+{
+ return aData.eType;
+}
+
+BOOL SbxValue::SetType( SbxDataType t )
+{
+ DBG_ASSERT( !( t & 0xF000 ), "Setzen von BYREF|ARRAY verboten!" );
+ if( ( t == SbxEMPTY && aData.eType == SbxVOID )
+ || ( aData.eType == SbxEMPTY && t == SbxVOID ) )
+ return TRUE;
+ if( ( t & 0x0FFF ) == SbxVARIANT )
+ {
+ // Trial to set the data type to Variant
+ ResetFlag( SBX_FIXED );
+ if( IsFixed() )
+ {
+ SetError( SbxERR_CONVERSION ); return FALSE;
+ }
+ t = SbxEMPTY;
+ }
+ if( ( t & 0x0FFF ) != ( aData.eType & 0x0FFF ) )
+ {
+ if( !CanWrite() || IsFixed() )
+ {
+ SetError( SbxERR_CONVERSION ); return FALSE;
+ }
+ else
+ {
+ // De-allocate potential objects
+ switch( aData.eType )
+ {
+ case SbxSTRING:
+ delete aData.pOUString;
+ break;
+ case SbxOBJECT:
+ if( aData.pObj && aData.pObj != this )
+ {
+ HACK(nicht bei Parent-Prop - sonst CyclicRef)
+ SbxVariable *pThisVar = PTR_CAST(SbxVariable, this);
+ UINT16 nSlotId = pThisVar
+ ? ( (INT16) ( pThisVar->GetUserData() & 0xFFFF ) )
+ : 0;
+ DBG_ASSERT( nSlotId != 5345 || pThisVar->GetName() == UniString::CreateFromAscii( "Parent" ),
+ "SID_PARENTOBJECT heisst nicht 'Parent'" );
+ BOOL bParentProp = 5345 == nSlotId;
+ if ( !bParentProp )
+ aData.pObj->ReleaseRef();
+ }
+ break;
+ default: break;
+ }
+ // This works always, because the Float representations are 0 as well.
+ memset( &aData, 0, sizeof( SbxValues ) );
+ aData.eType = t;
+ }
+ }
+ return TRUE;
+}
+
+BOOL SbxValue::Convert( SbxDataType eTo )
+{
+ eTo = SbxDataType( eTo & 0x0FFF );
+ if( ( aData.eType & 0x0FFF ) == eTo )
+ return TRUE;
+ if( !CanWrite() )
+ return FALSE;
+ if( eTo == SbxVARIANT )
+ {
+ // Trial to set the data type to Variant
+ ResetFlag( SBX_FIXED );
+ if( IsFixed() )
+ {
+ SetError( SbxERR_CONVERSION ); return FALSE;
+ }
+ else
+ return TRUE;
+ }
+ // Converting from zero doesn't work. Once zero, always zero!
+ if( aData.eType == SbxNULL )
+ {
+ SetError( SbxERR_CONVERSION ); return FALSE;
+ }
+
+ // Conversion of the data:
+ SbxValues aNew;
+ aNew.eType = eTo;
+ if( Get( aNew ) )
+ {
+ // The data type could be converted. It ends here with fixed elements,
+ // because the data had not to be taken over
+ if( !IsFixed() )
+ {
+ SetType( eTo );
+ Put( aNew );
+ SetModified( TRUE );
+ }
+ Broadcast( SBX_HINT_CONVERTED );
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+////////////////////////////////// Calculating /////////////////////////////////
+
+BOOL SbxValue::Compute( SbxOperator eOp, const SbxValue& rOp )
+{
+ bool bVBAInterop = SbiRuntime::isVBAEnabled();
+
+ SbxDataType eThisType = GetType();
+ SbxDataType eOpType = rOp.GetType();
+ SbxError eOld = GetError();
+ if( eOld != SbxERR_OK )
+ ResetError();
+ if( !CanWrite() )
+ SetError( SbxERR_PROP_READONLY );
+ else if( !rOp.CanRead() )
+ SetError( SbxERR_PROP_WRITEONLY );
+ // Special rule 1: If one operand is zero, the result is zero
+ else if( eThisType == SbxNULL || eOpType == SbxNULL )
+ SetType( SbxNULL );
+ // Special rule 2: If the operand is Empty, the result is the 2. operand
+ else if( eThisType == SbxEMPTY
+ && !bVBAInterop
+ )
+ *this = rOp;
+ // 1996-2-13: Don't test already before Get upon SbxEMPTY
+ else
+ {
+ SbxValues aL, aR;
+ bool bDecimal = false;
+ if( bVBAInterop && ( ( eThisType == SbxSTRING && eOpType != SbxSTRING && eOpType != SbxEMPTY ) ||
+ ( eThisType != SbxSTRING && eThisType != SbxEMPTY && eOpType == SbxSTRING ) ) &&
+ ( eOp == SbxMUL || eOp == SbxDIV || eOp == SbxPLUS || eOp == SbxMINUS ) )
+ {
+ goto Lbl_OpIsDouble;
+ }
+ else if( eThisType == SbxSTRING || eOp == SbxCAT || ( bVBAInterop && ( eOpType == SbxSTRING ) && ( eOp == SbxPLUS ) ) )
+ {
+ if( eOp == SbxCAT || eOp == SbxPLUS )
+ {
+ // From 1999-11-5, keep OUString in mind
+ aL.eType = aR.eType = SbxSTRING;
+ rOp.Get( aR );
+ // From 1999-12-8, #70399: Here call GetType() again, Get() can change the type!
+ if( rOp.GetType() == SbxEMPTY )
+ goto Lbl_OpIsEmpty;
+ Get( aL );
+
+ // #30576: To begin with test, if the conversion worked
+ if( aL.pOUString != NULL && aR.pOUString != NULL )
+ {
+ *aL.pOUString += *aR.pOUString;
+ }
+ // Not even Left OK?
+ else if( aL.pOUString == NULL )
+ {
+ aL.pOUString = new ::rtl::OUString();
+ }
+ Put( aL );
+ }
+ else
+ SetError( SbxERR_CONVERSION );
+ }
+ else if( eOpType == SbxSTRING && rOp.IsFixed() )
+ { // Numeric: there is no String allowed on the right side
+ SetError( SbxERR_CONVERSION );
+ }
+ else if( ( eOp >= SbxIDIV && eOp <= SbxNOT ) || eOp == SbxMOD )
+ {
+ if( GetType() == eOpType )
+ {
+ if( GetType() == SbxULONG64
+ || GetType() == SbxLONG64
+ || GetType() == SbxCURRENCY
+ || GetType() == SbxULONG )
+ aL.eType = aR.eType = GetType();
+// else if( GetType() == SbxDouble || GetType() == SbxSingle )
+// aL.eType = aR.eType = SbxLONG64;
+ else if ( bVBAInterop && eOpType == SbxBOOL )
+ aL.eType = aR.eType = SbxBOOL;
+ else
+ aL.eType = aR.eType = SbxLONG;
+ }
+ else if( GetType() == SbxCURRENCY || eOpType == SbxCURRENCY
+ || GetType() == SbxULONG64 || eOpType == SbxULONG64
+ || GetType() == SbxLONG64 || eOpType == SbxLONG64 )
+ aL.eType = aR.eType = SbxLONG64;
+// else if( GetType() == SbxDouble || rOP.GetType() == SbxDouble
+// || GetType() == SbxSingle || rOP.GetType() == SbxSingle )
+// aL.eType = aR.eType = SbxLONG64;
+ else
+ aL.eType = aR.eType = SbxLONG;
+
+ if( rOp.Get( aR ) )
+ {
+ if( rOp.GetType() == SbxEMPTY )
+ {
+ if ( !bVBAInterop || ( bVBAInterop && ( eOp != SbxNOT ) ) )
+ goto Lbl_OpIsEmpty;
+ }
+ if( Get( aL ) ) switch( eOp )
+ {
+ case SbxIDIV:
+ if( aL.eType == SbxCURRENCY )
+ aL.eType = SbxLONG64;
+ if( aL.eType == SbxLONG64 )
+ if( !aR.nLong64 ) SetError( SbxERR_ZERODIV );
+ else aL.nLong64 /= aR.nLong64;
+ else if( aL.eType == SbxULONG64 )
+ if( !aR.nULong64 ) SetError( SbxERR_ZERODIV );
+ else aL.nULong64 /= aR.nULong64;
+ else if( aL.eType == SbxLONG )
+ if( !aR.nLong ) SetError( SbxERR_ZERODIV );
+ else aL.nLong /= aR.nLong;
+ else
+ if( !aR.nULong ) SetError( SbxERR_ZERODIV );
+ else aL.nULong /= aR.nULong;
+ break;
+ case SbxMOD:
+ if( aL.eType == SbxCURRENCY )
+ aL.eType = SbxLONG64;
+ if( aL.eType == SbxLONG64 )
+ if( !aR.nLong64 ) SetError( SbxERR_ZERODIV );
+ else aL.nLong64 %= aR.nLong64;
+ else if( aL.eType == SbxULONG64 )
+ if( !aR.nULong64 ) SetError( SbxERR_ZERODIV );
+ else aL.nULong64 %= aR.nULong64;
+ else if( aL.eType == SbxLONG )
+ if( !aR.nLong ) SetError( SbxERR_ZERODIV );
+ else aL.nLong %= aR.nLong;
+ else
+ if( !aR.nULong ) SetError( SbxERR_ZERODIV );
+ else aL.nULong %= aR.nULong;
+ break;
+ case SbxAND:
+ if( aL.eType != SbxLONG && aL.eType != SbxULONG )
+ aL.nLong64 &= aR.nLong64;
+ else
+ aL.nLong &= aR.nLong;
+ break;
+ case SbxOR:
+ if( aL.eType != SbxLONG && aL.eType != SbxULONG )
+ aL.nLong64 |= aR.nLong64;
+ else
+ aL.nLong |= aR.nLong;
+ break;
+ case SbxXOR:
+ if( aL.eType != SbxLONG && aL.eType != SbxULONG )
+ aL.nLong64 ^= aR.nLong64;
+ else
+ aL.nLong ^= aR.nLong;
+ break;
+ case SbxEQV:
+ if( aL.eType != SbxLONG && aL.eType != SbxULONG )
+ aL.nLong64 = (aL.nLong64 & aR.nLong64) | (~aL.nLong64 & ~aR.nLong64);
+ else
+ aL.nLong = (aL.nLong & aR.nLong) | (~aL.nLong & ~aR.nLong);
+ break;
+ case SbxIMP:
+ if( aL.eType != SbxLONG && aL.eType != SbxULONG )
+ aL.nLong64 = ~aL.nLong64 | aR.nLong64;
+ else
+ aL.nLong = ~aL.nLong | aR.nLong;
+ break;
+ case SbxNOT:
+ if( aL.eType != SbxLONG && aL.eType != SbxULONG )
+ {
+ if ( aL.eType != SbxBOOL )
+ aL.nLong64 = ~aL.nLong64;
+ else
+ aL.nLong = ~aL.nLong;
+ }
+ else
+ aL.nLong = ~aL.nLong;
+ break;
+ default: break;
+ }
+ }
+ }
+ else if( ( GetType() == SbxDECIMAL || rOp.GetType() == SbxDECIMAL ) &&
+ ( eOp == SbxMUL || eOp == SbxDIV || eOp == SbxPLUS || eOp == SbxMINUS || eOp == SbxNEG ) )
+ {
+ aL.eType = aR.eType = SbxDECIMAL;
+ bDecimal = true;
+ if( rOp.Get( aR ) )
+ {
+ if( rOp.GetType() == SbxEMPTY )
+ {
+ releaseDecimalPtr( aL.pDecimal );
+ goto Lbl_OpIsEmpty;
+ }
+ if( Get( aL ) )
+ {
+ if( aL.pDecimal && aR.pDecimal )
+ {
+ bool bOk = true;
+ switch( eOp )
+ {
+ case SbxMUL:
+ bOk = ( *(aL.pDecimal) *= *(aR.pDecimal) );
+ break;
+ case SbxDIV:
+ if( aR.pDecimal->isZero() )
+ SetError( SbxERR_ZERODIV );
+ else
+ bOk = ( *(aL.pDecimal) /= *(aR.pDecimal) );
+ break;
+ case SbxPLUS:
+ bOk = ( *(aL.pDecimal) += *(aR.pDecimal) );
+ break;
+ case SbxMINUS:
+ bOk = ( *(aL.pDecimal) -= *(aR.pDecimal) );
+ break;
+ case SbxNEG:
+ bOk = ( aL.pDecimal->neg() );
+ break;
+ default:
+ SetError( SbxERR_NOTIMP );
+ }
+ if( !bOk )
+ SetError( SbxERR_OVERFLOW );
+ }
+ else
+ {
+ SetError( SbxERR_CONVERSION );
+ }
+ }
+ }
+ }
+ else if( GetType() == SbxCURRENCY || rOp.GetType() == SbxCURRENCY )
+ {
+ aL.eType = SbxCURRENCY;
+ aR.eType = SbxCURRENCY;
+
+ if( rOp.Get( aR ) )
+ {
+ static BigInt n10K( 10000 );
+
+ if( rOp.GetType() == SbxEMPTY )
+ goto Lbl_OpIsEmpty;
+
+ if( Get( aL ) ) switch( eOp )
+ {
+ case SbxMUL:
+ {
+ // #i20704 Implement directly
+ BigInt b1( aL.nLong64 );
+ BigInt b2( aR.nLong64 );
+ b1 *= b2;
+ b1 /= n10K;
+ double d = double( b1 ) / 10000.0;
+ if( d > SbxMAXCURR || d < SbxMINCURR )
+ SetError( SbxERR_OVERFLOW );
+ else
+ b1.INT64( &aL.nLong64 );
+ break;
+ }
+ case SbxDIV:
+ if( !aR.nLong64 )
+ {
+ SetError( SbxERR_ZERODIV );
+ }
+ else
+ {
+ // #i20704 Implement directly
+ BigInt b1( aL.nLong64 );
+ BigInt b2( aR.nLong64 );
+ b1 *= n10K;
+ b1 /= b2;
+ double d = double( b1 ) / 10000.0;
+ if( d > SbxMAXCURR || d < SbxMINCURR )
+ SetError( SbxERR_OVERFLOW );
+ else
+ b1.INT64( &aL.nLong64 );
+ }
+ break;
+ case SbxPLUS:
+ aL.nLong64 += aR.nLong64; break;
+ case SbxMINUS:
+ aL.nLong64 -= aR.nLong64; break;
+ case SbxNEG:
+ aL.nLong64 = -aL.nLong64; break;
+ default:
+ SetError( SbxERR_NOTIMP );
+ }
+ }
+ }
+ else
+Lbl_OpIsDouble:
+ { // other operators
+ aL.eType = aR.eType = SbxDOUBLE;
+ if( rOp.Get( aR ) )
+ {
+ if( rOp.GetType() == SbxEMPTY )
+ {
+ if ( !bVBAInterop || ( bVBAInterop && ( eOp != SbxNEG ) ) )
+ goto Lbl_OpIsEmpty;
+ }
+ if( Get( aL ) )
+ {
+ switch( eOp )
+ {
+ case SbxEXP:
+ aL.nDouble = pow( aL.nDouble, aR.nDouble );
+ break;
+ case SbxMUL:
+ aL.nDouble *= aR.nDouble; break;
+ case SbxDIV:
+ if( !aR.nDouble ) SetError( SbxERR_ZERODIV );
+ else aL.nDouble /= aR.nDouble; break;
+ case SbxPLUS:
+ aL.nDouble += aR.nDouble; break;
+ case SbxMINUS:
+ aL.nDouble -= aR.nDouble; break;
+ case SbxNEG:
+ aL.nDouble = -aL.nDouble; break;
+ default:
+ SetError( SbxERR_NOTIMP );
+ }
+
+ // #45465 Date needs with "+" a special handling
+ if( eOp == SbxPLUS && (GetType() == SbxDATE || rOp.GetType() == SbxDATE ) )
+ aL.eType = SbxDATE;
+ }
+ }
+
+ }
+ if( !IsError() )
+ Put( aL );
+ if( bDecimal )
+ {
+ releaseDecimalPtr( aL.pDecimal );
+ releaseDecimalPtr( aR.pDecimal );
+ }
+ }
+Lbl_OpIsEmpty:
+
+ BOOL bRes = BOOL( !IsError() );
+ if( bRes && eOld != SbxERR_OK )
+ SetError( eOld );
+ return bRes;
+}
+
+// The comparison routine deliver TRUE or FALSE.
+
+BOOL SbxValue::Compare( SbxOperator eOp, const SbxValue& rOp ) const
+{
+ bool bVBAInterop = SbiRuntime::isVBAEnabled();
+
+ BOOL bRes = FALSE;
+ SbxError eOld = GetError();
+ if( eOld != SbxERR_OK )
+ ResetError();
+ if( !CanRead() || !rOp.CanRead() )
+ SetError( SbxERR_PROP_WRITEONLY );
+ else if( GetType() == SbxNULL && rOp.GetType() == SbxNULL && !bVBAInterop )
+ {
+ bRes = TRUE;
+ }
+ else if( GetType() == SbxEMPTY && rOp.GetType() == SbxEMPTY )
+ bRes = !bVBAInterop ? TRUE : ( eOp == SbxEQ ? TRUE : FALSE );
+ // Special rule 1: If an operand is zero, the result is FALSE
+ else if( GetType() == SbxNULL || rOp.GetType() == SbxNULL )
+ bRes = FALSE;
+ // Special rule 2: If both are variant and one is numeric
+ // and the other is a String, num is < str
+ else if( !IsFixed() && !rOp.IsFixed()
+ && ( rOp.GetType() == SbxSTRING && GetType() != SbxSTRING && IsNumeric() ) && !bVBAInterop
+ )
+ bRes = BOOL( eOp == SbxLT || eOp == SbxLE || eOp == SbxNE );
+ else if( !IsFixed() && !rOp.IsFixed()
+ && ( GetType() == SbxSTRING && rOp.GetType() != SbxSTRING && rOp.IsNumeric() )
+&& !bVBAInterop
+ )
+ bRes = BOOL( eOp == SbxGT || eOp == SbxGE || eOp == SbxNE );
+ else
+ {
+ SbxValues aL, aR;
+ // If one of the operands is a String,
+ // a String comparing take place
+ if( GetType() == SbxSTRING || rOp.GetType() == SbxSTRING )
+ {
+ aL.eType = aR.eType = SbxSTRING;
+ if( Get( aL ) && rOp.Get( aR ) ) switch( eOp )
+ {
+ case SbxEQ:
+ bRes = BOOL( *aL.pOUString == *aR.pOUString ); break;
+ case SbxNE:
+ bRes = BOOL( *aL.pOUString != *aR.pOUString ); break;
+ case SbxLT:
+ bRes = BOOL( *aL.pOUString < *aR.pOUString ); break;
+ case SbxGT:
+ bRes = BOOL( *aL.pOUString > *aR.pOUString ); break;
+ case SbxLE:
+ bRes = BOOL( *aL.pOUString <= *aR.pOUString ); break;
+ case SbxGE:
+ bRes = BOOL( *aL.pOUString >= *aR.pOUString ); break;
+ default:
+ SetError( SbxERR_NOTIMP );
+ }
+ }
+ // From 1995-12-19: If SbxSINGLE participate, then convert to SINGLE,
+ // elsewise it shows a numeric error
+ else if( GetType() == SbxSINGLE || rOp.GetType() == SbxSINGLE )
+ {
+ aL.eType = aR.eType = SbxSINGLE;
+ if( Get( aL ) && rOp.Get( aR ) )
+ switch( eOp )
+ {
+ case SbxEQ:
+ bRes = BOOL( aL.nSingle == aR.nSingle ); break;
+ case SbxNE:
+ bRes = BOOL( aL.nSingle != aR.nSingle ); break;
+ case SbxLT:
+ bRes = BOOL( aL.nSingle < aR.nSingle ); break;
+ case SbxGT:
+ bRes = BOOL( aL.nSingle > aR.nSingle ); break;
+ case SbxLE:
+ bRes = BOOL( aL.nSingle <= aR.nSingle ); break;
+ case SbxGE:
+ bRes = BOOL( aL.nSingle >= aR.nSingle ); break;
+ default:
+ SetError( SbxERR_NOTIMP );
+ }
+ }
+ else if( GetType() == SbxDECIMAL && rOp.GetType() == SbxDECIMAL )
+ {
+ aL.eType = aR.eType = SbxDECIMAL;
+ Get( aL );
+ rOp.Get( aR );
+ if( aL.pDecimal && aR.pDecimal )
+ {
+ SbxDecimal::CmpResult eRes = compare( *aL.pDecimal, *aR.pDecimal );
+ switch( eOp )
+ {
+ case SbxEQ:
+ bRes = BOOL( eRes == SbxDecimal::EQ ); break;
+ case SbxNE:
+ bRes = BOOL( eRes != SbxDecimal::EQ ); break;
+ case SbxLT:
+ bRes = BOOL( eRes == SbxDecimal::LT ); break;
+ case SbxGT:
+ bRes = BOOL( eRes == SbxDecimal::GT ); break;
+ case SbxLE:
+ bRes = BOOL( eRes != SbxDecimal::GT ); break;
+ case SbxGE:
+ bRes = BOOL( eRes != SbxDecimal::LT ); break;
+ default:
+ SetError( SbxERR_NOTIMP );
+ }
+ }
+ else
+ {
+ SetError( SbxERR_CONVERSION );
+ }
+ releaseDecimalPtr( aL.pDecimal );
+ releaseDecimalPtr( aR.pDecimal );
+ }
+ // Everything else comparing on a SbxDOUBLE-Basis
+ else
+ {
+ aL.eType = aR.eType = SbxDOUBLE;
+ //if( Get( aL ) && rOp.Get( aR ) )
+ bool bGetL = Get( aL );
+ bool bGetR = rOp.Get( aR );
+ if( bGetL && bGetR )
+ switch( eOp )
+ {
+ case SbxEQ:
+ bRes = BOOL( aL.nDouble == aR.nDouble ); break;
+ case SbxNE:
+ bRes = BOOL( aL.nDouble != aR.nDouble ); break;
+ case SbxLT:
+ bRes = BOOL( aL.nDouble < aR.nDouble ); break;
+ case SbxGT:
+ bRes = BOOL( aL.nDouble > aR.nDouble ); break;
+ case SbxLE:
+ bRes = BOOL( aL.nDouble <= aR.nDouble ); break;
+ case SbxGE:
+ bRes = BOOL( aL.nDouble >= aR.nDouble ); break;
+ default:
+ SetError( SbxERR_NOTIMP );
+ }
+ // at least one value was got
+ // if this is VBA then a conversion error for one
+ // side will yield a false result of an equality test
+ else if ( bGetR || bGetL )
+ {
+ if ( bVBAInterop && eOp == SbxEQ && GetError() == SbxERR_CONVERSION )
+ {
+ ResetError();
+ bRes = FALSE;
+ }
+ }
+ }
+ }
+ if( eOld != SbxERR_OK )
+ SetError( eOld );
+ return bRes;
+}
+
+///////////////////////////// Reading/Writing ////////////////////////////
+
+BOOL SbxValue::LoadData( SvStream& r, USHORT )
+{
+ SbxValue::Clear();
+ UINT16 nType;
+ r >> nType;
+ aData.eType = SbxDataType( nType );
+ switch( nType )
+ {
+ case SbxBOOL:
+ case SbxINTEGER:
+ r >> aData.nInteger; break;
+ case SbxLONG:
+ r >> aData.nLong; break;
+ case SbxSINGLE:
+ {
+ // Floats as ASCII
+ XubString aVal;
+ r.ReadByteString( aVal, RTL_TEXTENCODING_ASCII_US );
+ double d;
+ SbxDataType t;
+ if( ImpScan( aVal, d, t, NULL ) != SbxERR_OK || t == SbxDOUBLE )
+ {
+ aData.nSingle = 0.0F;
+ return FALSE;
+ }
+ aData.nSingle = (float) d;
+ break;
+ }
+ case SbxDATE:
+ case SbxDOUBLE:
+ {
+ // Floats as ASCII
+ XubString aVal;
+ r.ReadByteString( aVal, RTL_TEXTENCODING_ASCII_US );
+ SbxDataType t;
+ if( ImpScan( aVal, aData.nDouble, t, NULL ) != SbxERR_OK )
+ {
+ aData.nDouble = 0.0;
+ return FALSE;
+ }
+ break;
+ }
+ case SbxULONG64:
+ {
+ r >> aData.nULong64.nHigh >> aData.nULong64.nLow;
+ break;
+ }
+ case SbxLONG64:
+ case SbxCURRENCY:
+ {
+ r >> aData.nLong64.nHigh >> aData.nLong64.nLow;
+ break;
+ }
+ case SbxSTRING:
+ {
+ XubString aVal;
+ r.ReadByteString( aVal, RTL_TEXTENCODING_ASCII_US );
+ if( aVal.Len() )
+ aData.pOUString = new ::rtl::OUString( aVal );
+ else
+ aData.pOUString = NULL; // JSM 1995-09-22
+ break;
+ }
+ case SbxERROR:
+ case SbxUSHORT:
+ r >> aData.nUShort; break;
+ case SbxOBJECT:
+ {
+ BYTE nMode;
+ r >> nMode;
+ switch( nMode )
+ {
+ case 0:
+ aData.pObj = NULL;
+ break;
+ case 1:
+ aData.pObj = SbxBase::Load( r );
+ return BOOL( aData.pObj != NULL );
+ case 2:
+ aData.pObj = this;
+ break;
+ }
+ break;
+ }
+ case SbxCHAR:
+ {
+ char c;
+ r >> c;
+ aData.nChar = c;
+ break;
+ }
+ case SbxBYTE:
+ r >> aData.nByte; break;
+ case SbxULONG:
+ r >> aData.nULong; break;
+ case SbxINT:
+ {
+ BYTE n;
+ r >> n;
+ // Match the Int on this system?
+ if( n > SAL_TYPES_SIZEOFINT )
+ r >> aData.nLong, aData.eType = SbxLONG;
+ else
+ r >> aData.nInt;
+ break;
+ }
+ case SbxUINT:
+ {
+ BYTE n;
+ r >> n;
+ // Match the UInt on this system?
+ if( n > SAL_TYPES_SIZEOFINT )
+ r >> aData.nULong, aData.eType = SbxULONG;
+ else
+ r >> (sal_uInt32&)aData.nUInt;
+ break;
+ }
+ case SbxEMPTY:
+ case SbxNULL:
+ case SbxVOID:
+ break;
+ case SbxDATAOBJECT:
+ r >> aData.nLong;
+ break;
+ // #78919 For backwards compatibility
+ case SbxWSTRING:
+ case SbxWCHAR:
+ break;
+ default:
+ memset (&aData,0,sizeof(aData));
+ ResetFlag(SBX_FIXED);
+ aData.eType = SbxNULL;
+ DBG_ASSERT( !this, "Nicht unterstuetzer Datentyp geladen" );
+ return FALSE;
+ }
+ return TRUE;
+}
+
+BOOL SbxValue::StoreData( SvStream& r ) const
+{
+ UINT16 nType = sal::static_int_cast< UINT16 >(aData.eType);
+ r << nType;
+ switch( nType & 0x0FFF )
+ {
+ case SbxBOOL:
+ case SbxINTEGER:
+ r << aData.nInteger; break;
+ case SbxLONG:
+ r << aData.nLong; break;
+ case SbxDATE:
+ // #49935: Save as double, elsewise an error during the read in
+ ((SbxValue*)this)->aData.eType = (SbxDataType)( ( nType & 0xF000 ) | SbxDOUBLE );
+ r.WriteByteString( GetCoreString(), RTL_TEXTENCODING_ASCII_US );
+ ((SbxValue*)this)->aData.eType = (SbxDataType)nType;
+ break;
+ case SbxSINGLE:
+ case SbxDOUBLE:
+ r.WriteByteString( GetCoreString(), RTL_TEXTENCODING_ASCII_US );
+ break;
+ case SbxULONG64:
+ {
+ r << aData.nULong64.nHigh << aData.nULong64.nLow;
+ break;
+ }
+ case SbxLONG64:
+ case SbxCURRENCY:
+ {
+ r << aData.nLong64.nHigh << aData.nLong64.nLow;
+ break;
+ }
+ case SbxSTRING:
+ if( aData.pOUString )
+ {
+ r.WriteByteString( *aData.pOUString, RTL_TEXTENCODING_ASCII_US );
+ }
+ else
+ {
+ String aEmpty;
+ r.WriteByteString( aEmpty, RTL_TEXTENCODING_ASCII_US );
+ }
+ break;
+ case SbxERROR:
+ case SbxUSHORT:
+ r << aData.nUShort; break;
+ case SbxOBJECT:
+ // to save itself as Objektptr doesn't work!
+ if( aData.pObj )
+ {
+ if( PTR_CAST(SbxValue,aData.pObj) != this )
+ {
+ r << (BYTE) 1;
+ return aData.pObj->Store( r );
+ }
+ else
+ r << (BYTE) 2;
+ }
+ else
+ r << (BYTE) 0;
+ break;
+ case SbxCHAR:
+ {
+ char c = sal::static_int_cast< char >(aData.nChar);
+ r << c;
+ break;
+ }
+ case SbxBYTE:
+ r << aData.nByte; break;
+ case SbxULONG:
+ r << aData.nULong; break;
+ case SbxINT:
+ {
+ BYTE n = SAL_TYPES_SIZEOFINT;
+ r << n << (sal_Int32)aData.nInt;
+ break;
+ }
+ case SbxUINT:
+ {
+ BYTE n = SAL_TYPES_SIZEOFINT;
+ r << n << (sal_uInt32)aData.nUInt;
+ break;
+ }
+ case SbxEMPTY:
+ case SbxNULL:
+ case SbxVOID:
+ break;
+ case SbxDATAOBJECT:
+ r << aData.nLong;
+ break;
+ // #78919 For backwards compatibility
+ case SbxWSTRING:
+ case SbxWCHAR:
+ break;
+ default:
+ DBG_ASSERT( !this, "Speichern eines nicht unterstuetzten Datentyps" );
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/sbx/sbxvar.cxx b/basic/source/sbx/sbxvar.cxx
new file mode 100644
index 000000000000..9ea647e6730a
--- /dev/null
+++ b/basic/source/sbx/sbxvar.cxx
@@ -0,0 +1,646 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_basic.hxx"
+
+
+#include <tools/stream.hxx>
+#include "svl/brdcst.hxx"
+
+#include <basic/sbx.hxx>
+#include <basic/sbxbase.hxx>
+#include "sbxres.hxx"
+#include "sbxconv.hxx"
+#include <math.h>
+#include <ctype.h>
+
+#include "com/sun/star/uno/XInterface.hpp"
+using namespace com::sun::star::uno;
+
+///////////////////////////// SbxVariable //////////////////////////////
+
+TYPEINIT1(SbxVariable,SbxValue)
+TYPEINIT1(SbxHint,SfxSimpleHint)
+
+extern UINT32 nVarCreator; // in SBXBASE.CXX, fuer LoadData()
+#ifdef DBG_UTIL
+static ULONG nVar = 0;
+#endif
+
+///////////////////////////// SbxVariableImpl ////////////////////////////
+
+class SbxVariableImpl
+{
+ friend class SbxVariable;
+ String m_aDeclareClassName;
+ Reference< XInterface > m_xComListener;
+
+ SbxVariableImpl( void )
+ {}
+ SbxVariableImpl( const SbxVariableImpl& r )
+ : m_aDeclareClassName( r.m_aDeclareClassName )
+ , m_xComListener( r.m_xComListener )
+ {}
+};
+
+
+///////////////////////////// Constructors //////////////////////////////
+
+SbxVariable::SbxVariable() : SbxValue()
+{
+ mpSbxVariableImpl = NULL;
+ 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 )
+ : SvRefBase( r ), SbxValue( r ), mpPar( r.mpPar ), pInfo( r.pInfo )
+{
+ mpSbxVariableImpl = NULL;
+ if( r.mpSbxVariableImpl != NULL )
+ mpSbxVariableImpl = new SbxVariableImpl( *r.mpSbxVariableImpl );
+ pCst = NULL;
+ if( r.CanRead() )
+ {
+ pParent = r.pParent;
+ nUserData = r.nUserData;
+ maName = r.maName;
+ nHash = r.nHash;
+ }
+ else
+ {
+ pParent = NULL;
+ nUserData = 0;
+ nHash = 0;
+ }
+#ifdef DBG_UTIL
+ static sal_Char const aCellsStr[] = "Cells";
+ if ( maName.EqualsAscii( aCellsStr ) )
+ maName.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 )
+{
+ mpSbxVariableImpl = NULL;
+ 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&)maName, RTL_TEXTENCODING_ASCII_US );
+ DbgOutf( "SbxVariable::Dtor %lx (%s)", (void*)this, aBStr.GetBuffer() );
+ static sal_Char const aCellsStr[] = "Cells";
+ if ( maName.EqualsAscii( aCellsStr ) )
+ maName.AssignAscii( aCellsStr, sizeof( aCellsStr )-1 );
+ GetSbxData_Impl()->aVars.Remove( this );
+#endif
+ delete mpSbxVariableImpl;
+ delete pCst;
+}
+
+////////////////////////////// Broadcasting //////////////////////////////
+
+SfxBroadcaster& SbxVariable::GetBroadcaster()
+{
+ if( !pCst )
+ pCst = new SfxBroadcaster;
+ return *pCst;
+}
+
+// Perhaps some day one could cut the parameter 0.
+// then the copying will be dropped ...
+
+void SbxVariable::Broadcast( ULONG nHintId )
+{
+ if( pCst && !IsSet( SBX_NO_BROADCAST ) && StaticIsEnabledBroadcasting() )
+ {
+ // Because the method could be called from outside, check the Da die Methode von aussen aufrufbar ist, hier noch einmal
+ // rights here again
+ if( nHintId & SBX_HINT_DATAWANTED )
+ if( !CanRead() )
+ return;
+ if( nHintId & SBX_HINT_DATACHANGED )
+ if( !CanWrite() )
+ return;
+ // Avoid further broadcasting
+ SfxBroadcaster* pSave = pCst;
+ pCst = NULL;
+ USHORT nSaveFlags = GetFlags();
+ SetFlag( SBX_READWRITE );
+ if( mpPar.Is() )
+ // Register this as element 0, but don't change over the parent!
+ mpPar->GetRef( 0 ) = this;
+ pSave->Broadcast( SbxHint( nHintId, this ) );
+ delete pCst; // who knows already, onto which thoughts someone comes?
+ pCst = pSave;
+ SetFlags( nSaveFlags );
+ }
+}
+
+SbxInfo* SbxVariable::GetInfo()
+{
+ if( !pInfo )
+ {
+ Broadcast( SBX_HINT_INFOWANTED );
+ if( pInfo.Is() )
+ SetModified( TRUE );
+ }
+ return pInfo;
+}
+
+void SbxVariable::SetInfo( SbxInfo* p )
+{
+ pInfo = p;
+}
+
+void SbxVariable::SetParameters( SbxArray* p )
+{
+ mpPar = p;
+}
+
+
+/////////////////////////// Name of the variables ///////////////////////////
+
+void SbxVariable::SetName( const XubString& rName )
+{
+ maName = rName;
+ nHash = MakeHashCode( rName );
+}
+
+const XubString& SbxVariable::GetName( SbxNameType t ) const
+{
+ static char cSuffixes[] = " %&!#@ $";
+ if( t == SbxNAME_NONE )
+ return maName;
+ // Request parameter-information (not for objects)
+ ((SbxVariable*)this)->GetInfo();
+ // Append nothing, if it is a simple property (no empty brackets)
+ if( !pInfo
+ || ( !pInfo->aParams.Count() && GetClass() == SbxCLASS_PROPERTY ) )
+ return maName;
+ xub_Unicode cType = ' ';
+ XubString aTmp( maName );
+ // short type? Then fetch it, posible this is 0.
+ SbxDataType 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 );
+ int nt = q->eType & 0x0FFF;
+ if( i )
+ aTmp += ',';
+ if( q->nFlags & SBX_OPTIONAL )
+ aTmp += String( SbxRes( STRING_OPTIONAL ) );
+ if( q->eType & SbxBYREF )
+ aTmp += String( SbxRes( STRING_BYREF ) );
+ aTmp += q->aName;
+ cType = ' ';
+ // short type? Then fetch it, posible this is 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( "()" );
+ // long type?
+ if( t != SbxNAME_SHORT )
+ {
+ aTmp += String( SbxRes( STRING_AS ) );
+ if( nt < 32 )
+ aTmp += String( SbxRes(
+ sal::static_int_cast< USHORT >( STRING_TYPES + nt ) ) );
+ else
+ aTmp += String( SbxRes( STRING_ANY ) );
+ }
+ }
+ }
+ aTmp += ')';
+ // Long type? Then fetch it
+ if( t == SbxNAME_LONG_TYPES && et != SbxEMPTY )
+ {
+ aTmp += String( SbxRes( STRING_AS ) );
+ if( et < 32 )
+ aTmp += String( SbxRes(
+ sal::static_int_cast< USHORT >( STRING_TYPES + et ) ) );
+ else
+ aTmp += String( SbxRes( STRING_ANY ) );
+ }
+ ((SbxVariable*) this)->aToolString = aTmp;
+ return aToolString;
+}
+
+// Create a simple hashcode: the first six characters were evaluated.
+
+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++;
+ // If we have a commen sigen break!!
+ if( c >= 0x80 )
+ return 0;
+ n = sal::static_int_cast< USHORT >( ( n << 3 ) + toupper( c ) );
+ }
+ return n;
+}
+
+////////////////////////////// Operators ////////////////////////////////
+
+SbxVariable& SbxVariable::operator=( const SbxVariable& r )
+{
+ SbxValue::operator=( r );
+ delete mpSbxVariableImpl;
+ if( r.mpSbxVariableImpl != NULL )
+ mpSbxVariableImpl = new SbxVariableImpl( *r.mpSbxVariableImpl );
+ else
+ mpSbxVariableImpl = NULL;
+ return *this;
+}
+
+//////////////////////////////// Conversion ////////////////////////////////
+
+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: Recursion out here MM
+ pParent->SetModified( b );
+}
+
+void SbxVariable::SetParent( SbxObject* p )
+{
+#ifdef DBG_UTIL
+ // Will the parent of a SbxObject be set?
+ if ( p && ISA(SbxObject) )
+ {
+ // then this had to be a child of the new parent
+ 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;
+}
+
+SbxVariableImpl* SbxVariable::getImpl( void )
+{
+ if( mpSbxVariableImpl == NULL )
+ mpSbxVariableImpl = new SbxVariableImpl();
+ return mpSbxVariableImpl;
+}
+
+const String& SbxVariable::GetDeclareClassName( void )
+{
+ SbxVariableImpl* pImpl = getImpl();
+ return pImpl->m_aDeclareClassName;
+}
+
+void SbxVariable::SetDeclareClassName( const String& rDeclareClassName )
+{
+ SbxVariableImpl* pImpl = getImpl();
+ pImpl->m_aDeclareClassName = rDeclareClassName;
+}
+
+void SbxVariable::SetComListener( ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xComListener )
+{
+ SbxVariableImpl* pImpl = getImpl();
+ pImpl->m_xComListener = xComListener;
+}
+
+
+////////////////////////////// Loading/Saving /////////////////////////////
+
+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( maName, RTL_TEXTENCODING_ASCII_US );
+ UINT32 nTemp;
+ rStrm >> nTemp;
+ nUserData = nTemp;
+ }
+ else
+ {
+ rStrm.SeekRel( -1L );
+ rStrm >> nType;
+ rStrm.ReadByteString( maName, RTL_TEXTENCODING_ASCII_US );
+ UINT32 nTemp;
+ rStrm >> nTemp;
+ nUserData = nTemp;
+ // correction: old methods have instead of SbxNULL now SbxEMPTY
+ if( nType == SbxNULL && GetClass() == SbxCLASS_METHOD )
+ nType = SbxEMPTY;
+ SbxValues aTmp;
+ String aTmpString;
+ ::rtl::OUString aVal;
+ aTmp.eType = aData.eType = (SbxDataType) nType;
+ aTmp.pOUString = &aVal;
+ switch( nType )
+ {
+ case SbxBOOL:
+ case SbxERROR:
+ case SbxINTEGER:
+ rStrm >> aTmp.nInteger; break;
+ case SbxLONG:
+ rStrm >> aTmp.nLong; break;
+ case SbxSINGLE:
+ {
+ // Floats as ASCII
+ rStrm.ReadByteString( aTmpString, RTL_TEXTENCODING_ASCII_US );
+ double d;
+ SbxDataType t;
+ if( ImpScan( aTmpString, d, t, NULL ) != SbxERR_OK || t == SbxDOUBLE )
+ {
+ aTmp.nSingle = 0;
+ return FALSE;
+ }
+ aTmp.nSingle = (float) d;
+ break;
+ }
+ case SbxDATE:
+ case SbxDOUBLE:
+ {
+ // Floats as ASCII
+ rStrm.ReadByteString( aTmpString, RTL_TEXTENCODING_ASCII_US );
+ SbxDataType t;
+ if( ImpScan( aTmpString, aTmp.nDouble, t, NULL ) != SbxERR_OK )
+ {
+ aTmp.nDouble = 0;
+ return FALSE;
+ }
+ break;
+ }
+ case SbxSTRING:
+ rStrm.ReadByteString( aTmpString, RTL_TEXTENCODING_ASCII_US );
+ aVal = aTmpString;
+ break;
+ case SbxEMPTY:
+ case SbxNULL:
+ break;
+ default:
+ aData.eType = SbxNULL;
+ DBG_ASSERT( !this, "Nicht unterstuetzer Datentyp geladen" );
+ return FALSE;
+ }
+ // putt value
+ if( nType != SbxNULL && nType != SbxEMPTY && !Put( aTmp ) )
+ return FALSE;
+ }
+ rStrm >> cMark;
+ // cMark is also a version number!
+ // 1: initial version
+ // 2: with nUserData
+ if( cMark )
+ {
+ if( cMark > 2 )
+ return FALSE;
+ pInfo = new SbxInfo;
+ pInfo->LoadData( rStrm, (USHORT) cMark );
+ }
+ // Load private data only, if it is a SbxVariable
+ if( GetClass() == SbxCLASS_VARIABLE && !LoadPrivateData( rStrm, nVer ) )
+ return FALSE;
+ ((SbxVariable*) this)->Broadcast( SBX_HINT_DATACHANGED );
+ nHash = MakeHashCode( maName );
+ SetModified( TRUE );
+ return TRUE;
+}
+
+BOOL SbxVariable::StoreData( SvStream& rStrm ) const
+{
+ rStrm << (BYTE) 0xFF; // Marker
+ BOOL bValStore;
+ if( this->IsA( TYPE(SbxMethod) ) )
+ {
+ // #50200 Avoid that objects , which during the runtime
+ // as return-value are saved in the method as a value were saved
+ SbxVariable* pThis = (SbxVariable*)this;
+ USHORT nSaveFlags = GetFlags();
+ pThis->SetFlag( SBX_WRITE );
+ pThis->SbxValue::Clear();
+ pThis->SetFlags( nSaveFlags );
+
+ // So that the method will not be executed in any case!
+ // CAST, to avoid const!
+ 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( maName, RTL_TEXTENCODING_ASCII_US );
+ rStrm << (UINT32)nUserData;
+ if( pInfo.Is() )
+ {
+ rStrm << (BYTE) 2; // Version 2: with UserData!
+ pInfo->StoreData( rStrm );
+ }
+ else
+ rStrm << (BYTE) 0;
+ // Save private data only, if it is a SbxVariable
+ 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 )
+ : SvRefBase( r ), SbxVariable( r ),
+ SfxListener( 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( xAlias.Is() && StaticIsEnabledBroadcasting() )
+ {
+ 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();
+ // delete the alias?
+ 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 << " ) ";
+
+ // output also the object at object-vars
+ 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;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */