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
-rwxr-xr-xbasic/source/sbx/makefile.mk77
-rw-r--r--basic/source/sbx/sbxarray.cxx849
-rw-r--r--basic/source/sbx/sbxbase.cxx457
-rw-r--r--basic/source/sbx/sbxbool.cxx231
-rw-r--r--basic/source/sbx/sbxbyte.cxx316
-rw-r--r--basic/source/sbx/sbxchar.cxx308
-rw-r--r--basic/source/sbx/sbxcoll.cxx301
-rw-r--r--basic/source/sbx/sbxconv.hxx137
-rw-r--r--basic/source/sbx/sbxcurr.cxx550
-rw-r--r--basic/source/sbx/sbxdate.cxx396
-rw-r--r--basic/source/sbx/sbxdbl.cxx319
-rw-r--r--basic/source/sbx/sbxdec.cxx748
-rw-r--r--basic/source/sbx/sbxdec.hxx122
-rw-r--r--basic/source/sbx/sbxexec.cxx401
-rw-r--r--basic/source/sbx/sbxform.cxx1118
-rw-r--r--basic/source/sbx/sbxint.cxx912
-rw-r--r--basic/source/sbx/sbxlng.cxx323
-rw-r--r--basic/source/sbx/sbxmstrm.cxx42
-rw-r--r--basic/source/sbx/sbxobj.cxx1022
-rw-r--r--basic/source/sbx/sbxres.cxx93
-rw-r--r--basic/source/sbx/sbxres.hxx90
-rw-r--r--basic/source/sbx/sbxscan.cxx965
-rw-r--r--basic/source/sbx/sbxsng.cxx350
-rw-r--r--basic/source/sbx/sbxstr.cxx321
-rw-r--r--basic/source/sbx/sbxuint.cxx324
-rw-r--r--basic/source/sbx/sbxulng.cxx300
-rw-r--r--basic/source/sbx/sbxvals.cxx109
-rw-r--r--basic/source/sbx/sbxvalue.cxx1752
-rw-r--r--basic/source/sbx/sbxvar.cxx666
30 files changed, 13684 insertions, 0 deletions
diff --git a/basic/source/sbx/format.src b/basic/source/sbx/format.src
new file mode 100644
index 000000000000..7e576134fad5
--- /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 100755
index 000000000000..332c6a0d426d
--- /dev/null
+++ b/basic/source/sbx/makefile.mk
@@ -0,0 +1,77 @@
+#*************************************************************************
+#
+# 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)$/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)$/sbxvar.obj
+
+
+EXCEPTIONSFILES= \
+ $(SLO)$/sbxarray.obj \
+ $(SLO)$/sbxcurr.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..0f9b81f8d479
--- /dev/null
+++ b/basic/source/sbx/sbxarray.cxx
@@ -0,0 +1,849 @@
+/* -*- 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
+ sal_Int32 nLbound, nUbound; // Limitations
+ sal_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( sal_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()
+{
+ sal_uInt32 nSize = pData->size();
+ for( sal_uInt32 i = 0 ; i < nSize ; i++ )
+ {
+ SbxVarEntry* pEntry = (*pData)[i];
+ delete pEntry;
+ }
+ pData->clear();
+}
+
+sal_uInt32 SbxArray::Count32() const
+{
+ return pData->size();
+}
+
+sal_uInt16 SbxArray::Count() const
+{
+ sal_uInt32 nCount = pData->size();
+ DBG_ASSERT( nCount <= SBX_MAXINDEX, "SBX: Array-Index > SBX_MAXINDEX" );
+ return (sal_uInt16)nCount;
+}
+
+SbxVariableRef& SbxArray::GetRef32( sal_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( sal_uInt16 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( sal_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( sal_uInt16 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, sal_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, sal_uInt16 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( sal_uInt16 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, sal_uInt16 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, sal_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, sal_uInt16 nIdx )
+{
+ DBG_ASSERT( pData->size() <= 0x3FF0, "SBX: Array wird zu gross" );
+ if( pData->size() > 0x3FF0 )
+ return;
+ Insert32( pVar, nIdx );
+}
+
+void SbxArray::Remove32( sal_uInt32 nIdx )
+{
+ if( nIdx < pData->size() )
+ {
+ SbxVariableRef* pRef = (*pData)[nIdx];
+ pData->erase( pData->begin() + nIdx );
+ delete pRef;
+ SetFlag( SBX_MODIFIED );
+ }
+}
+
+void SbxArray::Remove( sal_uInt16 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( sal_uInt32 i = 0; i < pData->size(); i++ )
+ {
+ SbxVariableRef* pRef = (*pData)[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 )
+ {
+ sal_uInt32 nSize = p->Count();
+ for( sal_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();
+ sal_uInt16 nHash = pVar->GetHashCode();
+ for( sal_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( sal_uInt32 nData )
+{
+ SbxVariable* p = NULL;
+ for( sal_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.
+ sal_uInt16 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;
+ sal_uInt32 nCount = pData->size();
+ if( !nCount )
+ return NULL;
+ sal_Bool bExtSearch = IsSet( SBX_EXTSEARCH );
+ sal_uInt16 nHash = SbxVariable::MakeHashCode( rName );
+ for( sal_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!
+ sal_uInt16 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.
+ sal_uInt16 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;
+}
+
+sal_Bool SbxArray::LoadData( SvStream& rStrm, sal_uInt16 nVer )
+{
+ sal_uInt16 nElem;
+ Clear();
+ sal_Bool bRes = sal_True;
+ sal_uInt16 f = nFlags;
+ nFlags |= SBX_WRITE;
+ rStrm >> nElem;
+ nElem &= 0x7FFF;
+ for( sal_uInt32 n = 0; n < nElem; n++ )
+ {
+ sal_uInt16 nIdx;
+ rStrm >> nIdx;
+ SbxVariable* pVar = (SbxVariable*) Load( rStrm );
+ if( pVar )
+ {
+ SbxVariableRef& rRef = GetRef( nIdx );
+ rRef = pVar;
+ }
+ else
+ {
+ bRes = sal_False; break;
+ }
+ }
+ if( bRes )
+ bRes = LoadPrivateData( rStrm, nVer );
+ nFlags = f;
+ return bRes;
+}
+
+sal_Bool SbxArray::StoreData( SvStream& rStrm ) const
+{
+ sal_uInt32 nElem = 0;
+ sal_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 << (sal_uInt16) nElem;
+ for( n = 0; n < pData->size(); n++ )
+ {
+ SbxVariableRef* pRef = (*pData)[n];
+ SbxVariable* p = *pRef;
+ if( p && !( p->GetFlags() & SBX_DONTSTORE ) )
+ {
+ rStrm << (sal_uInt16) n;
+ if( !p->Store( rStrm ) )
+ return sal_False;
+ }
+ }
+ return StorePrivateData( rStrm );
+}
+
+// #100883 Method to set method directly to parameter array
+void SbxArray::PutDirect( SbxVariable* pVar, sal_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( sal_Int32 lb, sal_Int32 ub, sal_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, sal_False );
+}
+
+void SbxDimArray::unoAddDim( short lb, short ub )
+{
+ AddDimImpl32( lb, ub, sal_True );
+}
+
+void SbxDimArray::AddDim32( sal_Int32 lb, sal_Int32 ub )
+{
+ AddDimImpl32( lb, ub, sal_False );
+}
+
+void SbxDimArray::unoAddDim32( sal_Int32 lb, sal_Int32 ub )
+{
+ AddDimImpl32( lb, ub, sal_True );
+}
+
+
+// Readout dimension data
+
+sal_Bool SbxDimArray::GetDim32( sal_Int32 n, sal_Int32& rlb, sal_Int32& rub ) const
+{
+ if( n < 1 || n > nDim )
+ {
+ SetError( SbxERR_BOUNDS ); rub = rlb = 0; return sal_False;
+ }
+ SbxDim* p = pFirst;
+ while( --n )
+ p = p->pNext;
+ rub = p->nUbound;
+ rlb = p->nLbound;
+ return sal_True;
+}
+
+sal_Bool SbxDimArray::GetDim( short n, short& rlb, short& rub ) const
+{
+ sal_Int32 rlb32, rub32;
+ sal_Bool bRet = GetDim32( n, rlb32, rub32 );
+ if( bRet )
+ {
+ if( rlb32 < -SBX_MAXINDEX || rub32 > SBX_MAXINDEX )
+ {
+ SetError( SbxERR_BOUNDS );
+ return sal_False;
+ }
+ rub = (short)rub32;
+ rlb = (short)rlb32;
+ }
+ return bRet;
+}
+
+// Element-Ptr with the help of an index list
+
+sal_uInt32 SbxDimArray::Offset32( const sal_Int32* pIdx )
+{
+ sal_uInt32 nPos = 0;
+ for( SbxDim* p = pFirst; p; p = p->pNext )
+ {
+ sal_Int32 nIdx = *pIdx++;
+ if( nIdx < p->nLbound || nIdx > p->nUbound )
+ {
+ nPos = (sal_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;
+}
+
+sal_uInt16 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 (sal_uInt16) 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 sal_Int32* pIdx )
+{
+ return SbxArray::GetRef32( Offset32( pIdx ) );
+}
+
+SbxVariable* SbxDimArray::Get32( const sal_Int32* pIdx )
+{
+ return SbxArray::Get32( Offset32( pIdx ) );
+}
+
+void SbxDimArray::Put32( SbxVariable* p, const sal_Int32* pIdx )
+{
+ SbxArray::Put32( p, Offset32( pIdx ) );
+}
+
+
+// Element-Number with the help of Parameter-Array
+
+sal_uInt32 SbxDimArray::Offset32( SbxArray* pPar )
+{
+ if( nDim == 0 || !pPar || ( ( nDim != ( pPar->Count() - 1 ) ) && SbiRuntime::isVBAEnabled() ) )
+ {
+ SetError( SbxERR_BOUNDS ); return 0;
+ }
+ sal_uInt32 nPos = 0;
+ sal_uInt16 nOff = 1; // Non element 0!
+ for( SbxDim* p = pFirst; p && !IsError(); p = p->pNext )
+ {
+ sal_Int32 nIdx = pPar->Get( nOff++ )->GetLong();
+ if( nIdx < p->nLbound || nIdx > p->nUbound )
+ {
+ nPos = (sal_uInt32) SBX_MAXINDEX32+1; break;
+ }
+ nPos = nPos * p->nSize + nIdx - p->nLbound;
+ }
+ if( nPos > (sal_uInt32) SBX_MAXINDEX32 )
+ {
+ SetError( SbxERR_BOUNDS ); nPos = 0;
+ }
+ return nPos;
+}
+
+sal_uInt16 SbxDimArray::Offset( SbxArray* pPar )
+{
+ sal_uInt32 nPos = Offset32( pPar );
+ if( nPos > (long) SBX_MAXINDEX )
+ {
+ SetError( SbxERR_BOUNDS ); nPos = 0;
+ }
+ return (sal_uInt16) 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 ) );
+}
+
+sal_Bool SbxDimArray::LoadData( SvStream& rStrm, sal_uInt16 nVer )
+{
+ short nDimension;
+ rStrm >> nDimension;
+ for( short i = 0; i < nDimension && rStrm.GetError() == SVSTREAM_OK; i++ )
+ {
+ sal_Int16 lb, ub;
+ rStrm >> lb >> ub;
+ AddDim( lb, ub );
+ }
+ return SbxArray::LoadData( rStrm, nVer );
+}
+
+sal_Bool SbxDimArray::StoreData( SvStream& rStrm ) const
+{
+ rStrm << (sal_Int16) nDim;
+ for( short i = 0; i < nDim; i++ )
+ {
+ short lb, ub;
+ GetDim( i, lb, ub );
+ rStrm << (sal_Int16) lb << (sal_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..77f34d90f370
--- /dev/null
+++ b/basic/source/sbx/sbxbase.cxx
@@ -0,0 +1,457 @@
+/* -*- 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()
+{
+ SbxAppData** ppData = (SbxAppData**) ::GetAppData( SHL_SBX );
+ SbxAppData* p = *ppData;
+ if( !p )
+ p = *ppData = new SbxAppData;
+ return p;
+}
+
+SbxAppData::~SbxAppData()
+{
+ if( pBasicFormater )
+ delete pBasicFormater;
+}
+
+
+//////////////////////////////// SbxBase /////////////////////////////////
+
+DBG_NAME(SbxBase);
+
+SbxBase::SbxBase()
+{
+ DBG_CTOR( SbxBase, 0 );
+ nFlags = SBX_READWRITE;
+}
+
+SbxBase::SbxBase( const SbxBase& r )
+ : SvRefBase( r )
+{
+ DBG_CTOR( SbxBase, 0 );
+ nFlags = r.nFlags;
+}
+
+SbxBase::~SbxBase()
+{
+ DBG_DTOR(SbxBase,0);
+}
+
+SbxBase& SbxBase::operator=( const SbxBase& r )
+{
+ DBG_CHKTHIS( SbxBase, 0 );
+ nFlags = r.nFlags;
+ return *this;
+}
+
+SbxDataType SbxBase::GetType() const
+{
+ DBG_CHKTHIS( SbxBase, 0 );
+ return SbxEMPTY;
+}
+
+SbxClassType SbxBase::GetClass() const
+{
+ DBG_CHKTHIS( SbxBase, 0 );
+ return SbxCLASS_DONTCARE;
+}
+
+void SbxBase::Clear()
+{
+ DBG_CHKTHIS( SbxBase, 0 );
+}
+
+sal_Bool SbxBase::IsFixed() const
+{
+ DBG_CHKTHIS( SbxBase, 0 );
+ return IsSet( SBX_FIXED );
+}
+
+void SbxBase::SetModified( sal_Bool b )
+{
+ DBG_CHKTHIS( SbxBase, 0 );
+ if( IsSet( SBX_NO_MODIFY ) )
+ return;
+ if( b )
+ SetFlag( SBX_MODIFIED );
+ else
+ ResetFlag( SBX_MODIFIED );
+}
+
+SbxError SbxBase::GetError()
+{
+ return GetSbxData_Impl()->eSbxError;
+}
+
+void SbxBase::SetError( SbxError e )
+{
+ SbxAppData* p = GetSbxData_Impl();
+ if( e && p->eSbxError == SbxERR_OK )
+ p->eSbxError = e;
+}
+
+sal_Bool SbxBase::IsError()
+{
+ return sal_Bool( GetSbxData_Impl()->eSbxError != SbxERR_OK );
+}
+
+void SbxBase::ResetError()
+{
+ GetSbxData_Impl()->eSbxError = SbxERR_OK;
+}
+
+void SbxBase::AddFactory( SbxFactory* pFac )
+{
+ SbxAppData* p = GetSbxData_Impl();
+ const SbxFactory* pTemp = pFac;
+
+ // From 1996-03-06: take the HandleLast-Flag into account
+ sal_uInt16 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( sal_uInt16 i = 0; i < p->aFacs.Count(); i++ )
+ {
+ if( p->aFacs.GetObject( i ) == pFac )
+ {
+ p->aFacs.Remove( i, 1 ); break;
+ }
+ }
+}
+
+
+SbxBase* SbxBase::Create( sal_uInt16 nSbxId, sal_uInt32 nCreator )
+{
+ // #91626: Hack to skip old Basic dialogs
+ // Problem: There does not exist a factory any more,
+ // so we have to create a dummy SbxVariable instead
+ if( nSbxId == 0x65 ) // Dialog Id
+ return new SbxVariable;
+
+ XubString aEmptyStr;
+ if( nCreator == SBXCR_SBX )
+ switch( nSbxId )
+ {
+ case SBXID_VALUE: return new SbxValue;
+ case SBXID_VARIABLE: return new SbxVariable;
+ case SBXID_ARRAY: return new SbxArray;
+ case SBXID_DIMARRAY: return new SbxDimArray;
+ case SBXID_OBJECT: return new SbxObject( aEmptyStr );
+ case SBXID_COLLECTION: return new SbxCollection( aEmptyStr );
+ case SBXID_FIXCOLLECTION:
+ return new SbxStdCollection( aEmptyStr, aEmptyStr );
+ case SBXID_METHOD: return new SbxMethod( aEmptyStr, SbxEMPTY );
+ case SBXID_PROPERTY: return new SbxProperty( aEmptyStr, SbxEMPTY );
+ }
+ // Unknown type: go over the factories!
+ SbxAppData* p = GetSbxData_Impl();
+ SbxBase* pNew = NULL;
+ for( sal_uInt16 i = 0; i < p->aFacs.Count(); i++ )
+ {
+ SbxFactory* pFac = p->aFacs.GetObject( i );
+ pNew = pFac->Create( nSbxId, nCreator );
+ if( pNew )
+ break;
+ }
+#ifdef DBG_UTIL
+ if( !pNew )
+ {
+ ByteString aMsg( "SBX: Keine Factory fuer SBX-ID " );
+ aMsg += ByteString::CreateFromInt32(nSbxId);
+ DbgError( aMsg.GetBuffer() );
+ }
+#endif
+ return pNew;
+}
+
+SbxObject* SbxBase::CreateObject( const XubString& rClass )
+{
+ SbxAppData* p = GetSbxData_Impl();
+ SbxObject* pNew = NULL;
+ for( sal_uInt16 i = 0; i < p->aFacs.Count(); i++ )
+ {
+ pNew = p->aFacs.GetObject( i )->CreateObject( rClass );
+ if( pNew )
+ break;
+ }
+#ifdef DBG_UTIL
+ if( !pNew )
+ {
+ ByteString aMsg( "SBX: Keine Factory fuer Objektklasse " );
+ ByteString aClassStr( (const UniString&)rClass, RTL_TEXTENCODING_ASCII_US );
+ aMsg += aClassStr;
+ DbgError( (const char*)aMsg.GetBuffer() );
+ }
+#endif
+ return pNew;
+}
+
+static sal_Bool bStaticEnableBroadcasting = sal_True;
+
+// Sbx-Solution in exchange for SfxBroadcaster::Enable()
+void SbxBase::StaticEnableBroadcasting( sal_Bool bEnable )
+{
+ bStaticEnableBroadcasting = bEnable;
+}
+
+sal_Bool SbxBase::StaticIsEnabledBroadcasting( void )
+{
+ return bStaticEnableBroadcasting;
+}
+
+
+SbxBase* SbxBase::Load( SvStream& rStrm )
+{
+ sal_uInt16 nSbxId, nFlags, nVer;
+ sal_uInt32 nCreator, nSize;
+ rStrm >> nCreator >> nSbxId >> nFlags >> nVer;
+
+ // Correcting a foolishness of mine:
+ if( nFlags & SBX_RESERVED )
+ nFlags = ( nFlags & ~SBX_RESERVED ) | SBX_GBLSEARCH;
+
+ sal_uIntPtr nOldPos = rStrm.Tell();
+ rStrm >> nSize;
+ SbxBase* p = Create( nSbxId, nCreator );
+ if( p )
+ {
+ p->nFlags = nFlags;
+ if( p->LoadData( rStrm, nVer ) )
+ {
+ sal_uIntPtr nNewPos = rStrm.Tell();
+ nOldPos += nSize;
+ DBG_ASSERT( nOldPos >= nNewPos, "SBX: Zu viele Daten eingelesen" );
+ if( nOldPos != nNewPos )
+ rStrm.Seek( nOldPos );
+ if( !p->LoadCompleted() )
+ {
+ // 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 )
+{
+ sal_uInt16 nSbxId, nFlags, nVer;
+ sal_uInt32 nCreator, nSize;
+ rStrm >> nCreator >> nSbxId >> nFlags >> nVer;
+
+ sal_uIntPtr nStartPos = rStrm.Tell();
+ rStrm >> nSize;
+
+ rStrm.Seek( nStartPos + nSize );
+}
+
+sal_Bool SbxBase::Store( SvStream& rStrm )
+{
+ DBG_CHKTHIS( SbxBase, 0 );
+ if( !( nFlags & SBX_DONTSTORE ) )
+ {
+ rStrm << (sal_uInt32) GetCreator()
+ << (sal_uInt16) GetSbxId()
+ << (sal_uInt16) GetFlags()
+ << (sal_uInt16) GetVersion();
+ sal_uIntPtr nOldPos = rStrm.Tell();
+ rStrm << (sal_uInt32) 0L;
+ sal_Bool bRes = StoreData( rStrm );
+ sal_uIntPtr nNewPos = rStrm.Tell();
+ rStrm.Seek( nOldPos );
+ rStrm << (sal_uInt32) ( nNewPos - nOldPos );
+ rStrm.Seek( nNewPos );
+ if( rStrm.GetError() != SVSTREAM_OK )
+ bRes = sal_False;
+ if( bRes )
+ bRes = StoreCompleted();
+ return bRes;
+ }
+ else
+ return sal_True;
+}
+
+sal_Bool SbxBase::LoadData( SvStream&, sal_uInt16 )
+{
+ DBG_CHKTHIS( SbxBase, 0 );
+ return sal_False;
+}
+
+sal_Bool SbxBase::StoreData( SvStream& ) const
+{
+ DBG_CHKTHIS( SbxBase, 0 );
+ return sal_False;
+}
+
+sal_Bool SbxBase::LoadPrivateData( SvStream&, sal_uInt16 )
+{
+ DBG_CHKTHIS( SbxBase, 0 );
+ return sal_True;
+}
+
+sal_Bool SbxBase::StorePrivateData( SvStream& ) const
+{
+ DBG_CHKTHIS( SbxBase, 0 );
+ return sal_True;
+}
+
+sal_Bool SbxBase::LoadCompleted()
+{
+ DBG_CHKTHIS( SbxBase, 0 );
+ return sal_True;
+}
+
+sal_Bool SbxBase::StoreCompleted()
+{
+ DBG_CHKTHIS( SbxBase, 0 );
+ return sal_True;
+}
+
+//////////////////////////////// SbxFactory ////////////////////////////////
+
+SbxBase* SbxFactory::Create( sal_uInt16, sal_uInt32 )
+{
+ return NULL;
+}
+
+SbxObject* SbxFactory::CreateObject( const XubString& )
+{
+ return NULL;
+}
+
+///////////////////////////////// SbxInfo //////////////////////////////////
+
+SbxInfo::~SbxInfo()
+{}
+
+void SbxInfo::AddParam
+ ( const XubString& rName, SbxDataType eType, sal_uInt16 nFlags )
+{
+ const SbxParamInfo* p = new SbxParamInfo( rName, eType, nFlags );
+ aParams.Insert( p, aParams.Count() );
+}
+
+void SbxInfo::AddParam( const SbxParamInfo& r )
+{
+ const SbxParamInfo* p = new SbxParamInfo
+ ( r.aName, r.eType, r.nFlags, r.aTypeRef );
+ aParams.Insert( p, aParams.Count() );
+}
+
+const SbxParamInfo* SbxInfo::GetParam( sal_uInt16 n ) const
+{
+ if( n < 1 || n > aParams.Count() )
+ return NULL;
+ else
+ return aParams.GetObject( n-1 );
+}
+
+sal_Bool SbxInfo::LoadData( SvStream& rStrm, sal_uInt16 nVer )
+{
+ aParams.Remove( 0, aParams.Count() );
+ sal_uInt16 nParam;
+ rStrm.ReadByteString( aComment, RTL_TEXTENCODING_ASCII_US );
+ rStrm.ReadByteString( aHelpFile, RTL_TEXTENCODING_ASCII_US );
+ rStrm >> nHelpId >> nParam;
+ while( nParam-- )
+ {
+ XubString aName;
+ sal_uInt16 nType, nFlags;
+ sal_uInt32 nUserData = 0;
+ rStrm.ReadByteString( aName, RTL_TEXTENCODING_ASCII_US );
+ rStrm >> nType >> nFlags;
+ if( nVer > 1 )
+ rStrm >> nUserData;
+ AddParam( aName, (SbxDataType) nType, nFlags );
+ SbxParamInfo* p = aParams.GetObject( aParams.Count() - 1 );
+ p->nUserData = nUserData;
+ }
+ return sal_True;
+}
+
+sal_Bool SbxInfo::StoreData( SvStream& rStrm ) const
+{
+ rStrm.WriteByteString( aComment, RTL_TEXTENCODING_ASCII_US );
+ rStrm.WriteByteString( aHelpFile, RTL_TEXTENCODING_ASCII_US );
+ rStrm << nHelpId << aParams.Count();
+ for( sal_uInt16 i = 0; i < aParams.Count(); i++ )
+ {
+ SbxParamInfo* p = aParams.GetObject( i );
+ rStrm.WriteByteString( p->aName, RTL_TEXTENCODING_ASCII_US );
+ rStrm << (sal_uInt16) p->eType
+ << (sal_uInt16) p->nFlags
+ << (sal_uInt32) p->nUserData;
+ }
+ return sal_True;
+}
+
+/* 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..7efb748355cc
--- /dev/null
+++ b/basic/source/sbx/sbxbool.cxx
@@ -0,0 +1,231 @@
+/* -*- 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:
+ case SbxCURRENCY:
+ nRes = p->nInt64 ? SbxTRUE : SbxFALSE; break;
+ case SbxSALUINT64:
+ nRes = p->uInt64 ? 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
+ sal_Bool bError = sal_True;
+ double n;
+ SbxDataType t;
+ sal_uInt16 nLen = 0;
+ if( ImpScan( *p->pOUString, n, t, &nLen ) == SbxERR_OK )
+ {
+ if( nLen == p->pOUString->getLength() )
+ {
+ bError = sal_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 | SbxCURRENCY:
+ case SbxBYREF | SbxSALINT64:
+ nRes = ( *p->pnInt64 ) ? SbxTRUE : SbxFALSE; break;
+ case SbxBYREF | SbxSALUINT64:
+ nRes = ( *p->puInt64 ) ? SbxTRUE : SbxFALSE; break;
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION ); nRes = SbxFALSE;
+ }
+ return nRes;
+}
+
+void ImpPutBool( SbxValues* p, sal_Int16 n )
+{
+ if( n )
+ n = SbxTRUE;
+ switch( +p->eType )
+ {
+ case SbxCHAR:
+ p->nChar = (xub_Unicode) n; break;
+ case SbxUINT:
+ p->nByte = (sal_uInt8) n; break;
+ case SbxINTEGER:
+ case SbxBOOL:
+ p->nInteger = n; break;
+ case SbxLONG:
+ p->nLong = n; break;
+ case SbxULONG:
+ p->nULong = (sal_uInt32) n; break;
+ case SbxERROR:
+ case SbxUSHORT:
+ p->nUShort = (sal_uInt16) n; break;
+ case SbxSINGLE:
+ p->nSingle = n; break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ p->nDouble = n; break;
+ case SbxCURRENCY:
+ case SbxSALINT64:
+ p->nInt64 = (sal_Int64) n; break;
+ case SbxSALUINT64:
+ p->uInt64 = (sal_uInt64) n; break;
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ ImpCreateDecimal( p )->setInt( (sal_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( sal_Bool( n != 0 ) );
+ else
+ SbxBase::SetError( SbxERR_NO_OBJECT );
+ break;
+ }
+ case SbxBYREF | SbxCHAR:
+ *p->pChar = (xub_Unicode) n; break;
+ case SbxBYREF | SbxBYTE:
+ *p->pByte = (sal_uInt8) n; break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ *p->pInteger = (sal_Int16) n; break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ *p->pUShort = (sal_uInt16) n; break;
+ case SbxBYREF | SbxLONG:
+ *p->pLong = n; break;
+ case SbxBYREF | SbxULONG:
+ *p->pULong = (sal_uInt32) n; break;
+ case SbxBYREF | SbxSINGLE:
+ *p->pSingle = n; break;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ *p->pDouble = n; break;
+ case SbxBYREF | SbxCURRENCY:
+ case SbxBYREF | SbxSALINT64:
+ *p->pnInt64 = (sal_Int64) n; break;
+ case SbxBYREF | SbxSALUINT64:
+ *p->puInt64 = (sal_uInt64) 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..90d8ecc40a20
--- /dev/null
+++ b/basic/source/sbx/sbxbyte.cxx
@@ -0,0 +1,316 @@
+/* -*- 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"
+
+sal_uInt8 ImpGetByte( const SbxValues* p )
+{
+ SbxValues aTmp;
+ sal_uInt8 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 = (sal_uInt8) p->nChar;
+ break;
+ case SbxBYTE:
+ nRes = (sal_uInt8) 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 = (sal_uInt8) p->nInteger;
+ break;
+ case SbxERROR:
+ case SbxUSHORT:
+ if( p->nUShort > (sal_uInt16) SbxMAXBYTE )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXBYTE;
+ }
+ else
+ nRes = (sal_uInt8) 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 = (sal_uInt8) p->nLong;
+ break;
+ case SbxULONG:
+ if( p->nULong > SbxMAXBYTE )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXBYTE;
+ }
+ else
+ nRes = (sal_uInt8) p->nULong;
+ break;
+ case SbxCURRENCY:
+ case SbxSALINT64:
+ {
+ sal_Int64 val = p->nInt64;
+ if ( p->eType == SbxCURRENCY )
+ val = val / CURRENCY_FACTOR;
+ if( val > SbxMAXBYTE )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXBYTE;
+ }
+ else if( p->nInt64 < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0;
+ }
+ else
+ nRes = (sal_uInt8) val;
+ break;
+ }
+ case SbxSALUINT64:
+ if( p->uInt64 > SbxMAXBYTE )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXBYTE;
+ }
+ else
+ nRes = (sal_uInt8) 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 = (sal_uInt8) ImpRound( p->nSingle );
+ break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ {
+ double dVal;
+ 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 = (sal_uInt8) 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 = (sal_uInt8) ( 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 | SbxCURRENCY:
+ 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, sal_uInt8 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 SbxCURRENCY:
+ p->nInt64 = n * CURRENCY_FACTOR; break;
+ case SbxSALINT64:
+ p->nInt64 = n; break;
+ case SbxSALUINT64:
+ p->uInt64 = 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 | SbxCURRENCY:
+ p->nInt64 = n * CURRENCY_FACTOR; break;
+ case SbxBYREF | SbxSALINT64:
+ *p->pnInt64 = n; break;
+ case SbxBYREF | SbxSALUINT64:
+ *p->puInt64 = 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..ee4cb48b8efb
--- /dev/null
+++ b/basic/source/sbx/sbxchar.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"
+
+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 SbxCURRENCY:
+ case SbxSALINT64:
+ {
+ sal_Int64 val = p->nInt64;
+
+ if ( p->eType == SbxCURRENCY )
+ val = val / CURRENCY_FACTOR;
+
+ if( val > SbxMAXCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXCHAR;
+ }
+ else if( p->nInt64 < SbxMINCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMINCHAR;
+ }
+ else
+ nRes = (xub_Unicode) val;
+ 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 SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ {
+ double dVal;
+ 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 = (sal_uInt8) 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 | SbxCURRENCY:
+ 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 SbxCURRENCY:
+ p->nInt64 = n * CURRENCY_FACTOR; break;
+ case SbxSALINT64:
+ p->nInt64 = n; break;
+ case SbxSALUINT64:
+ p->uInt64 = 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 = (sal_uInt8) n; break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ *p->pInteger = n; break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ *p->pUShort = (sal_uInt16) n; break;
+ case SbxBYREF | SbxLONG:
+ *p->pLong = (sal_Int32) n; break;
+ case SbxBYREF | SbxULONG:
+ *p->pULong = (sal_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:
+ p->nInt64 = n * CURRENCY_FACTOR; break;
+ case SbxBYREF | SbxSALINT64:
+ *p->pnInt64 = n; break;
+ case SbxBYREF | SbxSALUINT64:
+ *p->puInt64 = 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..8cf068d657cb
--- /dev/null
+++ b/basic/source/sbx/sbxcoll.cxx
@@ -0,0 +1,301 @@
+/* -*- 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 sal_uInt16 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(), sal_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( sal_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 )
+ {
+ sal_uIntPtr nId = p->GetId();
+ sal_Bool bRead = sal_Bool( nId == SBX_HINT_DATAWANTED );
+ sal_Bool bWrite = sal_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( (sal_uInt16) 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( (sal_uInt16) n - 1 ) );
+ }
+}
+
+sal_Bool SbxCollection::LoadData( SvStream& rStrm, sal_uInt16 nVer )
+{
+ sal_Bool bRes = SbxObject::LoadData( rStrm, nVer );
+ Initialize();
+ return bRes;
+}
+
+
+SbxStdCollection::SbxStdCollection
+ ( const XubString& rClass, const XubString& rElem, sal_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_ );
+}
+
+sal_Bool SbxStdCollection::LoadData( SvStream& rStrm, sal_uInt16 nVer )
+{
+ sal_Bool bRes = SbxCollection::LoadData( rStrm, nVer );
+ if( bRes )
+ {
+ rStrm.ReadByteString( aElemClass, RTL_TEXTENCODING_ASCII_US );
+ rStrm >> bAddRemoveOk;
+ }
+ return bRes;
+}
+
+sal_Bool SbxStdCollection::StoreData( SvStream& rStrm ) const
+{
+ sal_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..2a11f151d862
--- /dev/null
+++ b/basic/source/sbx/sbxconv.hxx
@@ -0,0 +1,137 @@
+/* -*- 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, sal_Bool bCoreString=sal_False );
+extern SbxError ImpScan
+ ( const ::rtl::OUString& rSrc, double& nVal, SbxDataType& rType, sal_uInt16* pLen,
+ sal_Bool bAllowIntntl=sal_False, sal_Bool bOnlyIntntl=sal_False );
+
+// with advanced evaluation (International, "TRUE"/"FALSE")
+extern sal_Bool ImpConvStringExt( ::rtl::OUString& rSrc, SbxDataType eTargetType );
+
+// SBXINT.CXX
+
+double ImpRound( double );
+sal_Int16 ImpGetInteger( const SbxValues* );
+void ImpPutInteger( SbxValues*, sal_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 ImpSalInt64ToDouble ( sal_Int64 n );
+double ImpSalUInt64ToDouble( sal_uInt64 n );
+
+// SBXLNG.CXX
+
+sal_Int32 ImpGetLong( const SbxValues* );
+void ImpPutLong( SbxValues*, sal_Int32 );
+
+// SBXSNG.CXX
+
+float ImpGetSingle( const SbxValues* );
+void ImpPutSingle( SbxValues*, float );
+
+// SBXDBL.CXX
+
+double ImpGetDouble( const SbxValues* );
+void ImpPutDouble( SbxValues*, double, sal_Bool bCoreString=sal_False );
+
+// SBXCURR.CXX
+
+sal_Int64 ImpGetCurrency( const SbxValues* );
+void ImpPutCurrency( SbxValues*, const sal_Int64 );
+
+inline sal_Int64 ImpDoubleToCurrency( double d )
+ { if (d > 0) return (sal_Int64)( d * CURRENCY_FACTOR + 0.5);
+ else return (sal_Int64)( d * CURRENCY_FACTOR - 0.5);
+ }
+
+inline double ImpCurrencyToDouble( const sal_Int64 r )
+ { return (double)r / (double)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
+sal_uInt8 ImpGetByte( const SbxValues* );
+void ImpPutByte( SbxValues*, sal_uInt8 );
+
+// SBXUINT.CXX
+
+sal_uInt16 ImpGetUShort( const SbxValues* );
+void ImpPutUShort( SbxValues*, sal_uInt16 );
+
+// SBXULNG.CXX
+
+sal_uInt32 ImpGetULong( const SbxValues* );
+void ImpPutULong( SbxValues*, sal_uInt32 );
+
+// SBXBOOL.CXX
+
+enum SbxBOOL ImpGetBool( const SbxValues* );
+void ImpPutBool( SbxValues*, sal_Int16 );
+
+// ByteArray <--> 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..0ea500bb0ba2
--- /dev/null
+++ b/basic/source/sbx/sbxcurr.cxx
@@ -0,0 +1,550 @@
+/* -*- 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> // for SvtSysLocale
+
+#include <basic/sbx.hxx>
+#include <basic/sbxvar.hxx>
+#include "sbxconv.hxx"
+
+
+static rtl::OUString ImpCurrencyToString( const sal_Int64 &rVal )
+{
+ bool isNeg = ( rVal < 0 );
+ sal_Int64 absVal = isNeg ? -rVal : rVal;
+
+ SvtSysLocale aSysLocale;
+ sal_Unicode cDecimalSep = '.';
+#if MAYBEFUTURE
+ sal_Unicode cThousandSep = ',';
+ const LocaleDataWrapper& rData = aSysLocale.GetLocaleData();
+ cDecimalSep = rData.getNumDecimalSep().GetBuffer()[0];
+ cThousandSep = rData.getNumThousandSep().GetBuffer()[0];
+#endif
+
+ rtl::OUString aAbsStr = rtl::OUString::valueOf( absVal );
+ rtl::OUStringBuffer aBuf;
+
+ sal_Int32 initialLen = aAbsStr.getLength();
+
+ bool bLessThanOne = false;
+ if ( initialLen <= 4 ) // if less the 1
+ bLessThanOne = true;
+
+ sal_Int32 nCapacity = 6; // minimum e.g. 0.0000
+
+ if ( !bLessThanOne )
+ {
+ nCapacity = initialLen + 1;
+#if MAYBEFUTURE
+ if ( initialLen > 5 )
+ {
+ sal_Int32 nThouSeperators = ( initialLen - 5 ) / 3;
+ nCapacity += nThouSeperators;
+ }
+#endif
+ }
+
+ if ( isNeg )
+ ++nCapacity;
+
+ aBuf.setLength( nCapacity );
+
+
+ sal_Int32 nDigitCount = 0;
+ sal_Int32 nInsertIndex = nCapacity - 1;
+ sal_Int32 nEndIndex = isNeg ? 1 : 0;
+
+ for ( sal_Int32 charCpyIndex = aAbsStr.getLength() - 1; nInsertIndex >= nEndIndex; ++nDigitCount )
+ {
+ if ( nDigitCount == 4 )
+ aBuf.setCharAt( nInsertIndex--, cDecimalSep );
+#if MAYBEFUTURE
+ if ( nDigitCount > 4 && ! ( ( nDigitCount - 4 ) % 3) )
+ aBuf.setCharAt( nInsertIndex--, cThousandSep );
+#endif
+ if ( nDigitCount < initialLen )
+ aBuf.setCharAt( nInsertIndex--, aAbsStr[ charCpyIndex-- ] );
+ else
+ // Handle leading 0's to right of decimal point
+ // Note: in VBA the stringification is a little more complex
+ // but more natural as only the necessary digits
+ // to the right of the decimal places are displayed
+ // It would be great to conditionally be able to display like that too
+ //
+ // Val OOo (Cur) VBA (Cur)
+ // --- --------- ---------
+ // 0 0.0000 0
+ // 0.1 0.1000 0.1
+
+ aBuf.setCharAt( nInsertIndex--, (sal_Unicode)'0' );
+ }
+ if ( isNeg )
+ aBuf.setCharAt( nInsertIndex, (sal_Unicode)'-' );
+
+ aAbsStr = aBuf.makeStringAndClear();
+ return aAbsStr;
+}
+
+
+static sal_Int64 ImpStringToCurrency( const rtl::OUString &rStr )
+{
+
+ sal_Int32 nFractDigit = 4;
+
+ SvtSysLocale aSysLocale;
+ sal_Unicode cDeciPnt = sal_Unicode('.');
+ sal_Unicode c1000Sep = sal_Unicode(',');
+
+#if MAYBEFUTURE
+ const LocaleDataWrapper& rData = aSysLocale.GetLocaleData();
+ sal_Unicode cLocaleDeciPnt = rData.getNumDecimalSep().GetBuffer()[0];
+ sal_Unicode cLocale1000Sep = rData.getNumThousandSep().GetBuffer()[0];
+
+ // score each set of separators (Locale and Basic) on total number of matches
+ // if one set has more matches use that set
+ // if tied use the set with the only or rightmost decimal separator match
+ // currency is fixed pt system: usually expect the decimal pt, 1000sep may occur
+ sal_Int32 LocaleScore = 0;
+ sal_Int32 LocaleLastDeci = -1;
+ sal_Int32 LOBasicScore = 0;
+ sal_Int32 LOBasicLastDeci = -1;
+
+ for( int idx=0; idx<rStr.getLength(); idx++ )
+ {
+ if ( *(p+idx) == cLocaleDeciPnt )
+ {
+ LocaleScore++;
+ LocaleLastDeci = idx;
+ }
+ if ( *(p+idx) == cLocale1000Sep )
+ LocaleScore++;
+
+ if ( *(p+idx) == cDeciPnt )
+ {
+ LOBasicScore++;
+ LOBasicLastDeci = idx;
+ }
+ if ( *(p+idx) == c1000Sep )
+ LOBasicScore++;
+ }
+ if ( ( LocaleScore > LOBasicScore )
+ ||( LocaleScore = LOBasicScore && LocaleLastDeci > LOBasicLastDeci ) )
+ {
+ cDeciPnt = cLocaleDeciPnt;
+ c1000Sep = cLocale1000Sep;
+ }
+#endif
+
+ // lets use the existing string number conversions
+ // there is a performance impact here ( multiple string copies )
+ // but better I think than a home brewed string parser, if we need a parser
+ // we should share some existing ( possibly from calc is there a currency
+ // conversion there ? #TODO check )
+
+ rtl::OUString sTmp( rStr.trim() );
+ const sal_Unicode* p = sTmp.getStr();
+
+ // normalise string number by removeing thousands & decimal point seperators
+ rtl::OUStringBuffer sNormalisedNumString( sTmp.getLength() + nFractDigit );
+
+ if ( *p == '-' || *p == '+' )
+ sNormalisedNumString.append( *p );
+
+ while ( ( *p >= '0' && *p <= '9' ) )
+ {
+ sNormalisedNumString.append( *p++ );
+ // #TODO in vba mode set runtime error when a space ( or other )
+ // illegal character is found
+ if( *p == c1000Sep )
+ p++;
+ }
+
+ bool bRoundUp = false;
+
+ if( *p == cDeciPnt )
+ {
+ p++;
+ while( nFractDigit && *p >= '0' && *p <= '9' )
+ {
+ sNormalisedNumString.append( *p++ );
+ nFractDigit--;
+ }
+ // Consume trailing content
+ if ( p != NULL )
+ {
+ // Round up if necessary
+ if( *p >= '5' && *p <= '9' )
+ bRoundUp = true;
+ while( *p >= '0' && *p <= '9' )
+ p++;
+ }
+
+ }
+ // can we raise error here ? ( previous behaviour was more forgiving )
+ // so... not sure that could bread existing code, lets see if anyone
+ // complains.
+
+ if ( p != sTmp.getStr() + sTmp.getLength() )
+ SbxBase::SetError( SbxERR_CONVERSION );
+ while( nFractDigit )
+ {
+ sNormalisedNumString.append( sal_Unicode('0') );
+ nFractDigit--;
+ }
+
+ sal_Int64 result = sNormalisedNumString.makeStringAndClear().toInt64();
+
+ if ( bRoundUp )
+ ++result;
+ return result;
+}
+
+
+sal_Int64 ImpGetCurrency( const SbxValues* p )
+{
+ SbxValues aTmp;
+ sal_Int64 nRes;
+start:
+ switch( +p->eType )
+ {
+ case SbxERROR:
+ case SbxNULL:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ nRes = 0; break;
+ case SbxEMPTY:
+ nRes = 0; break;
+ case SbxCURRENCY:
+ nRes = p->nInt64; break;
+ case SbxBYTE:
+ nRes = (sal_Int64)CURRENCY_FACTOR * (sal_Int64)(p->nByte);
+ break;
+ case SbxCHAR:
+ nRes = (sal_Int64)CURRENCY_FACTOR * (sal_Int64)(p->pChar);
+ break;
+ case SbxBOOL:
+ case SbxINTEGER:
+ nRes = (sal_Int64)CURRENCY_FACTOR * (sal_Int64)(p->nInteger);
+ break;
+ case SbxUSHORT:
+ nRes = (sal_Int64)CURRENCY_FACTOR * (sal_Int64)(p->nUShort);
+ break;
+ case SbxLONG:
+ nRes = (sal_Int64)CURRENCY_FACTOR * (sal_Int64)(p->nLong);
+ break;
+ case SbxULONG:
+ nRes = (sal_Int64)CURRENCY_FACTOR * (sal_Int64)(p->nULong);
+ break;
+
+ case SbxSALINT64:
+ {
+ nRes = p->nInt64 * CURRENCY_FACTOR; break;
+ if ( nRes > SbxMAXSALINT64 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXSALINT64;
+ }
+ }
+ case SbxSALUINT64:
+ nRes = p->nInt64 * CURRENCY_FACTOR; break;
+ if ( nRes > SbxMAXSALINT64 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXSALINT64;
+ }
+ else if ( nRes < SbxMINSALINT64 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMINSALINT64;
+ }
+ break;
+//TODO: bring back SbxINT64 types here for limits -1 with flag value at SAL_MAX/MIN
+ case SbxSINGLE:
+ if( p->nSingle * CURRENCY_FACTOR + 0.5 > (float)SAL_MAX_INT64
+ || p->nSingle * CURRENCY_FACTOR - 0.5 < (float)SAL_MIN_INT64 )
+ {
+ nRes = SAL_MAX_INT64;
+ if( p->nSingle * CURRENCY_FACTOR - 0.5 < (float)SAL_MIN_INT64 )
+ nRes = SAL_MIN_INT64;
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ break;
+ }
+ nRes = ImpDoubleToCurrency( (double)p->nSingle );
+ break;
+
+ case SbxDATE:
+ case SbxDOUBLE:
+ if( p->nDouble * CURRENCY_FACTOR + 0.5 > (double)SAL_MAX_INT64
+ || p->nDouble * CURRENCY_FACTOR - 0.5 < (double)SAL_MIN_INT64 )
+ {
+ nRes = SAL_MAX_INT64;
+ if( p->nDouble * CURRENCY_FACTOR - 0.5 < (double)SAL_MIN_INT64 )
+ nRes = SAL_MIN_INT64;
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ break;
+ }
+ nRes = ImpDoubleToCurrency( p->nDouble );
+ break;
+
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ {
+ double d = 0.0;
+ if( p->pDecimal )
+ p->pDecimal->getDouble( d );
+ nRes = ImpDoubleToCurrency( d );
+ break;
+ }
+
+
+ case SbxBYREF | SbxSTRING:
+ case SbxSTRING:
+ case SbxLPSTR:
+ if( !p->pOUString )
+ nRes=0;
+ 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=0;
+ }
+ break;
+ }
+
+ case SbxBYREF | SbxCHAR:
+ nRes = (sal_Int64)CURRENCY_FACTOR * (sal_Int64)(*p->pChar);
+ break;
+ case SbxBYREF | SbxBYTE:
+ nRes = (sal_Int64)CURRENCY_FACTOR * (sal_Int64)(*p->pByte);
+ break;
+ case SbxBYREF | SbxBOOL:
+ case SbxBYREF | SbxINTEGER:
+ nRes = (sal_Int64)CURRENCY_FACTOR * (sal_Int64)(*p->pInteger);
+ break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ nRes = (sal_Int64)CURRENCY_FACTOR * (sal_Int64)(*p->pUShort);
+ 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 | SbxCURRENCY:
+ case SbxBYREF | SbxSALINT64:
+ aTmp.nInt64 = *p->pnInt64; goto ref;
+ case SbxBYREF | SbxSALUINT64:
+ aTmp.uInt64 = *p->puInt64; goto ref;
+ ref:
+ aTmp.eType = SbxDataType( p->eType & ~SbxBYREF );
+ p = &aTmp; goto start;
+
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ nRes=0;
+ }
+ return nRes;
+}
+
+
+void ImpPutCurrency( SbxValues* p, const sal_Int64 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)( r / CURRENCY_FACTOR ); break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ p->nDouble = ImpCurrencyToDouble( r ); break;
+ case SbxSALUINT64:
+ p->uInt64 = r / CURRENCY_FACTOR; break;
+ case SbxSALINT64:
+ p->nInt64 = r / CURRENCY_FACTOR; break;
+
+ case SbxCURRENCY:
+ p->nInt64 = r; break;
+
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ {
+ SbxDecimal* pDec = ImpCreateDecimal( p );
+ if( !pDec->setDouble( ImpCurrencyToDouble( r ) / CURRENCY_FACTOR ) )
+ 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:
+ {
+ sal_Int64 val = r / CURRENCY_FACTOR;
+ if( val > SbxMAXCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); val = SbxMAXCHAR;
+ }
+ else if( val < SbxMINCHAR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); val = SbxMINCHAR;
+ }
+ *p->pChar = (sal_Unicode) val; break;
+ }
+ case SbxBYREF | SbxBYTE:
+ {
+ sal_Int64 val = r / CURRENCY_FACTOR;
+ if( val > SbxMAXBYTE )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); val = SbxMAXBYTE;
+ }
+ else if( val < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); val = 0;
+ }
+ *p->pByte = (sal_uInt8) val; break;
+ }
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ {
+ sal_Int64 val = r / CURRENCY_FACTOR;
+ if( r > SbxMAXINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); val = SbxMAXINT;
+ }
+ else if( r < SbxMININT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); val = SbxMININT;
+ }
+ *p->pInteger = (sal_uInt16) val; break;
+ }
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ {
+ sal_Int64 val = r / CURRENCY_FACTOR;
+ if( val > SbxMAXUINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); val = SbxMAXUINT;
+ }
+ else if( val < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); val = 0;
+ }
+ *p->pUShort = (sal_uInt16) val; break;
+ }
+ case SbxBYREF | SbxLONG:
+ {
+ sal_Int64 val = r / CURRENCY_FACTOR;
+ if( val > SbxMAXLNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); val = SbxMAXLNG;
+ }
+ else if( val < SbxMINLNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); val = SbxMINLNG;
+ }
+ *p->pLong = (sal_Int32) val; break;
+ }
+ case SbxBYREF | SbxULONG:
+ {
+ sal_Int64 val = r / CURRENCY_FACTOR;
+ if( val > SbxMAXULNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); val = SbxMAXULNG;
+ }
+ else if( val < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); val = 0;
+ }
+ *p->pULong = (sal_uInt32) val; break;
+ break;
+ }
+ case SbxBYREF | SbxCURRENCY:
+ *p->pnInt64 = r; break;
+ case SbxBYREF | SbxSALINT64:
+ *p->pnInt64 = r / CURRENCY_FACTOR; break;
+ case SbxBYREF | SbxSALUINT64:
+ *p->puInt64 = (sal_uInt64)r / CURRENCY_FACTOR; break;
+ case SbxBYREF | SbxSINGLE:
+ p->nSingle = (float)( r / CURRENCY_FACTOR ); break;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ *p->pDouble = ImpCurrencyToDouble( r ); break;
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ }
+}
+
+/* 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..804506c18215
--- /dev/null
+++ b/basic/source/sbx/sbxdate.cxx
@@ -0,0 +1,396 @@
+/* -*- 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 SbxCURRENCY:
+ nRes = ImpCurrencyToDouble( p->nInt64 ); 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
+ {
+ 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 );
+ sal_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 = sal_False;
+ }
+
+ if ( !bSuccess )
+ {
+ SbxBase::SetError( SbxERR_CONVERSION ); nRes = 0;
+ }
+
+ delete pFormatter;
+ }
+ 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 | SbxCURRENCY:
+ nRes = ImpCurrencyToDouble( *p->pnInt64 ); 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 SbxCURRENCY:
+ 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:
+ {
+ 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;
+ break;
+ }
+ 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 = (sal_uInt8) 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 = (sal_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 = (sal_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 = (sal_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 = (sal_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->pnInt64 = 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..c4bbbe46c4ec
--- /dev/null
+++ b/basic/source/sbx/sbxdbl.cxx
@@ -0,0 +1,319 @@
+/* -*- 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->nInt64 ); 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->pnInt64 ); 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, sal_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:
+ 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;
+
+ case SbxCURRENCY:
+ if( n > SbxMAXCURR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXCURR;
+ }
+ else if( n < SbxMINCURR )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMINCURR;
+ }
+ p->nInt64 = ImpDoubleToCurrency( n );
+ break;
+
+ // 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 = (sal_uInt8) 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 = (sal_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 = (sal_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 = (sal_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 = (sal_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->pnInt64 = 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..ddf9d68489a5
--- /dev/null
+++ b/basic/source/sbx/sbxdec.cxx
@@ -0,0 +1,748 @@
+/* -*- 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>
+
+
+// Implementation SbxDecimal
+SbxDecimal::SbxDecimal( void )
+{
+ setInt( 0 );
+ mnRefCount = 0;
+}
+
+SbxDecimal::SbxDecimal( const SbxDecimal& rDec )
+{
+#ifdef WIN32
+ maDec = rDec.maDec;
+#else
+ (void)rDec;
+#endif
+ mnRefCount = 0;
+}
+
+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;
+}
+
+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()
+{
+}
+
+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( (sal_uInt16)val, &maDec );
+}
+
+void SbxDecimal::setByte( sal_uInt8 val )
+{
+ VarDecFromUI1( (sal_uInt8)val, &maDec );
+}
+
+void SbxDecimal::setShort( sal_Int16 val )
+{
+ VarDecFromI2( (short)val, &maDec );
+}
+
+void SbxDecimal::setLong( sal_Int32 val )
+{
+ VarDecFromI4( (long)val, &maDec );
+}
+
+void SbxDecimal::setUShort( sal_uInt16 val )
+{
+ VarDecFromUI2( (sal_uInt16)val, &maDec );
+}
+
+void SbxDecimal::setULong( sal_uInt32 val )
+{
+ VarDecFromUI4( (sal_uIntPtr)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( (sal_Int32)val );
+}
+
+void SbxDecimal::setUInt( unsigned int val )
+{
+ setULong( (sal_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( sal_uInt8& rVal )
+{
+ bool bRet = ( VarUI1FromDec( &maDec, &rVal ) == S_OK );
+ return bRet;
+}
+
+bool SbxDecimal::getShort( sal_Int16& rVal )
+{
+ bool bRet = ( VarI2FromDec( &maDec, &rVal ) == S_OK );
+ return bRet;
+}
+
+bool SbxDecimal::getLong( sal_Int32& rVal )
+{
+ bool bRet = ( VarI4FromDec( &maDec, &rVal ) == S_OK );
+ return bRet;
+}
+
+bool SbxDecimal::getUShort( sal_uInt16& rVal )
+{
+ bool bRet = ( VarUI2FromDec( &maDec, &rVal ) == S_OK );
+ return bRet;
+}
+
+bool SbxDecimal::getULong( sal_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 )
+{
+ sal_Int32 TmpVal;
+ bool bRet = getLong( TmpVal );
+ rVal = TmpVal;
+ return bRet;
+}
+
+bool SbxDecimal::getUInt( unsigned int& rVal )
+{
+ sal_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( sal_uInt8 val ) { (void)val; }
+void SbxDecimal::setShort( sal_Int16 val ) { (void)val; }
+void SbxDecimal::setLong( sal_Int32 val ) { (void)val; }
+void SbxDecimal::setUShort( sal_uInt16 val ) { (void)val; }
+void SbxDecimal::setULong( sal_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( sal_uInt8& rVal ) { (void)rVal; return false; }
+bool SbxDecimal::getShort( sal_Int16& rVal ) { (void)rVal; return false; }
+bool SbxDecimal::getLong( sal_Int32& rVal ) { (void)rVal; return false; }
+bool SbxDecimal::getUShort( sal_uInt16& rVal ) { (void)rVal; return false; }
+bool SbxDecimal::getULong( sal_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 SbxCURRENCY:
+ {
+ if( !pnDecRes->setDouble( ImpCurrencyToDouble( p->nInt64 ) ) )
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ break;
+ }
+ case SbxSALINT64:
+ {
+ if( !pnDecRes->setDouble( (double)p->nInt64 ) )
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ break;
+ }
+ case SbxSALUINT64:
+ {
+ if( !pnDecRes->setDouble( (double)p->uInt64 ) )
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ break;
+ }
+ case SbxDATE:
+ case SbxDOUBLE:
+ {
+ double 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 | SbxCURRENCY:
+ 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 SbxINTEGER:
+ case SbxBOOL:
+ aTmp.pInteger = &p->nInteger; goto direct;
+ case SbxLONG:
+ aTmp.pLong = &p->nLong; goto direct;
+ case SbxCURRENCY:
+ case SbxSALINT64:
+ 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;
+
+ // from here on no longer
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ {
+ if( pDec != p->pDecimal )
+ {
+ releaseDecimalPtr( p->pDecimal );
+ 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 SbxLPSTR:
+ case SbxSTRING:
+ case SbxBYREF | SbxSTRING:
+ if( !p->pOUString )
+ p->pOUString = new ::rtl::OUString;
+ 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;
+ 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 | SbxCURRENCY:
+ double d;
+ if( !pDec->getDouble( d ) )
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ *p->pnInt64 = ImpDoubleToCurrency( d );
+ 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;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ if( !pDec->getDouble( *p->pDouble ) )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW );
+ *p->pDouble = 0;
+ }
+ 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..533ffb9aebb9
--- /dev/null
+++ b/basic/source/sbx/sbxdec.hxx
@@ -0,0 +1,122 @@
+/* -*- 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 <prewin.h>
+#include <postwin.h>
+
+#ifndef __MINGW32__
+#include <comutil.h>
+#endif
+#include <oleauto.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
+ sal_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( sal_uInt8 val );
+ void setShort( sal_Int16 val );
+ void setLong( sal_Int32 val );
+ void setUShort( sal_uInt16 val );
+ void setULong( sal_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( sal_uInt8& rVal );
+ bool getShort( sal_Int16& rVal );
+ bool getLong( sal_Int32& rVal );
+ bool getUShort( sal_uInt16& rVal );
+ bool getULong( sal_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..f12ffc0bf817
--- /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:
+ sal_Bool isAlpha( sal_Unicode c ) const
+ {
+ sal_Bool bRet = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+ return bRet;
+ }
+
+ sal_Bool isDigit( sal_Unicode c ) const
+ {
+ sal_Bool bRet = (c >= '0' && c <= '9');
+ return bRet;
+ }
+
+ sal_Bool isAlphaNumeric( sal_Unicode c ) const
+ {
+ sal_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 )
+{
+ sal_uInt16 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, sal_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!
+ sal_uInt16 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, sal_False ) );
+ p = SkipWhitespace( p );
+ while( refVar.Is() && ( *p == '*' || *p == '/' ) )
+ {
+ xub_Unicode cOp = *p++;
+ SbxVariableRef refVar2( Operand( pObj, pGbl, &p, sal_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, sal_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() )
+ {
+ sal_uInt16 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;
+ sal_uInt16 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..61fbafdd37cf
--- /dev/null
+++ b/basic/source/sbx/sbxform.cxx
@@ -0,0 +1,1118 @@
+/* -*- 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)
+// 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, sal_uInt16 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 )
+{
+ sal_uInt16 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, sal_Bool& bOverflow )
+{
+ // wurde ggf ein falscher Index uebergeben --> Aufruf ignorieren
+ if( nPos<0 )
+ return;
+
+ bOverflow = sal_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 = sal_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 = sal_True;
+ }
+ }
+}
+
+// rundet in einem String die Ziffer an der angegebenen Stelle
+void SbxBasicFormater::StrRoundDigit( String& sStrg, short nPos )
+{
+ sal_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, sal_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
+ sal_uInt16 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 = sal_True;
+ return (short)(sSciNumStrg.GetChar( no ) - ASCII_0);
+}
+
+short SbxBasicFormater::GetDigitAtPosExpScan( short nPos, sal_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
+ sal_uInt16 no = 1;
+ no += nExpExp-nPos;
+ // Abfrage der ersten (g"ultigen) Ziffer der Zahl --> Flag setzen
+ if( nPos==nExpExp )
+ bFoundFirstDigit = sal_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,
+ sal_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, sal_Bool& bFoundFirstDigit )
+// ACHTUNG: nPos kann auch negativ werden, f"ur Stellen nach dem Dezimal-Punkt
+{
+ double dDigit;
+ short nMaxDigit;
+
+ // erst mal aus der Zahl eine positive Zahl machen:
+ dNumber = fabs( dNumber );
+
+ // "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 = sal_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, sal_Bool & bFound )
+{
+ bFound = sal_False; // default...
+ sal_uInt16 nPos = sFormatStrg.Search( FORMAT_SEPARATOR );
+
+ if( nPos!=STRING_NOTFOUND )
+ {
+ bFound = sal_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, sal_Bool & bFound )
+{
+ bFound = sal_False; // default...
+ sal_uInt16 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 = sal_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, sal_Bool & bFound )
+{
+ bFound = sal_False; // default...
+ sal_uInt16 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 = sal_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, sal_Bool & bFound )
+{
+ bFound = sal_False; // default...
+ sal_uInt16 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 = sal_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,
+ sal_Bool& bPercent, sal_Bool& bCurrency, sal_Bool& bScientific,
+ sal_Bool& bGenerateThousandSeparator,
+ short& nMultipleThousandSeparators )
+{
+ sal_uInt16 nLen;
+ short nState = 0;
+
+ nLen = sFormatStrg.Len();
+ // initialisiere alle Z"ahler und Flags
+ nNoOfDigitsLeft = 0;
+ nNoOfDigitsRight = 0;
+ nNoOfOptionalDigitsLeft = 0;
+ nNoOfExponentDigits = 0;
+ nNoOfOptionalExponentDigits = 0;
+ bPercent = sal_False;
+ bCurrency = sal_False;
+ bScientific = sal_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( sal_uInt16 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 = sal_True;
+ break;
+ case '(':
+ bCurrency = sal_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 = sal_True;
+ }
+ break;
+ // EIGENES Kommando-Zeichen, das die Erzeugung der
+ // Tausender-Trennzeichen einschaltet
+ case '\\':
+ // Ignore next char
+ i++;
+ break;
+ case CREATE_1000SEP_CHAR:
+ bGenerateThousandSeparator = sal_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,
+ sal_Bool bCreateSign )
+{
+ short /*nErr,*/nNoOfDigitsLeft,nNoOfDigitsRight,nNoOfOptionalDigitsLeft,
+ nNoOfExponentDigits,nNoOfOptionalExponentDigits,
+ nMultipleThousandSeparators;
+ sal_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
+ */
+ AnalyseFormatString( sFormatStrg,nNoOfDigitsLeft,nNoOfDigitsRight,
+ nNoOfOptionalDigitsLeft,nNoOfExponentDigits,
+ nNoOfOptionalExponentDigits,
+ bPercent,bCurrency,bScientific,bGenerateThousandSeparator,
+ nMultipleThousandSeparators );
+ // 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;
+ sal_Bool bFirstDigit,bFirstExponentDigit,bFoundFirstDigit,
+ bIsNegative,bZeroSpaceOn, bSignHappend,bDigitPosNegative;
+
+ // Initialisierung der Arbeits-Variablen
+ bSignHappend = sal_False;
+ bFoundFirstDigit = sal_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 )
+ {
+ // 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 = sal_True;
+ bFirstExponentDigit = sal_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 )
+ {
+ // ggf. Vorzeichen erzeugen
+ // Bem.: bei bCurrency soll das negative
+ // Vorzeichen durch () angezeigt werden
+ if( bIsNegative && !bCreateSign && !bSignHappend )
+ {
+ // nur einmal ein Vorzeichen ausgeben
+ bSignHappend = sal_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 = sal_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 = sal_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 = sal_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 = sal_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;
+ }
+
+ sal_Bool bOverflow = sal_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,'+' );
+ }
+ }
+ break;
+ case ',':
+ 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)
+ c = sFormatStrg.GetChar( ++i );
+ if( c!=0 )
+ StrAppendChar( sReturnStrg,c );
+ 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 );
+ }
+ }
+ // 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 )
+{
+ sal_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 )
+{
+ sal_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 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=*/sal_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=*/sal_False );
+ }
+ }
+ return sReturnStrg;
+}
+
+sal_Bool SbxBasicFormater::isBasicFormat( String sFormatStrg )
+{
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_GENERALNUMBER ) )
+ return sal_True;
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_CURRENCY ) )
+ return sal_True;
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_FIXED ) )
+ return sal_True;
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_STANDARD ) )
+ return sal_True;
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_PERCENT ) )
+ return sal_True;
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_SCIENTIFIC ) )
+ return sal_True;
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_YESNO ) )
+ return sal_True;
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_TRUEFALSE ) )
+ return sal_True;
+ if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_ONOFF ) )
+ return sal_True;
+ return sal_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..289622a016fd
--- /dev/null
+++ b/basic/source/sbx/sbxint.cxx
@@ -0,0 +1,912 @@
+/* -*- 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 );
+}
+
+sal_Int16 ImpGetInteger( const SbxValues* p )
+{
+ SbxValues aTmp;
+ sal_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 > (sal_uInt16) SbxMAXINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXINT;
+ }
+ else
+ nRes = (sal_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 = (sal_Int16) p->nLong;
+ break;
+ case SbxULONG:
+ if( p->nULong > SbxMAXINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXINT;
+ }
+ else
+ nRes = (sal_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 = (sal_Int16) ImpRound( p->nSingle );
+ break;
+ case SbxCURRENCY:
+ {
+ sal_Int64 tstVal = (sal_Int64) p->nInt64 / (sal_Int64) CURRENCY_FACTOR;
+
+ if( tstVal > SbxMAXINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXINT;
+ }
+ else if( tstVal < SbxMININT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMININT;
+ }
+ else
+ nRes = (sal_Int16) (tstVal);
+ 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 = (sal_Int16) p->nInt64;
+ break;
+ case SbxSALUINT64:
+ if( p->uInt64 > SbxMAXINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXINT;
+ }
+ else
+ nRes = (sal_Int16) p->uInt64;
+ break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ {
+ double dVal = 0.0;
+ if( p->eType == SbxDECIMAL )
+ {
+ 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 = (sal_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 = (sal_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 | SbxCURRENCY:
+ 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, sal_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;
+
+ // from here no tests needed
+ 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 SbxCURRENCY:
+ p->nInt64 = n * CURRENCY_FACTOR; break;
+ case SbxSALINT64:
+ p->nInt64 = 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 = (sal_uInt8) 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 = (sal_uInt16) n; break;
+ case SbxBYREF | SbxLONG:
+ *p->pLong = (sal_Int32) n; break;
+ case SbxBYREF | SbxULONG:
+ if( n < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = 0;
+ }
+ *p->pULong = (sal_uInt32) n; break;
+ case SbxBYREF | SbxCURRENCY:
+ *p->pnInt64 = n * CURRENCY_FACTOR; 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;
+
+ 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 = (sal_Int64) p->nUShort; break;
+ case SbxLONG:
+ nRes = (sal_Int64) p->nLong; break;
+ case SbxULONG:
+ nRes = (sal_Int64) p->nULong; break;
+ case SbxSINGLE:
+ nRes = (sal_Int64) p->nSingle;
+ break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ nRes = (sal_Int64) p->nDouble;
+ break;
+ case SbxCURRENCY:
+ nRes = p->nInt64 / CURRENCY_FACTOR; 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 = (sal_Int64) 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 | SbxCURRENCY:
+ nRes = p->nInt64 / CURRENCY_FACTOR; break;
+ case SbxBYREF | SbxSALINT64:
+ nRes = *p->pnInt64; break;
+
+ // from here the values has to be checked
+ case SbxBYREF | SbxSALUINT64:
+ aTmp.uInt64 = *p->puInt64; 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;
+ 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 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 SbxCURRENCY:
+ case SbxSALINT64:
+ 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;
+
+ 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 = (sal_uInt8) 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 = (sal_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 = (sal_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 = (sal_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 = (sal_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:
+ *p->pnInt64 = n * CURRENCY_FACTOR; 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 = (sal_uInt64) p->nSingle; break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ {
+//TODO overflow check
+ nRes = (sal_uInt64) p->nDouble;
+ break;
+ }
+ case SbxCURRENCY:
+ nRes = p->nInt64 * CURRENCY_FACTOR; break;
+ case SbxSALINT64:
+ if( p->nInt64 < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0;
+ }
+ else
+ nRes = (sal_uInt64) p->nInt64;
+ break;
+ 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 on the value 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 | SbxCURRENCY:
+ 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 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 SbxCURRENCY:
+ 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 = (sal_uInt8) n; break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ if( n > SbxMAXINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXINT;
+ }
+ *p->pInteger = (sal_Int16) n; break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ if( n > SbxMAXUINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXUINT;
+ }
+ *p->pUShort = (sal_uInt16) n; break;
+ case SbxBYREF | SbxLONG:
+ if( n > SbxMAXLNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXLNG;
+ }
+ *p->pLong = (sal_Int32) n; break;
+ case SbxBYREF | SbxULONG:
+ if( n > SbxMAXULNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXULNG;
+ }
+ *p->pULong = (sal_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 / CURRENCY_FACTOR ) )
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXSALINT64;
+ *p->pnInt64 = ( sal_Int64) ( n * CURRENCY_FACTOR ); 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..dd772fe4a52a
--- /dev/null
+++ b/basic/source/sbx/sbxlng.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"
+
+sal_Int32 ImpGetLong( const SbxValues* p )
+{
+ SbxValues aTmp;
+ sal_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 = (sal_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 = (sal_Int32) ImpRound( p->nSingle );
+ break;
+ case SbxSALINT64:
+ nRes = p->nInt64;
+ break;
+ case SbxSALUINT64:
+ nRes = p->uInt64;
+ break;
+ case SbxCURRENCY:
+ {
+ sal_Int64 tstVal = p->nInt64 / CURRENCY_FACTOR;
+ nRes = (sal_Int32) (tstVal);
+ if( tstVal < SbxMINLNG || SbxMAXLNG < tstVal ) SbxBase::SetError( SbxERR_OVERFLOW );
+ if( SbxMAXLNG < tstVal ) nRes = SbxMAXLNG;
+ if( tstVal < SbxMINLNG ) nRes = SbxMINLNG;
+ break;
+ }
+ case SbxDATE:
+ case SbxDOUBLE:
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ {
+ double dVal;
+ 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 = (sal_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 = (sal_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 | SbxCURRENCY:
+ 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 ImpPutLong( SbxValues* p, sal_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 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 SbxCURRENCY:
+ p->nInt64 = n * CURRENCY_FACTOR; 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 = (sal_uInt8) 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 = (sal_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 = (sal_uInt16) n; break;
+ case SbxBYREF | SbxLONG:
+ *p->pLong = n; break;
+ case SbxBYREF | SbxULONG:
+ if( n < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = 0;
+ }
+ *p->pULong = (sal_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:
+ *p->pnInt64 = (sal_Int64)n * (sal_Int64)CURRENCY_FACTOR; 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..e4ed782d75b2
--- /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..8c1bbbec6119
--- /dev/null
+++ b/basic/source/sbx/sbxobj.cxx
@@ -0,0 +1,1022 @@
+/* -*- 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 "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 sal_uInt16 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 );
+ // The arrays were copied, the content taken over
+ *pMethods = *r.pMethods;
+ *pProps = *r.pProps;
+ *pObjs = *r.pObjs;
+ // Because the variables were taken over, this is OK
+ pDfltProp = r.pDfltProp;
+ SetName( r.GetName() );
+ SetFlags( r.GetFlags() );
+ SetModified( sal_True );
+ }
+ return *this;
+}
+
+static void CheckParentsOnDelete( SbxObject* pObj, SbxArray* p )
+{
+ for( sal_uInt16 i = 0; i < p->Count(); i++ )
+ {
+ SbxVariableRef& rRef = p->GetRef( i );
+ if( rRef->IsBroadcaster() )
+ pObj->EndListening( rRef->GetBroadcaster(), sal_True );
+ // Did the element have more then one reference and still a 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 );
+
+ // avoid handling in ~SbxVariable as SBX_DIM_AS_NEW == SBX_GBLSEARCH
+ ResetFlag( SBX_DIM_AS_NEW );
+}
+
+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( sal_False );
+}
+
+void SbxObject::SFX_NOTIFY( SfxBroadcaster&, const TypeId&,
+ const SfxHint& rHint, const TypeId& )
+{
+ const SbxHint* p = PTR_CAST(SbxHint,&rHint);
+ if( p )
+ {
+ sal_uIntPtr nId = p->GetId();
+ sal_Bool bRead = sal_Bool( nId == SBX_HINT_DATAWANTED );
+ sal_Bool bWrite = sal_Bool( nId == SBX_HINT_DATACHANGED );
+ SbxVariable* pVar = p->GetVar();
+ if( bRead || bWrite )
+ {
+ XubString aVarName( pVar->GetName() );
+ sal_uInt16 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_ );
+ }
+ }
+ }
+}
+
+sal_Bool SbxObject::IsClass( const XubString& rName ) const
+{
+ return sal_Bool( aClassName.EqualsIgnoreCaseAscii( rName ) );
+}
+
+SbxVariable* SbxObject::FindUserData( sal_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 the parents?
+ if( !pRes && IsSet( SBX_GBLSEARCH ) )
+ {
+ SbxObject* pCur = this;
+ while( !pRes && pCur->pParent )
+ {
+ // I myself was already searched through!
+ sal_uInt16 nOwn = pCur->GetFlags();
+ pCur->ResetFlag( SBX_EXTSEARCH );
+ // I search already global!
+ sal_uInt16 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 sal_uInt16 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 );
+ }
+ // ExtendedsSearch in the Object-Array?
+ // For objects and DontCare is the Objektarray already
+ // searched through
+ if( !pRes && ( t == SbxCLASS_METHOD || t == SbxCLASS_PROPERTY ) )
+ pRes = pObjs->Find( rName, t );
+ // Search in the parents?
+ if( !pRes && IsSet( SBX_GBLSEARCH ) )
+ {
+ SbxObject* pCur = this;
+ while( !pRes && pCur->pParent )
+ {
+ // I myself was already searched through!
+ sal_uInt16 nOwn = pCur->GetFlags();
+ pCur->ResetFlag( SBX_EXTSEARCH );
+ // I search already global!
+ sal_uInt16 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;
+}
+
+// Abbreviated version: The parent-string will be searched through
+// The whole thing recursive, because Call() might be overloaded
+// Qualified names are allowed
+
+sal_Bool SbxObject::Call( const XubString& rName, SbxArray* pParam )
+{
+ SbxVariable* pMeth = FindQualified( rName, SbxCLASS_DONTCARE);
+ if( pMeth && pMeth->ISA(SbxMethod) )
+ {
+ // FindQualified() might have been stroked!
+ if( pParam )
+ pMeth->SetParameters( pParam );
+ pMeth->Broadcast( SBX_HINT_DATAWANTED );
+ pMeth->SetParameters( NULL );
+ return sal_True;
+ }
+ SetError( SbxERR_NO_METHOD );
+ return sal_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( sal_True );
+}
+
+void SbxObject::SetDfltProperty( SbxProperty* p )
+{
+ if( p )
+ {
+ sal_uInt16 n;
+ SbxArray* pArray = FindVar( p, n );
+ pArray->Put( p, n );
+ if( p->GetParent() != this )
+ p->SetParent( this );
+ Broadcast( SBX_HINT_OBJECTCHANGED );
+ }
+ pDfltProp = p;
+ SetModified( sal_True );
+}
+
+// Search of a already available variable. If she was located,
+// the index will be set, elsewise will be delivered the Count of the Array.
+// In any case it will be delivered the correct Array.
+
+SbxArray* SbxObject::FindVar( SbxVariable* pVar, sal_uInt16& 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();
+ // Is the variable per name available?
+ pArray->ResetFlag( SBX_EXTSEARCH );
+ SbxVariable* pOld = pArray->Find( pVar->GetName(), pVar->GetClass() );
+ if( pOld )
+ for( sal_uInt16 i = 0; i < pArray->Count(); i++ )
+ {
+ SbxVariableRef& rRef = pArray->GetRef( i );
+ if( (SbxVariable*) rRef == pOld )
+ {
+ nArrayIdx = i; break;
+ }
+ }
+ }
+ return pArray;
+}
+
+// If a new object will be established, this object will be indexed,
+// if an object of this name exists already.
+
+SbxVariable* SbxObject::Make( const XubString& rName, SbxClassType ct, SbxDataType dt )
+{
+ // Is the object already available?
+ 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 may contain objects of the same name
+ if( !( ct == SbxCLASS_OBJECT && ISA(SbxCollection) ) )
+ {
+ SbxVariable* pRes = pArray->Find( rName, ct );
+ if( pRes )
+ {
+ 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( sal_True );
+ // The object listen always
+ StartListening( pVar->GetBroadcaster(), sal_True );
+ Broadcast( SBX_HINT_OBJECTCHANGED );
+ return pVar;
+}
+
+SbxObject* SbxObject::MakeObject( const XubString& rName, const XubString& rClass )
+{
+ // Is the object already available?
+ if( !ISA(SbxCollection) )
+ {
+ SbxVariable* pRes = pObjs->Find( rName, SbxCLASS_OBJECT );
+ if( pRes )
+ {
+ return PTR_CAST(SbxObject,pRes);
+ }
+ }
+ SbxObject* pVar = CreateObject( rClass );
+ if( pVar )
+ {
+ pVar->SetName( rName );
+ pVar->SetParent( this );
+ pObjs->Put( pVar, pObjs->Count() );
+ SetModified( sal_True );
+ // The object listen always
+ StartListening( pVar->GetBroadcaster(), sal_True );
+ Broadcast( SBX_HINT_OBJECTCHANGED );
+ }
+ return pVar;
+}
+
+void SbxObject::Insert( SbxVariable* pVar )
+{
+ sal_uInt16 nIdx;
+ SbxArray* pArray = FindVar( pVar, nIdx );
+ if( pArray )
+ {
+ // Into with it. But you should pay attention at the Pointer!
+ if( nIdx < pArray->Count() )
+ {
+ // Then this element exists already
+ // There are objects of the same name allowed at collections
+ if( pArray == pObjs && ISA(SbxCollection) )
+ nIdx = pArray->Count();
+ else
+ {
+ SbxVariable* pOld = pArray->Get( nIdx );
+ // already inside: overwrite
+ if( pOld == pVar )
+ return;
+
+ EndListening( pOld->GetBroadcaster(), sal_True );
+ if( pVar->GetClass() == SbxCLASS_PROPERTY )
+ {
+ if( pOld == pDfltProp )
+ pDfltProp = (SbxProperty*) pVar;
+ }
+ }
+ }
+ StartListening( pVar->GetBroadcaster(), sal_True );
+ pArray->Put( pVar, nIdx );
+ if( pVar->GetParent() != this )
+ pVar->SetParent( this );
+ SetModified( sal_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
+ }
+}
+
+// Optimisation, Insertion without checking about
+// double entry and without broadcasts, will only be used in SO2/auto.cxx
+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(), sal_True );
+ pArray->Put( pVar, pArray->Count() );
+ if( pVar->GetParent() != this )
+ pVar->SetParent( this );
+ SetModified( sal_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
+ }
+}
+
+// special method, allow controls of the same name
+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(), sal_True );
+ pArray->Put( pVar, pArray->Count() );
+ if( pVar->GetParent() != this )
+ pVar->SetParent( this );
+ SetModified( sal_True );
+ Broadcast( SBX_HINT_OBJECTCHANGED );
+ }
+}
+
+void SbxObject::Remove( const XubString& rName, SbxClassType t )
+{
+ Remove( SbxObject::Find( rName, t ) );
+}
+
+void SbxObject::Remove( SbxVariable* pVar )
+{
+ sal_uInt16 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(), sal_True );
+ if( (SbxVariable*) pVar_ == pDfltProp )
+ pDfltProp = NULL;
+ pArray->Remove( nIdx );
+ if( pVar_->GetParent() == this )
+ pVar_->SetParent( NULL );
+ SetModified( sal_True );
+ Broadcast( SBX_HINT_OBJECTCHANGED );
+ }
+}
+
+// cleanup per Pointer for Controls (double names!)
+void SbxObject::VCPtrRemove( SbxVariable* pVar )
+{
+ sal_uInt16 nIdx;
+ // New FindVar-Method, otherwise identical with the normal method
+ SbxArray* pArray = VCPtrFindVar( pVar, nIdx );
+ if( pArray && nIdx < pArray->Count() )
+ {
+ SbxVariableRef xVar = pArray->Get( nIdx );
+ if( xVar->IsBroadcaster() )
+ EndListening( xVar->GetBroadcaster(), sal_True );
+ if( (SbxVariable*) xVar == pDfltProp )
+ pDfltProp = NULL;
+ pArray->Remove( nIdx );
+ if( xVar->GetParent() == this )
+ xVar->SetParent( NULL );
+ SetModified( sal_True );
+ Broadcast( SBX_HINT_OBJECTCHANGED );
+ }
+}
+
+// associated special method, search only by Pointer
+SbxArray* SbxObject::VCPtrFindVar( SbxVariable* pVar, sal_uInt16& 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( sal_uInt16 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, sal_uInt16 nPos )
+{
+ sal_uInt16 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 );
+ }
+ }
+}
+
+static sal_Bool LoadArray( SvStream& rStrm, SbxObject* pThis, SbxArray* pArray )
+{
+ SbxArrayRef p = (SbxArray*) SbxBase::Load( rStrm );
+ if( !p.Is() )
+ return sal_False;
+ for( sal_uInt16 i = 0; i < p->Count(); i++ )
+ {
+ SbxVariableRef& r = p->GetRef( i );
+ SbxVariable* pVar = r;
+ if( pVar )
+ {
+ pVar->SetParent( pThis );
+ pThis->StartListening( pVar->GetBroadcaster(), sal_True );
+ }
+ }
+ pArray->Merge( p );
+ return sal_True;
+}
+
+// The load of an object is additive!
+
+sal_Bool SbxObject::LoadData( SvStream& rStrm, sal_uInt16 nVer )
+{
+ // Help for the read in of old objects: just TRUE back,
+ // LoadPrivateData() had to set the default status up
+ if( !nVer )
+ return sal_True;
+
+ pDfltProp = NULL;
+ if( !SbxVariable::LoadData( rStrm, nVer ) )
+ return sal_False;
+ // If it contains no alien object, insert ourselves
+ 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 );
+ sal_uIntPtr nPos = rStrm.Tell();
+ rStrm >> nSize;
+ if( !LoadPrivateData( rStrm, nVer ) )
+ return sal_False;
+ sal_uIntPtr 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 sal_False;
+ // Set properties
+ if( aDfltProp.Len() )
+ pDfltProp = (SbxProperty*) pProps->Find( aDfltProp, SbxCLASS_PROPERTY );
+ SetModified( sal_False );
+ return sal_True;
+}
+
+sal_Bool SbxObject::StoreData( SvStream& rStrm ) const
+{
+ if( !SbxVariable::StoreData( rStrm ) )
+ return sal_False;
+ XubString aDfltProp;
+ if( pDfltProp )
+ aDfltProp = pDfltProp->GetName();
+ rStrm.WriteByteString( aClassName, RTL_TEXTENCODING_ASCII_US );
+ rStrm.WriteByteString( aDfltProp, RTL_TEXTENCODING_ASCII_US );
+ sal_uIntPtr nPos = rStrm.Tell();
+ rStrm << (sal_uInt32) 0L;
+ if( !StorePrivateData( rStrm ) )
+ return sal_False;
+ sal_uIntPtr nNew = rStrm.Tell();
+ rStrm.Seek( nPos );
+ rStrm << (sal_uInt32) ( nNew - nPos );
+ rStrm.Seek( nNew );
+ if( !pMethods->Store( rStrm ) )
+ return sal_False;
+ if( !pProps->Store( rStrm ) )
+ return sal_False;
+ if( !pObjs->Store( rStrm ) )
+ return sal_False;
+ ((SbxObject*) this)->SetModified( sal_False );
+ return sal_True;
+}
+
+XubString SbxObject::GenerateSource( const XubString &rLinePrefix,
+ const SbxObject* )
+{
+ // Collect the properties in a String
+ XubString aSource;
+ SbxArrayRef xProps( GetProperties() );
+ bool bLineFeed = false;
+ for ( sal_uInt16 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 ) ) )
+ {
+ // Insert a break except in front of the first property
+ if ( bLineFeed )
+ aSource.AppendAscii( "\n" );
+ else
+ bLineFeed = true;
+
+ aSource += rLinePrefix;
+ aSource += '.';
+ aSource += aPropName;
+ aSource.AppendAscii( " = " );
+
+ // Display the property value textual
+ switch ( xProp->GetType() )
+ {
+ case SbxEMPTY:
+ case SbxNULL:
+ // no value
+ break;
+
+ case SbxSTRING:
+ {
+ // Strings in quotation mark
+ aSource.AppendAscii( "\"" );
+ aSource += xProp->GetString();
+ aSource.AppendAscii( "\"" );
+ break;
+ }
+
+ default:
+ {
+ // miscellaneous, such as e.g.numerary directly
+ aSource += xProp->GetString();
+ break;
+ }
+ }
+ }
+ }
+ return aSource;
+}
+
+static sal_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 sal_True;
+ }
+ else
+ {
+ rRes.Erase();
+ return sal_False;
+ }
+}
+
+void SbxObject::Dump( SvStream& rStrm, sal_Bool bFill )
+{
+ // Shifting
+ static sal_uInt16 nLevel = 0;
+ if ( nLevel > 10 )
+ {
+ rStrm << "<too deep>" << endl;
+ return;
+ }
+ ++nLevel;
+ String aIndent;
+ for ( sal_uInt16 n = 1; n < nLevel; ++n )
+ aIndent.AppendAscii( " " );
+
+ // if necessary complete the object
+ if ( bFill )
+ GetAll( SbxCLASS_DONTCARE );
+
+ // Output the data of the object itself
+ ByteString aNameStr( (const UniString&)GetName(), RTL_TEXTENCODING_ASCII_US );
+ ByteString aClassNameStr( (const UniString&)aClassName, RTL_TEXTENCODING_ASCII_US );
+ rStrm << "Object( "
+ << ByteString::CreateFromInt64( (sal_uIntPtr) 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( (sal_uIntPtr) 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( sal_uInt16 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 );
+
+ // Output also the object at object-methods
+ 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( sal_uInt16 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 );
+
+ // output also the object at object properties
+ 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( sal_uInt16 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;
+}
+
+sal_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( sal_uIntPtr /* nObjects */ )
+
+/* [Description]
+
+ This statistic method browse the next 'nObjects' of the currently existing
+ <SbxObject>-Instances for cyclic references, which keep only themselfes alive
+ If there is 'nObjects==0', then all existing will be browsed.
+
+ currently only implemented: 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..5b6466e21e2c
--- /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( sal_uInt16 nId )
+{
+ return ( ( nId > SBXRES_MAX ) ? "???" : pSbxRes[ nId ] );
+}
+
+SbxRes::SbxRes( sal_uInt16 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..c50b197a4e88
--- /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( sal_uInt16 );
+};
+
+const char* GetSbxRes( sal_uInt16 );
+
+
+#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..95d4b8dbc836
--- /dev/null
+++ b/basic/source/sbx/sbxscan.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"
+
+#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,
+ sal_uInt16* pLen, sal_Bool bAllowIntntl, sal_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;
+ sal_Bool bRes = sal_True;
+ sal_Bool bMinus = sal_False;
+ nVal = 0;
+ SbxDataType eScanType = SbxSINGLE;
+ // Whitespace wech
+ while( *p &&( *p == ' ' || *p == '\t' ) ) p++;
+ // Zahl? Dann einlesen und konvertieren.
+ if( *p == '-' )
+ p++, bMinus = sal_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 = sal_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 = sal_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 = sal_False;
+ }
+ *q = 0;
+ for( q = buf; *q; q++ )
+ {
+ i =( *q & 0xFF ) - '0';
+ if( i > 9 ) i -= 7;
+ l =( l * base ) + i;
+ if( !ndig-- )
+ bRes = sal_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 = (sal_uInt16) ( 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, sal_Bool bSingle )
+{
+ SbxDataType t;
+ sal_uInt16 nLen = 0;
+ SbxError nRetError = ImpScan( rSrc, nVal, t, &nLen,
+ /*bAllowIntntl*/sal_False, /*bOnlyIntntl*/sal_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, sal_Bool, sal_Bool )
+|*
+|* Beschreibung: Konversion double --> ASCII
+|* Parameter: double die Zahl.
+|* char * der Zielpuffer
+|* short Anzahl Nachkommastellen
+|* short Weite des Exponenten( 0=kein E )
+|* sal_Bool sal_True: mit 1000er Punkten
+|* sal_Bool sal_True: formatfreie Ausgabe
+|*
+***************************************************************************/
+
+static void myftoa( double nNum, char * pBuf, short nPrec, short nExpWidth,
+ sal_Bool bPt, sal_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;
+
+ // 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 )
+ {
+ register int digit;
+ 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, sal_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,
+ sal_False, sal_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
+
+sal_Bool ImpConvStringExt( ::rtl::OUString& rSrc, SbxDataType eTargetType )
+{
+ // Merken, ob ueberhaupt was geaendert wurde
+ sal_Bool bChanged = sal_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 = sal_True;
+ }
+ }
+ break;
+ }
+
+ // Bei sal_Bool sal_True und sal_False als String pruefen
+ case SbxBOOL:
+ {
+ if( rSrc.equalsIgnoreAsciiCaseAscii( "true" ) )
+ {
+ aNewString = ::rtl::OUString::valueOf( (sal_Int32)SbxTRUE );
+ bChanged = sal_True;
+ }
+ else
+ if( rSrc.equalsIgnoreAsciiCaseAscii( "false" ) )
+ {
+ aNewString = ::rtl::OUString::valueOf( (sal_Int32)SbxFALSE );
+ bChanged = sal_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 sal_uInt16 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
+ sal_Bool bPoint = sal_False; // sal_True: mit 1000er Kommas
+ sal_Bool bTrail = sal_False; // sal_True, wenn folgendes Minus
+ sal_Bool bSign = sal_False; // sal_True: immer mit Vorzeichen
+ sal_Bool bNeg = sal_False; // sal_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 = sal_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 = sal_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 = sal_True;
+
+ // Zahl konvertieren:
+ if( nPrec > 15 ) nPrec = 15;
+ if( nNum < 0.0 ) nNum = -nNum, bNeg = sal_True;
+ p = cBuf;
+ if( bSign ) *p++ = bNeg ? '-' : '+';
+ myftoa( nNum, p, nPrec, nExpDig, bPoint, sal_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 (sal_uInt16) ( pFmt - (const char*) rFmt );
+}
+
+#endif //_old_format_code_
+
+static sal_uInt16 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 (sal_uInt16) ( pFmt - pFmtStart );
+}
+
+
+sal_Bool SbxValue::Scan( const XubString& rSrc, sal_uInt16* 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 sal_False;
+ }
+ else
+ return sal_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( sal_uInt16 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;
+ sal_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
+sal_Int16 implGetWeekDay( double aDate, bool bFirstDayParam = false, sal_Int16 nFirstDay = 0 );
+// from methods.cxx
+sal_Int16 implGetMinute( double dDate );
+sal_Int16 implGetDateYear( double aDate );
+sal_Bool implDateSerial( sal_Int16 nYear, sal_Int16 nMonth, sal_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;
+ double nNumber;
+ Color* pCol;
+
+ sal_Bool bSuccess = aFormatter.IsNumberFormat( aStr, nIndex, nNumber );
+
+ // number format, use SvNumberFormatter to handle it.
+ if( bSuccess )
+ {
+ xub_StrLen nCheckPos = 0;
+ short nType;
+ 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 ))
+ {
+ sal_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 ))
+ {
+ sal_Int32 nWeekDay = implGetWeekDay( nNumber );
+ rRes = String::CreateFromInt32( nWeekDay );
+ }
+ else if( aFmtStr.EqualsIgnoreCaseAscii( VBAFORMAT_Y ))
+ {
+ sal_Int16 nYear = implGetDateYear( nNumber );
+ double dBaseDate;
+ implDateSerial( nYear, 1, 1, dBaseDate );
+ sal_Int32 nYear32 = 1 + sal_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 );
+ }
+
+ }
+ 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*/sal_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..62c98131a2c2
--- /dev/null
+++ b/basic/source/sbx/sbxsng.cxx
@@ -0,0 +1,350 @@
+/* -*- 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 SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ if( p->pDecimal )
+ p->pDecimal->getSingle( nRes );
+ else
+ nRes = 0.0;
+ break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ case SbxCURRENCY:
+ case SbxSALINT64:
+ case SbxSALUINT64:
+ {
+ double dVal;
+ if( p->eType == SbxCURRENCY )
+ dVal = ImpCurrencyToDouble( p->nInt64 );
+ else if( p->eType == SbxSALINT64 )
+ dVal = (float) p->nInt64;
+ else if( p->eType == SbxSALUINT64 )
+ dVal = (float) p->uInt64;
+ 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);
+ }
+ // tests for underflow - storing value too small for precision of single
+ 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 | SbxSALINT64:
+ case SbxBYREF | SbxCURRENCY:
+ 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 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 SbxCURRENCY:
+ 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 = (sal_uInt8) 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 = (sal_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 = (sal_uInt16) n; break;
+ case SbxBYREF | SbxLONG:
+ {
+ sal_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< sal_Int32 >(n);
+ }
+ *p->pLong = i; break;
+ }
+ case SbxBYREF | SbxULONG:
+ {
+ sal_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< sal_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 = (sal_Int64)n; break;
+ case SbxBYREF | SbxSALUINT64:
+ *p->puInt64 = (sal_uInt64)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->pnInt64 = ImpDoubleToCurrency( d ); 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..27d1ca192868
--- /dev/null
+++ b/basic/source/sbx/sbxstr.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"
+#include "sbxres.hxx"
+#include "runtime.hxx"
+#include <rtl/ustrbuf.hxx>
+
+// The conversion of an item onto String was handled via the Put-Methods
+// of the several data types to avoid double code.
+
+::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->nInt64 ); 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:
+ // Here will be created the String "Error n"
+ 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->pnInt64 ); break;
+ case SbxBYREF | SbxSALINT64:
+ ImpPutInt64( &aTmp, *p->pnInt64 ); break;
+ case SbxBYREF | SbxSALUINT64:
+ ImpPutUInt64( &aTmp, *p->puInt64 ); break;
+ default:
+ SbxBase::SetError( SbxERR_CONVERSION );
+ }
+ return aRes;
+}
+
+// From 1997-04-10, new function for SbxValue::GetCoreString()
+::rtl::OUString ImpGetCoreString( const SbxValues* p )
+{
+ // For now only for double
+ if( ( p->eType & (~SbxBYREF) ) == SbxDOUBLE )
+ {
+ SbxValues aTmp;
+ XubString aRes;
+ aTmp.eType = SbxSTRING;
+ if( p->eType == SbxDOUBLE )
+ ImpPutDouble( &aTmp, p->nDouble, sal_True ); // true = bCoreString
+ else
+ ImpPutDouble( &aTmp, *p->pDouble, sal_True ); // true = bCoreString
+ return aRes;
+ }
+ else
+ return ImpGetString( p );
+}
+
+void ImpPutString( SbxValues* p, const ::rtl::OUString* n )
+{
+ SbxValues aTmp;
+ aTmp.eType = SbxSTRING;
+ ::rtl::OUString* pTmp = NULL;
+ // as a precaution, if a NULL-Ptr appears
+ 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 SbxCURRENCY:
+ p->nInt64 = 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< sal_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->pnInt64 = ImpGetCurrency( p ); break;
+ case SbxBYREF | SbxSALINT64:
+ *p->pnInt64 = ImpGetInt64( p ); break;
+ case SbxBYREF | SbxSALUINT64:
+ *p->puInt64 = ImpGetUInt64( 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( sal_uInt16 i=0; i< nArraySize; i++)
+ {
+ SbxVariable* pNew = new SbxVariable( SbxBYTE );
+ sal_uInt8 aByte = static_cast< sal_uInt8 >( 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)
+{
+ sal_uInt16 nCount = pArr->Count();
+ ::rtl::OUStringBuffer aStrBuf;
+ sal_Unicode aChar = 0;
+ for( sal_uInt16 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..5922b3571987
--- /dev/null
+++ b/basic/source/sbx/sbxuint.cxx
@@ -0,0 +1,324 @@
+/* -*- 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"
+
+sal_uInt16 ImpGetUShort( const SbxValues* p )
+{
+ SbxValues aTmp;
+ sal_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 = (sal_uInt16) p->nLong;
+ break;
+ case SbxULONG:
+ if( p->nULong > SbxMAXUINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXUINT;
+ }
+ else
+ nRes = (sal_uInt16) p->nULong;
+ break;
+ case SbxCURRENCY:
+ if( p->nInt64 / CURRENCY_FACTOR > SbxMAXUINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXUINT;
+ }
+ else if( p->nInt64 < 0 )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = 0;
+ }
+ else
+ nRes = (sal_uInt16) (p->nInt64 / CURRENCY_FACTOR);
+ 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 = (sal_uInt16) p->nInt64;
+ break;
+ case SbxSALUINT64:
+ if( p->uInt64 > SbxMAXUINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); nRes = SbxMAXUINT;
+ }
+ else
+ nRes = (sal_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 = (sal_uInt16) ( p->nSingle + 0.5 );
+ break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ {
+ double dVal;
+ 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 = (sal_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 = (sal_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;
+
+ // 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 | SbxSINGLE:
+ aTmp.nSingle = *p->pSingle; goto ref;
+ case SbxBYREF | SbxDATE:
+ case SbxBYREF | SbxDOUBLE:
+ aTmp.nDouble = *p->pDouble; goto ref;
+ case SbxBYREF | SbxCURRENCY:
+ 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, sal_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 SbxCURRENCY:
+ p->nInt64 = n * CURRENCY_FACTOR; break;
+ case SbxSALINT64:
+ p->nInt64 = n; break;
+ case SbxSALUINT64:
+ p->uInt64 = n; break;
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ ImpCreateDecimal( p )->setUInt( n );
+ break;
+
+ // from here on tests
+ 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 = (sal_uInt8) n; break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ if( n > SbxMAXINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXINT;
+ }
+ *p->pInteger = (sal_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 | SbxCURRENCY:
+ *p->pnInt64 = n * CURRENCY_FACTOR; break;
+ case SbxBYREF | SbxSALINT64:
+ *p->pnInt64 = n; break;
+ case SbxBYREF | SbxSALUINT64:
+ *p->puInt64 = 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..b8f74b4bf5e6
--- /dev/null
+++ b/basic/source/sbx/sbxulng.cxx
@@ -0,0 +1,300 @@
+/* -*- 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"
+
+sal_uInt32 ImpGetULong( const SbxValues* p )
+{
+ SbxValues aTmp;
+ sal_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 = (sal_uInt32) ( p->nSingle + 0.5 );
+ break;
+ case SbxDATE:
+ case SbxDOUBLE:
+ case SbxSALINT64:
+ case SbxSALUINT64:
+ case SbxCURRENCY:
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ {
+ double dVal;
+ if( p->eType == SbxCURRENCY )
+ dVal = ImpCurrencyToDouble( p->nInt64 );
+ 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 = (sal_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 = (sal_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;
+
+ // from here on tests
+ 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 | SbxCURRENCY:
+ 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 ImpPutULong( SbxValues* p, sal_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 SbxCURRENCY:
+ case SbxSALINT64:
+ aTmp.pnInt64 = &p->nInt64; goto direct;
+ case SbxSALUINT64:
+ p->uInt64 = n; break;
+ case SbxDECIMAL:
+ case SbxBYREF | SbxDECIMAL:
+ ImpCreateDecimal( p )->setULong( n );
+ break;
+
+ // from here on tests
+ 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;
+ 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 = (sal_uInt8) n; break;
+ case SbxBYREF | SbxINTEGER:
+ case SbxBYREF | SbxBOOL:
+ if( n > SbxMAXINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXINT;
+ }
+ *p->pInteger = (sal_Int16) n; break;
+ case SbxBYREF | SbxERROR:
+ case SbxBYREF | SbxUSHORT:
+ if( n > SbxMAXUINT )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXUINT;
+ }
+ *p->pUShort = (sal_uInt16) n; break;
+ case SbxBYREF | SbxLONG:
+ if( n > SbxMAXLNG )
+ {
+ SbxBase::SetError( SbxERR_OVERFLOW ); n = SbxMAXLNG;
+ }
+ *p->pLong = (sal_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 | SbxCURRENCY:
+ *p->pnInt64 = n * CURRENCY_FACTOR; break;
+ case SbxBYREF | SbxSALINT64:
+ *p->pnInt64 = n; break;
+ case SbxBYREF | SbxSALUINT64:
+ *p->puInt64 = 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..71a3bfc7f0d8
--- /dev/null
+++ b/basic/source/sbx/sbxvals.cxx
@@ -0,0 +1,109 @@
+/*************************************************************************
+ *
+ * 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
+
+sal_Bool BigInt::INT64( SbxINT64 *p ) const
+{
+ if( bIsBig ) {
+ if( nLen > 4 || (nNum[3] & 0x8000) )
+ return sal_False;
+
+ p->nLow = ((sal_uInt32)nNum[1] << 16) | (sal_uInt32)nNum[0];
+ p->nHigh = ((sal_uInt32)nNum[3] << 16) | (sal_uInt32)nNum[2];
+ if( bIsNeg )
+ p->CHS();
+ }
+ else
+ p->Set( (sal_Int32)nVal );
+
+ return sal_True;
+}
+
+BigInt::BigInt( const SbxINT64 &r )
+{
+ BigInt a10000 = 0x10000;
+
+ *this = r.nHigh;
+ if( r.nHigh )
+ *this *= a10000;
+ *this += (sal_uInt16)(r.nLow >> 16);
+ *this *= a10000;
+ *this += (sal_uInt16)r.nLow;
+}
+
+sal_Bool BigInt::UINT64( SbxUINT64 *p ) const
+{
+ if( bIsBig ) {
+ if( bIsNeg || nLen > 4 )
+ return sal_False;
+
+ p->nLow = ((sal_uInt32)nNum[1] << 16) | (sal_uInt32)nNum[0];
+ p->nHigh = ((sal_uInt32)nNum[3] << 16) | (sal_uInt32)nNum[2];
+ }
+ else {
+ if( nVal < 0 )
+ return sal_False;
+
+ p->Set( (sal_uInt32)nVal );
+ }
+
+ return sal_True;
+}
+
+BigInt::BigInt( const SbxUINT64 &r )
+{
+ BigInt a10000 = 0x10000;
+
+ *this = BigInt(r.nHigh);
+ if( r.nHigh )
+ *this *= a10000;
+ *this += (sal_uInt16)(r.nLow >> 16);
+ *this *= a10000;
+ *this += (sal_uInt16)r.nLow;
+}
diff --git a/basic/source/sbx/sbxvalue.cxx b/basic/source/sbx/sbxvalue.cxx
new file mode 100644
index 000000000000..8b55561d2acf
--- /dev/null
+++ b/basic/source/sbx/sbxvalue.cxx
@@ -0,0 +1,1752 @@
+/* -*- 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 <math.h>
+#include <tools/stream.hxx>
+
+#include <basic/sbx.hxx>
+#include "sbxconv.hxx"
+#include "runtime.hxx"
+
+TYPEINIT1(SbxValue,SbxBase)
+
+
+///////////////////////////// error handling //////////////////////////////
+// bring back ?? was ever in ?? currently ifdef out ?
+#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 sal_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 = (sal_Int16*) p; break;
+ case SbxSALUINT64: n |= SbxBYREF; aData.puInt64 = (sal_uInt64*) p; break;
+ case SbxSALINT64:
+ case SbxCURRENCY: n |= SbxBYREF; aData.pnInt64 = (sal_Int64*) p; break;
+ case SbxLONG: n |= SbxBYREF; aData.pLong = (sal_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 = (sal_uInt16*) p; break;
+ case SbxULONG: n |= SbxBYREF; aData.pULong = (sal_uInt32*) p; break;
+ case SbxCHAR: n |= SbxBYREF; aData.pChar = (sal_Unicode*) p; break;
+ case SbxBYTE: n |= SbxBYREF; aData.pByte = (sal_uInt8*) 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);
+ sal_Bool bParentProp = pThisVar && 5345 ==
+ ( (sal_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);
+ sal_Bool bParentProp = pThisVar && 5345 ==
+ ( (sal_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( sal_uIntPtr )
+{}
+
+//////////////////////////// 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( sal_True );
+}
+
+// #55226 ship additional information
+bool handleToStringForCOMObjects( SbxObject* pObj, SbxValue* pVal ); // sbunoobj.cxx
+
+SbxValue* SbxValue::TheRealValue( sal_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
+ // 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 )
+ {
+ bool bSuccess = handleToStringForCOMObjects( pObj, p );
+ if( !bSuccess )
+ {
+ SetError( SbxERR_BAD_PROP_VALUE );
+ p = NULL;
+ }
+ }
+ else if( pDflt )
+ p = pDflt;
+ 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;
+}
+
+sal_Bool SbxValue::Get( SbxValues& rRes ) const
+{
+ sal_Bool bRes = sal_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.nInt64 = 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< sal_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 = sal_True;
+ if( eOld != SbxERR_OK )
+ SetError( eOld );
+ }
+ return bRes;
+}
+
+sal_Bool SbxValue::GetNoBroadcast( SbxValues& rRes )
+{
+ sal_uInt16 nFlags_ = GetFlags();
+ SetFlag( SBX_NO_BROADCAST );
+ sal_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;
+}
+
+sal_Bool SbxValue::HasObject() const
+{
+ ErrCode eErr = GetError();
+ SbxValues aRes;
+ aRes.eType = SbxOBJECT;
+ Get( aRes );
+ SetError( eErr );
+ return 0 != aRes.pObj;
+}
+
+sal_Bool SbxValue::GetBool() const
+{
+ SbxValues aRes;
+ aRes.eType = SbxBOOL;
+ Get( aRes );
+ return sal_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, sal_uInt8, nByte )
+GET( GetChar, SbxCHAR, xub_Unicode, nChar )
+GET( GetCurrency, SbxCURRENCY, sal_Int64, nInt64 )
+GET( GetDate, SbxDATE, double, nDouble )
+GET( GetData, SbxDATAOBJECT, void*, pData )
+GET( GetDouble, SbxDOUBLE, double, nDouble )
+GET( GetErr, SbxERROR, sal_uInt16, nUShort )
+GET( GetInt, SbxINT, int, nInt )
+GET( GetInteger, SbxINTEGER, sal_Int16, nInteger )
+GET( GetLong, SbxLONG, sal_Int32, nLong )
+GET( GetObject, SbxOBJECT, SbxBase*, pObj )
+GET( GetSingle, SbxSINGLE, float, nSingle )
+GET( GetULong, SbxULONG, sal_uInt32, nULong )
+GET( GetUShort, SbxUSHORT, sal_uInt16, nUShort )
+GET( GetInt64, SbxSALINT64, sal_Int64, nInt64 )
+GET( GetUInt64, SbxSALUINT64, sal_uInt64, uInt64 )
+GET( GetDecimal, SbxDECIMAL, SbxDecimal*, pDecimal )
+
+
+//////////////////////////// Write data /////////////////////////////
+
+sal_Bool SbxValue::Put( const SbxValues& rVal )
+{
+ sal_Bool bRes = sal_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( sal_False ); // 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.nInt64 ); 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, (sal_Int16) rVal.nInt );
+#else
+ ImpPutLong( &p->aData, (sal_Int32) rVal.nInt );
+#endif
+ break;
+ case SbxUINT:
+#if SAL_TYPES_SIZEOFINT == 2
+ ImpPutUShort( &p->aData, (sal_uInt16) rVal.nUInt );
+#else
+ ImpPutULong( &p->aData, (sal_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 )
+ {
+ OSL_FAIL( "TheRealValue" );
+ }
+ HACK(nicht bei Parent-Prop - sonst CyclicRef)
+ SbxVariable *pThisVar = PTR_CAST(SbxVariable, this);
+ sal_Bool bParentProp = pThisVar && 5345 ==
+ ( (sal_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( sal_True );
+ p->Broadcast( SBX_HINT_DATACHANGED );
+ if( eOld != SbxERR_OK )
+ SetError( eOld );
+ bRes = sal_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)
+sal_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)
+ sal_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
+ sal_uInt16 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 = sal_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;
+}
+
+sal_Bool SbxValue::PutString( const xub_Unicode* p )
+{
+ ::rtl::OUString aVal( p );
+ SbxValues aRes;
+ aRes.eType = SbxSTRING;
+ aRes.pOUString = &aVal;
+ Put( aRes );
+ return sal_Bool( !IsError() );
+}
+
+sal_Bool SbxValue::PutBool( sal_Bool b )
+{
+ SbxValues aRes;
+ aRes.eType = SbxBOOL;
+ aRes.nUShort = sal::static_int_cast< sal_uInt16 >(b ? SbxTRUE : SbxFALSE);
+ Put( aRes );
+ return sal_Bool( !IsError() );
+}
+
+sal_Bool SbxValue::PutEmpty()
+{
+ sal_Bool bRet = SetType( SbxEMPTY );
+ SetModified( sal_True );
+ return bRet;
+}
+
+sal_Bool SbxValue::PutNull()
+{
+ sal_Bool bRet = SetType( SbxNULL );
+ if( bRet )
+ SetModified( sal_True );
+ return bRet;
+}
+
+
+// Special decimal methods
+sal_Bool SbxValue::PutDecimal( com::sun::star::bridge::oleautomation::Decimal& rAutomationDec )
+{
+ SbxValue::Clear();
+ aData.pDecimal = new SbxDecimal( rAutomationDec );
+ aData.pDecimal->addRef();
+ aData.eType = SbxDECIMAL;
+ return sal_True;
+}
+
+sal_Bool SbxValue::fillAutomationDecimal
+ ( com::sun::star::bridge::oleautomation::Decimal& rAutomationDec )
+{
+ SbxDecimal* pDecimal = GetDecimal();
+ if( pDecimal != NULL )
+ {
+ pDecimal->fillAutomationDecimal( rAutomationDec );
+ return sal_True;
+ }
+ return sal_False;
+}
+
+
+sal_Bool SbxValue::PutpChar( const xub_Unicode* p )
+{
+ ::rtl::OUString aVal( p );
+ SbxValues aRes;
+ aRes.eType = SbxLPSTR;
+ aRes.pOUString = &aVal;
+ Put( aRes );
+ return sal_Bool( !IsError() );
+}
+
+sal_Bool SbxValue::PutString( const ::rtl::OUString& r )
+{
+ SbxValues aRes;
+ aRes.eType = SbxSTRING;
+ aRes.pOUString = (::rtl::OUString*) &r;
+ Put( aRes );
+ return sal_Bool( !IsError() );
+}
+
+
+#define PUT( p, e, t, m ) \
+sal_Bool SbxValue::p( t n ) \
+{ SbxValues aRes(e); aRes.m = n; Put( aRes ); return sal_Bool( !IsError() ); }
+
+PUT( PutByte, SbxBYTE, sal_uInt8, nByte )
+PUT( PutChar, SbxCHAR, sal_Unicode, nChar )
+PUT( PutCurrency, SbxCURRENCY, const sal_Int64&, nInt64 )
+PUT( PutDate, SbxDATE, double, nDouble )
+PUT( PutData, SbxDATAOBJECT, void*, pData )
+PUT( PutDouble, SbxDOUBLE, double, nDouble )
+PUT( PutErr, SbxERROR, sal_uInt16, nUShort )
+PUT( PutInt, SbxINT, int, nInt )
+PUT( PutInteger, SbxINTEGER, sal_Int16, nInteger )
+PUT( PutLong, SbxLONG, sal_Int32, nLong )
+PUT( PutObject, SbxOBJECT, SbxBase*, pObj )
+PUT( PutSingle, SbxSINGLE, float, nSingle )
+PUT( PutULong, SbxULONG, sal_uInt32, nULong )
+PUT( PutUShort, SbxUSHORT, sal_uInt16, nUShort )
+PUT( PutInt64, SbxSALINT64, sal_Int64, nInt64 )
+PUT( PutUInt64, SbxSALUINT64, sal_uInt64, uInt64 )
+PUT( PutDecimal, SbxDECIMAL, SbxDecimal*, pDecimal )
+
+
+////////////////////////// Setting of the data type ///////////////////////////
+
+sal_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
+sal_Bool SbxValue::IsNumeric() const
+{
+ return ImpIsNumeric( /*bOnlyIntntl*/sal_False );
+}
+
+sal_Bool SbxValue::IsNumericRTL() const
+{
+ return ImpIsNumeric( /*bOnlyIntntl*/sal_True );
+}
+
+sal_Bool SbxValue::ImpIsNumeric( sal_Bool bOnlyIntntl ) const
+{
+
+ if( !CanRead() )
+ {
+ SetError( SbxERR_PROP_WRITEONLY ); return sal_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;
+ sal_uInt16 nLen = 0;
+ if( ImpScan( s, n, t2, &nLen, /*bAllowIntntl*/sal_False, bOnlyIntntl ) == SbxERR_OK )
+ return sal_Bool( nLen == s.getLength() );
+ }
+ return sal_False;
+ }
+ else
+ return sal_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;
+}
+
+sal_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 sal_True;
+ if( ( t & 0x0FFF ) == SbxVARIANT )
+ {
+ // Trial to set the data type to Variant
+ ResetFlag( SBX_FIXED );
+ if( IsFixed() )
+ {
+ SetError( SbxERR_CONVERSION ); return sal_False;
+ }
+ t = SbxEMPTY;
+ }
+ if( ( t & 0x0FFF ) != ( aData.eType & 0x0FFF ) )
+ {
+ if( !CanWrite() || IsFixed() )
+ {
+ SetError( SbxERR_CONVERSION ); return sal_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);
+ sal_uInt16 nSlotId = pThisVar
+ ? ( (sal_Int16) ( pThisVar->GetUserData() & 0xFFFF ) )
+ : 0;
+ DBG_ASSERT( nSlotId != 5345 || pThisVar->GetName() == UniString::CreateFromAscii( "Parent" ),
+ "SID_PARENTOBJECT heisst nicht 'Parent'" );
+ sal_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 sal_True;
+}
+
+sal_Bool SbxValue::Convert( SbxDataType eTo )
+{
+ eTo = SbxDataType( eTo & 0x0FFF );
+ if( ( aData.eType & 0x0FFF ) == eTo )
+ return sal_True;
+ if( !CanWrite() )
+ return sal_False;
+ if( eTo == SbxVARIANT )
+ {
+ // Trial to set the data type to Variant
+ ResetFlag( SBX_FIXED );
+ if( IsFixed() )
+ {
+ SetError( SbxERR_CONVERSION ); return sal_False;
+ }
+ else
+ return sal_True;
+ }
+ // Converting from zero doesn't work. Once zero, always zero!
+ if( aData.eType == SbxNULL )
+ {
+ SetError( SbxERR_CONVERSION ); return sal_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( sal_True );
+ }
+ Broadcast( SBX_HINT_CONVERTED );
+ return sal_True;
+ }
+ else
+ return sal_False;
+}
+////////////////////////////////// Calculating /////////////////////////////////
+
+sal_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 );
+ // falls all the way out
+ }
+ else if( ( eOp >= SbxIDIV && eOp <= SbxNOT ) || eOp == SbxMOD )
+ {
+ if( GetType() == eOpType )
+ {
+ if( GetType() == SbxSALUINT64 || GetType() == SbxSALINT64
+ || GetType() == SbxCURRENCY || GetType() == SbxULONG )
+ aL.eType = aR.eType = GetType();
+ else if ( bVBAInterop && eOpType == SbxBOOL )
+ aL.eType = aR.eType = SbxBOOL;
+ else
+ aL.eType = aR.eType = SbxLONG;
+ }
+ else
+ aL.eType = aR.eType = SbxLONG;
+
+ if( rOp.Get( aR ) ) // re-do Get after type assigns above
+ {
+ if( rOp.GetType() == SbxEMPTY )
+ {
+ if ( !bVBAInterop || ( bVBAInterop && ( eOp != SbxNOT ) ) )
+ goto Lbl_OpIsEmpty;
+ }
+ if( Get( aL ) ) switch( eOp )
+ {
+ case SbxIDIV:
+ if( aL.eType == SbxCURRENCY )
+ if( !aR.nInt64 ) SetError( SbxERR_ZERODIV );
+ else {
+ aL.nInt64 /= aR.nInt64;
+ aL.nInt64 *= CURRENCY_FACTOR;
+ }
+ else if( aL.eType == SbxSALUINT64 )
+ if( !aR.uInt64 ) SetError( SbxERR_ZERODIV );
+ else aL.uInt64 /= aR.uInt64;
+ else if( aL.eType == SbxSALINT64 )
+ if( !aR.nInt64 ) SetError( SbxERR_ZERODIV );
+ else aL.nInt64 /= aR.nInt64;
+ 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 == SbxSALINT64 )
+ if( !aR.nInt64 ) SetError( SbxERR_ZERODIV );
+ else aL.nInt64 %= aR.nInt64;
+ else if( aL.eType == SbxSALUINT64 )
+ if( !aR.uInt64 ) SetError( SbxERR_ZERODIV );
+ else aL.uInt64 %= aR.uInt64;
+ 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.nInt64 &= aR.nInt64;
+ else
+ aL.nLong &= aR.nLong;
+ break;
+ case SbxOR:
+ if( aL.eType != SbxLONG && aL.eType != SbxULONG )
+ aL.nInt64 |= aR.nInt64;
+ else
+ aL.nLong |= aR.nLong;
+ break;
+ case SbxXOR:
+ if( aL.eType != SbxLONG && aL.eType != SbxULONG )
+ aL.nInt64 ^= aR.nInt64;
+ else
+ aL.nLong ^= aR.nLong;
+ break;
+ case SbxEQV:
+ if( aL.eType != SbxLONG && aL.eType != SbxULONG )
+ aL.nInt64 = (aL.nInt64 & aR.nInt64) | (~aL.nInt64 & ~aR.nInt64);
+ else
+ aL.nLong = (aL.nLong & aR.nLong) | (~aL.nLong & ~aR.nLong);
+ break;
+ case SbxIMP:
+ if( aL.eType != SbxLONG && aL.eType != SbxULONG )
+ aL.nInt64 = ~aL.nInt64 | aR.nInt64;
+ else
+ aL.nLong = ~aL.nLong | aR.nLong;
+ break;
+ case SbxNOT:
+ if( aL.eType != SbxLONG && aL.eType != SbxULONG )
+ {
+ if ( aL.eType != SbxBOOL )
+ aL.nInt64 = ~aL.nInt64;
+ 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 ) )
+ {
+ if( rOp.GetType() == SbxEMPTY )
+ goto Lbl_OpIsEmpty;
+
+ if( Get( aL ) ) switch( eOp )
+ {
+ double dTest;
+ case SbxMUL:
+ // first overflow check: see if product will fit - test real value of product (hence 2 curr factors)
+ dTest = (double)aL.nInt64 * (double)aR.nInt64 / (double)CURRENCY_FACTOR_SQUARE;
+ if( dTest < SbxMINCURR || SbxMAXCURR < dTest)
+ {
+ aL.nInt64 = SAL_MAX_INT64;
+ if( dTest < SbxMINCURR ) aL.nInt64 = SAL_MIN_INT64;
+ SetError( SbxERR_OVERFLOW );
+ break;
+ }
+ // second overflow check: see if unscaled product overflows - if so use doubles
+ dTest = (double)aL.nInt64 * (double)aR.nInt64;
+ if( dTest < SAL_MIN_INT64 || SAL_MAX_INT64 < dTest)
+ {
+ aL.nInt64 = (sal_Int64)( dTest / (double)CURRENCY_FACTOR );
+ break;
+ }
+ // precise calc: multiply then scale back (move decimal pt)
+ aL.nInt64 *= aR.nInt64;
+ aL.nInt64 /= CURRENCY_FACTOR;
+ break;
+
+ case SbxDIV:
+ if( !aR.nInt64 )
+ {
+ SetError( SbxERR_ZERODIV );
+ break;
+ }
+ // first overflow check: see if quotient will fit - calc real value of quotient (curr factors cancel)
+ dTest = (double)aL.nInt64 / (double)aR.nInt64;
+ if( dTest < SbxMINCURR || SbxMAXCURR < dTest)
+ {
+ SetError( SbxERR_OVERFLOW );
+ break;
+ }
+ // second overflow check: see if scaled dividend overflows - if so use doubles
+ dTest = (double)aL.nInt64 * (double)CURRENCY_FACTOR;
+ if( dTest < SAL_MIN_INT64 || SAL_MAX_INT64 < dTest)
+ {
+ aL.nInt64 = (sal_Int64)(dTest / (double)aR.nInt64);
+ break;
+ }
+ // precise calc: scale (move decimal pt) then divide
+ aL.nInt64 *= CURRENCY_FACTOR;
+ aL.nInt64 /= aR.nInt64;
+ break;
+
+ case SbxPLUS:
+ dTest = ( (double)aL.nInt64 + (double)aR.nInt64 ) / (double)CURRENCY_FACTOR;
+ if( dTest < SbxMINCURR || SbxMAXCURR < dTest)
+ {
+ SetError( SbxERR_OVERFLOW );
+ break;
+ }
+ aL.nInt64 += aR.nInt64;
+ break;
+
+ case SbxMINUS:
+ dTest = ( (double)aL.nInt64 - (double)aR.nInt64 ) / (double)CURRENCY_FACTOR;
+ if( dTest < SbxMINCURR || SbxMAXCURR < dTest)
+ {
+ SetError( SbxERR_OVERFLOW );
+ break;
+ }
+ aL.nInt64 -= aR.nInt64;
+ break;
+ case SbxNEG:
+ aL.nInt64 = -aL.nInt64;
+ break;
+ default:
+ SetError( SbxERR_NOTIMP );
+ }
+ }
+ }
+ else
+Lbl_OpIsDouble:
+ { // other types and operators including Date, Double and Single
+ 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;
+ // #45465 Date needs with "+" a special handling: forces date type
+ if( GetType() == SbxDATE || rOp.GetType() == SbxDATE )
+ aL.eType = SbxDATE;
+ case SbxMINUS:
+ aL.nDouble -= aR.nDouble; break;
+ case SbxNEG:
+ aL.nDouble = -aL.nDouble; break;
+ default:
+ SetError( SbxERR_NOTIMP );
+ }
+
+ }
+ }
+
+ }
+ if( !IsError() )
+ Put( aL );
+ if( bDecimal )
+ {
+ releaseDecimalPtr( aL.pDecimal );
+ releaseDecimalPtr( aR.pDecimal );
+ }
+ }
+Lbl_OpIsEmpty:
+
+ sal_Bool bRes = sal_Bool( !IsError() );
+ if( bRes && eOld != SbxERR_OK )
+ SetError( eOld );
+ return bRes;
+}
+
+// The comparison routine deliver TRUE or FALSE.
+
+sal_Bool SbxValue::Compare( SbxOperator eOp, const SbxValue& rOp ) const
+{
+ bool bVBAInterop = SbiRuntime::isVBAEnabled();
+
+ sal_Bool bRes = sal_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 = sal_True;
+ }
+ else if( GetType() == SbxEMPTY && rOp.GetType() == SbxEMPTY )
+ bRes = !bVBAInterop ? sal_True : ( eOp == SbxEQ ? sal_True : sal_False );
+ // Special rule 1: If an operand is zero, the result is FALSE
+ else if( GetType() == SbxNULL || rOp.GetType() == SbxNULL )
+ bRes = sal_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 = sal_Bool( eOp == SbxLT || eOp == SbxLE || eOp == SbxNE );
+ else if( !IsFixed() && !rOp.IsFixed()
+ && ( GetType() == SbxSTRING && rOp.GetType() != SbxSTRING && rOp.IsNumeric() )
+&& !bVBAInterop
+ )
+ bRes = sal_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 = sal_Bool( *aL.pOUString == *aR.pOUString ); break;
+ case SbxNE:
+ bRes = sal_Bool( *aL.pOUString != *aR.pOUString ); break;
+ case SbxLT:
+ bRes = sal_Bool( *aL.pOUString < *aR.pOUString ); break;
+ case SbxGT:
+ bRes = sal_Bool( *aL.pOUString > *aR.pOUString ); break;
+ case SbxLE:
+ bRes = sal_Bool( *aL.pOUString <= *aR.pOUString ); break;
+ case SbxGE:
+ bRes = sal_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 = sal_Bool( aL.nSingle == aR.nSingle ); break;
+ case SbxNE:
+ bRes = sal_Bool( aL.nSingle != aR.nSingle ); break;
+ case SbxLT:
+ bRes = sal_Bool( aL.nSingle < aR.nSingle ); break;
+ case SbxGT:
+ bRes = sal_Bool( aL.nSingle > aR.nSingle ); break;
+ case SbxLE:
+ bRes = sal_Bool( aL.nSingle <= aR.nSingle ); break;
+ case SbxGE:
+ bRes = sal_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 = sal_Bool( eRes == SbxDecimal::EQ ); break;
+ case SbxNE:
+ bRes = sal_Bool( eRes != SbxDecimal::EQ ); break;
+ case SbxLT:
+ bRes = sal_Bool( eRes == SbxDecimal::LT ); break;
+ case SbxGT:
+ bRes = sal_Bool( eRes == SbxDecimal::GT ); break;
+ case SbxLE:
+ bRes = sal_Bool( eRes != SbxDecimal::GT ); break;
+ case SbxGE:
+ bRes = sal_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;
+ bool bGetL = Get( aL );
+ bool bGetR = rOp.Get( aR );
+ if( bGetL && bGetR )
+ switch( eOp )
+ {
+ case SbxEQ:
+ bRes = sal_Bool( aL.nDouble == aR.nDouble ); break;
+ case SbxNE:
+ bRes = sal_Bool( aL.nDouble != aR.nDouble ); break;
+ case SbxLT:
+ bRes = sal_Bool( aL.nDouble < aR.nDouble ); break;
+ case SbxGT:
+ bRes = sal_Bool( aL.nDouble > aR.nDouble ); break;
+ case SbxLE:
+ bRes = sal_Bool( aL.nDouble <= aR.nDouble ); break;
+ case SbxGE:
+ bRes = sal_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 = sal_False;
+ }
+ }
+ }
+ }
+ if( eOld != SbxERR_OK )
+ SetError( eOld );
+ return bRes;
+}
+
+///////////////////////////// Reading/Writing ////////////////////////////
+
+sal_Bool SbxValue::LoadData( SvStream& r, sal_uInt16 )
+{
+ // #TODO see if these types are really dumped to any stream
+ // more than likely this is functionality used in the binfilter alone
+ SbxValue::Clear();
+ sal_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 sal_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 sal_False;
+ }
+ break;
+ }
+ case SbxSALUINT64:
+ case SbxSALINT64:
+ // Rather ugly use of the union here because we only
+ // have a SvStream& SvStream::operator>>(sal_uInt64&) available to us
+ // There is no SvStream::operator>>(sal_Int64&) due to conflict with
+ // SvStream::operator>>(long&) ( at least on 64 bit linux )
+ r >> aData.uInt64;
+ break;
+ case SbxCURRENCY:
+ {
+ sal_uInt32 tmpHi = 0;
+ sal_uInt32 tmpLo = 0;
+ r >> tmpHi >> tmpLo;
+ aData.nInt64 = ((sal_Int64)tmpHi << 32);
+ aData.nInt64 |= (sal_Int64)tmpLo;
+ 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:
+ {
+ sal_uInt8 nMode;
+ r >> nMode;
+ switch( nMode )
+ {
+ case 0:
+ aData.pObj = NULL;
+ break;
+ case 1:
+ aData.pObj = SbxBase::Load( r );
+ return sal_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:
+ {
+ sal_uInt8 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:
+ {
+ sal_uInt8 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 sal_False;
+ }
+ return sal_True;
+}
+
+sal_Bool SbxValue::StoreData( SvStream& r ) const
+{
+ sal_uInt16 nType = sal::static_int_cast< sal_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 SbxSALUINT64:
+ case SbxSALINT64:
+ // see comment in SbxValue::StoreData
+ r << aData.uInt64;
+ break;
+ case SbxCURRENCY:
+ {
+ sal_Int32 tmpHi = ( (aData.nInt64 >> 32) & 0xFFFFFFFF );
+ sal_Int32 tmpLo = ( sal_Int32 )aData.nInt64;
+ r << tmpHi << tmpLo;
+ 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 << (sal_uInt8) 1;
+ return aData.pObj->Store( r );
+ }
+ else
+ r << (sal_uInt8) 2;
+ }
+ else
+ r << (sal_uInt8) 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:
+ {
+ sal_uInt8 n = SAL_TYPES_SIZEOFINT;
+ r << n << (sal_Int32)aData.nInt;
+ break;
+ }
+ case SbxUINT:
+ {
+ sal_uInt8 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 sal_False;
+ }
+ return sal_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..9a99f06b151c
--- /dev/null
+++ b/basic/source/sbx/sbxvar.cxx
@@ -0,0 +1,666 @@
+/* -*- 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 "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 sal_uInt32 nVarCreator; // in SBXBASE.CXX, fuer LoadData()
+#ifdef DBG_UTIL
+static sal_uIntPtr nVar = 0;
+#endif
+
+///////////////////////////// SbxVariableImpl ////////////////////////////
+
+class SbxVariableImpl
+{
+ friend class SbxVariable;
+ String m_aDeclareClassName;
+ Reference< XInterface > m_xComListener;
+ StarBASIC* m_pComListenerParentBasic;
+
+ SbxVariableImpl( void )
+ : m_pComListenerParentBasic( NULL )
+ {}
+ SbxVariableImpl( const SbxVariableImpl& r )
+ : m_aDeclareClassName( r.m_aDeclareClassName )
+ , m_xComListener( r.m_xComListener )
+ , m_pComListenerParentBasic( r.m_pComListenerParentBasic )
+ {
+ }
+};
+
+
+///////////////////////////// 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 );
+#endif
+}
+
+void registerComListenerVariableForBasic( SbxVariable* pVar, StarBASIC* pBasic );
+
+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 );
+ if( mpSbxVariableImpl->m_xComListener.is() )
+ registerComListenerVariableForBasic( this, mpSbxVariableImpl->m_pComListenerParentBasic );
+ }
+ 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 );
+#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 );
+#endif
+}
+
+void removeDimAsNewRecoverItem( SbxVariable* pVar );
+
+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 );
+#endif
+ if( IsSet( SBX_DIM_AS_NEW ))
+ removeDimAsNewRecoverItem( this );
+ 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( sal_uIntPtr 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;
+ sal_uInt16 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( sal_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( sal_uInt16 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< sal_uInt16 >( 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< sal_uInt16 >( 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.
+
+sal_uInt16 SbxVariable::MakeHashCode( const XubString& rName )
+{
+ sal_uInt16 n = 0;
+ sal_uInt16 nLen = rName.Len();
+ if( nLen > 6 )
+ nLen = 6;
+ const xub_Unicode* p = rName.GetBuffer();
+ while( nLen-- )
+ {
+ sal_uInt8 c = (sal_uInt8)*p;
+ p++;
+ // If we have a commen sigen break!!
+ if( c >= 0x80 )
+ return 0;
+ n = sal::static_int_cast< sal_uInt16 >( ( 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 );
+ if( mpSbxVariableImpl->m_xComListener.is() )
+ registerComListenerVariableForBasic( this, mpSbxVariableImpl->m_pComListenerParentBasic );
+ }
+ 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( sal_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
+ sal_Bool bFound = sal_False;
+ SbxArray *pChilds = p->GetObjects();
+ if ( pChilds )
+ {
+ for ( sal_uInt16 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,
+ StarBASIC* pParentBasic )
+{
+ SbxVariableImpl* pImpl = getImpl();
+ pImpl->m_xComListener = xComListener;
+ pImpl->m_pComListenerParentBasic = pParentBasic;
+ registerComListenerVariableForBasic( this, pParentBasic );
+}
+
+void SbxVariable::ClearComListener( void )
+{
+ SbxVariableImpl* pImpl = getImpl();
+ pImpl->m_xComListener.clear();
+}
+
+
+////////////////////////////// Loading/Saving /////////////////////////////
+
+sal_Bool SbxVariable::LoadData( SvStream& rStrm, sal_uInt16 nVer )
+{
+ sal_uInt16 nType;
+ sal_uInt8 cMark;
+ rStrm >> cMark;
+ if( cMark == 0xFF )
+ {
+ if( !SbxValue::LoadData( rStrm, nVer ) )
+ return sal_False;
+ rStrm.ReadByteString( maName, RTL_TEXTENCODING_ASCII_US );
+ sal_uInt32 nTemp;
+ rStrm >> nTemp;
+ nUserData = nTemp;
+ }
+ else
+ {
+ rStrm.SeekRel( -1L );
+ rStrm >> nType;
+ rStrm.ReadByteString( maName, RTL_TEXTENCODING_ASCII_US );
+ sal_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 sal_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 sal_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 sal_False;
+ }
+ // putt value
+ if( nType != SbxNULL && nType != SbxEMPTY && !Put( aTmp ) )
+ return sal_False;
+ }
+ rStrm >> cMark;
+ // cMark is also a version number!
+ // 1: initial version
+ // 2: with nUserData
+ if( cMark )
+ {
+ if( cMark > 2 )
+ return sal_False;
+ pInfo = new SbxInfo;
+ pInfo->LoadData( rStrm, (sal_uInt16) cMark );
+ }
+ // Load private data only, if it is a SbxVariable
+ if( GetClass() == SbxCLASS_VARIABLE && !LoadPrivateData( rStrm, nVer ) )
+ return sal_False;
+ ((SbxVariable*) this)->Broadcast( SBX_HINT_DATACHANGED );
+ nHash = MakeHashCode( maName );
+ SetModified( sal_True );
+ return sal_True;
+}
+
+sal_Bool SbxVariable::StoreData( SvStream& rStrm ) const
+{
+ rStrm << (sal_uInt8) 0xFF; // Marker
+ sal_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;
+ sal_uInt16 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 sal_False;
+ rStrm.WriteByteString( maName, RTL_TEXTENCODING_ASCII_US );
+ rStrm << (sal_uInt32)nUserData;
+ if( pInfo.Is() )
+ {
+ rStrm << (sal_uInt8) 2; // Version 2: with UserData!
+ pInfo->StoreData( rStrm );
+ }
+ else
+ rStrm << (sal_uInt8) 0;
+ // Save private data only, if it is a SbxVariable
+ if( GetClass() == SbxCLASS_VARIABLE )
+ return StorePrivateData( rStrm );
+ else
+ return sal_True;
+}
+
+////////////////////////////// SbxInfo ///////////////////////////////////
+
+SbxInfo::SbxInfo() : aHelpFile(), nHelpId( 0 ), aParams()
+{}
+
+SbxInfo::SbxInfo( const String& r, sal_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( sal_uIntPtr 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, sal_Bool bFill )
+{
+ ByteString aBNameStr( (const UniString&)GetName( SbxNAME_SHORT_TYPES ), RTL_TEXTENCODING_ASCII_US );
+ rStrm << "Variable( "
+ << ByteString::CreateFromInt64( (sal_uIntPtr) 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: */