xref: /trunk/main/basic/source/sbx/sbxvalue.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_basic.hxx"
30 
31 #define _TLBIGINT_INT64
32 #include <tools/bigint.hxx>
33 #include <tools/stream.hxx>
34 
35 #include <basic/sbx.hxx>
36 #include "sbxconv.hxx"
37 #include <math.h>
38 #include "runtime.hxx"
39 // AB 29.10.99 Unicode
40 #ifndef _USE_NO_NAMESPACE
41 using namespace rtl;
42 #endif
43 
44 
45 TYPEINIT1(SbxValue,SbxBase)
46 
47 /////////////////////////// SbxINT64 /////////////////////////////////////
48 SbxINT64 &SbxINT64::operator -= ( const SbxINT64 &r )
49 {
50 	BigInt b( *this );
51 	b -= BigInt( r );
52 	b.INT64( this );
53 	return *this;
54 }
55 SbxINT64 &SbxINT64::operator += ( const SbxINT64 &r )
56 {
57 	BigInt b( *this );
58 	b += BigInt( r );
59 	b.INT64( this );
60 	return *this;
61 }
62 SbxINT64 &SbxINT64::operator *= ( const SbxINT64 &r )
63 {
64 	BigInt b( *this );
65 	b *= BigInt( r );
66 	b.INT64( this );
67 	return *this;
68 }
69 SbxINT64 &SbxINT64::operator %= ( const SbxINT64 &r )
70 {
71 	BigInt b( *this );
72 	b %= BigInt( r );
73 	b.INT64( this );
74 	return *this;
75 }
76 SbxINT64 &SbxINT64::operator /= ( const SbxINT64 &r )
77 {
78 	BigInt b( *this );
79 	b /= BigInt( r );
80 	b.INT64( this );
81 	return *this;
82 }
83 SbxINT64 &SbxINT64::operator &= ( const SbxINT64 &r )
84 {
85 	nHigh &= r.nHigh;
86 	nLow  &= r.nLow;
87 	return *this;
88 }
89 SbxINT64 &SbxINT64::operator |= ( const SbxINT64 &r )
90 {
91 	nHigh |= r.nHigh;
92 	nLow  |= r.nLow;
93 	return *this;
94 }
95 SbxINT64 &SbxINT64::operator ^= ( const SbxINT64 &r )
96 {
97 	nHigh ^= r.nHigh;
98 	nLow  ^= r.nLow;
99 	return *this;
100 }
101 
102 SbxINT64 operator - ( const SbxINT64 &l, const SbxINT64 &r )
103 {
104 	SbxINT64 a(l);
105 	a -= r;
106 	return a;
107 }
108 SbxINT64 operator + ( const SbxINT64 &l, const SbxINT64 &r )
109 {
110 	SbxINT64 a(l);
111 	a += r;
112 	return a;
113 }
114 SbxINT64 operator / ( const SbxINT64 &l, const SbxINT64 &r )
115 {
116 	SbxINT64 a(l);
117 	a /= r;
118 	return a;
119 }
120 SbxINT64 operator % ( const SbxINT64 &l, const SbxINT64 &r )
121 {
122 	SbxINT64 a(l);
123 	a %= r;
124 	return a;
125 }
126 SbxINT64 operator * ( const SbxINT64 &l, const SbxINT64 &r )
127 {
128 	SbxINT64 a(l);
129 	a *= r;
130 	return a;
131 }
132 SbxINT64 operator & ( const SbxINT64 &l, const SbxINT64 &r )
133 {
134 	SbxINT64 a;
135 	a.nHigh = r.nHigh & l.nHigh;
136 	a.nLow  = r.nLow  & l.nLow;
137 	return a;
138 }
139 SbxINT64 operator | ( const SbxINT64 &l, const SbxINT64 &r )
140 {
141 	SbxINT64 a;
142 	a.nHigh = r.nHigh | l.nHigh;
143 	a.nLow  = r.nLow  | l.nLow;
144 	return a;
145 }
146 SbxINT64 operator ^ ( const SbxINT64 &r, const SbxINT64 &l )
147 {
148 	SbxINT64 a;
149 	a.nHigh = r.nHigh ^ l.nHigh;
150 	a.nLow  = r.nLow  ^ l.nLow;
151 	return a;
152 }
153 
154 SbxINT64 operator - ( const SbxINT64 &r )
155 {
156 	SbxINT64 a( r );
157 	a.CHS();
158 	return a;
159 }
160 SbxINT64 operator ~ ( const SbxINT64 &r )
161 {
162 	SbxINT64 a;
163 	a.nHigh = ~r.nHigh;
164 	a.nLow  = ~r.nLow;
165 	return a;
166 }
167 
168 SbxUINT64 &SbxUINT64::operator %= ( const SbxUINT64 &r )
169 {
170 	BigInt b( *this );
171 	b %= BigInt( r );
172 	b.UINT64( this );
173 	return *this;
174 }
175 SbxUINT64 &SbxUINT64::operator /= ( const SbxUINT64 &r )
176 {
177 	BigInt b( *this );
178 	b /= BigInt( r );
179 	b.UINT64( this );
180 	return *this;
181 }
182 /////////////////////////// Fehlerbehandlung /////////////////////////////
183 
184 #ifdef _USED
185 // NOCH NACHZUBAUEN!
186 
187 // Das Default-Handling setzt nur den Fehlercode.
188 
189 #ifndef WNT
190 #if defined ( UNX )
191 int matherr( struct exception* p )
192 #else
193 int matherr( struct _exception* p )
194 #endif
195 {
196 	switch( p->type )
197 	{
198 #if defined ( UNX )
199 		case OVERFLOW: SbxBase::SetError( SbxERR_OVERFLOW ); break;
200 #else
201 		case _OVERFLOW: SbxBase::SetError( SbxERR_OVERFLOW ); break;
202 #endif
203 		default:		SbxBase::SetError( SbxERR_NOTIMP ); break;
204 	}
205 	return sal_True;
206 }
207 #endif
208 
209 #endif // _USED
210 
211 
212 ///////////////////////////// Konstruktoren //////////////////////////////
213 
214 SbxValue::SbxValue() : SbxBase()
215 {
216 	aData.eType = SbxEMPTY;
217 }
218 
219 SbxValue::SbxValue( SbxDataType t, void* p ) : SbxBase()
220 {
221 	int n = t & 0x0FFF;
222 	if( p )
223 		n |= SbxBYREF;
224 	if( n == SbxVARIANT )
225 		n = SbxEMPTY;
226 	else
227 		SetFlag( SBX_FIXED );
228 	if( p )
229 	switch( t & 0x0FFF )
230 	{
231 		case SbxINTEGER:	n |= SbxBYREF; aData.pInteger = (sal_Int16*) p; break;
232 		case SbxULONG64:	n |= SbxBYREF; aData.pULong64 = (SbxUINT64*) p; break;
233 		case SbxLONG64:
234 		case SbxCURRENCY:	n |= SbxBYREF; aData.pLong64 = (SbxINT64*) p; break;
235 		case SbxLONG:		n |= SbxBYREF; aData.pLong = (sal_Int32*) p; break;
236 		case SbxSINGLE:		n |= SbxBYREF; aData.pSingle = (float*) p; break;
237 		case SbxDATE:
238 		case SbxDOUBLE:		n |= SbxBYREF; aData.pDouble = (double*) p; break;
239         case SbxSTRING:		n |= SbxBYREF; aData.pOUString = (::rtl::OUString*) p; break;
240 		case SbxERROR:
241 		case SbxUSHORT:
242 		case SbxBOOL:		n |= SbxBYREF; aData.pUShort = (sal_uInt16*) p; break;
243 		case SbxULONG:		n |= SbxBYREF; aData.pULong = (sal_uInt32*) p; break;
244 		case SbxCHAR:		n |= SbxBYREF; aData.pChar = (xub_Unicode*) p; break;
245 		case SbxBYTE:		n |= SbxBYREF; aData.pByte = (sal_uInt8*) p; break;
246 		case SbxINT:		n |= SbxBYREF; aData.pInt = (int*) p; break;
247 		case SbxOBJECT:
248 			aData.pObj = (SbxBase*) p;
249 			if( p )
250 				aData.pObj->AddRef();
251 			break;
252 		case SbxDECIMAL:
253 			aData.pDecimal = (SbxDecimal*) p;
254 			if( p )
255 				aData.pDecimal->addRef();
256 			break;
257 		default:
258 			DBG_ASSERT( !this, "Angabe eines Pointers unzulaessig" );
259 			n = SbxNULL;
260 	}
261 	else
262 		memset( &aData, 0, sizeof( SbxValues ) );
263 	aData.eType = SbxDataType( n );
264 }
265 
266 SbxValue::SbxValue( const SbxValue& r )
267     : SvRefBase( r ), SbxBase( r )
268 {
269 	if( !r.CanRead() )
270 	{
271 		SetError( SbxERR_PROP_WRITEONLY );
272 		if( !IsFixed() )
273 			aData.eType = SbxNULL;
274 	}
275 	else
276 	{
277 		((SbxValue*) &r)->Broadcast( SBX_HINT_DATAWANTED );
278 		aData = r.aData;
279 		// Pointer kopieren, Referenzen inkrementieren
280 		switch( aData.eType )
281 		{
282 			case SbxSTRING:
283 				if( aData.pOUString )
284 					aData.pOUString = new ::rtl::OUString( *aData.pOUString );
285 				break;
286 			case SbxOBJECT:
287 				if( aData.pObj )
288 					aData.pObj->AddRef();
289 				break;
290 			case SbxDECIMAL:
291 				if( aData.pDecimal )
292 					aData.pDecimal->addRef();
293 				break;
294 			default: break;
295 		}
296 	}
297 }
298 
299 SbxValue& SbxValue::operator=( const SbxValue& r )
300 {
301 	if( &r != this )
302 	{
303 		if( !CanWrite() )
304 			SetError( SbxERR_PROP_READONLY );
305 		else
306 		{
307 			// string -> byte array
308 			if( IsFixed() && (aData.eType == SbxOBJECT)
309 				&& aData.pObj && ( aData.pObj->GetType() == (SbxARRAY | SbxBYTE) )
310 				&& (r.aData.eType == SbxSTRING) )
311 			{
312 				::rtl::OUString aStr = r.GetString();
313 				SbxArray* pArr = StringToByteArray(aStr);
314 				PutObject(pArr);
315 				return *this;
316 			}
317 			// byte array -> string
318 			if( r.IsFixed() && (r.aData.eType == SbxOBJECT)
319 				&& r.aData.pObj && ( r.aData.pObj->GetType() == (SbxARRAY | SbxBYTE) )
320 				&& (aData.eType == SbxSTRING) )
321 			{
322 				SbxBase* pObj = r.GetObject();
323 				SbxArray* pArr = PTR_CAST(SbxArray, pObj);
324 				if( pArr )
325 				{
326 					::rtl::OUString aStr = ByteArrayToString( pArr );
327 					PutString(aStr);
328 					return *this;
329 				}
330 			}
331 			// Den Inhalt der Variablen auslesen
332 			SbxValues aNew;
333 			if( IsFixed() )
334 				// fest: dann muss der Typ stimmen
335 				aNew.eType = aData.eType;
336 			else if( r.IsFixed() )
337 				// Quelle fest: Typ uebernehmen
338 				aNew.eType = SbxDataType( r.aData.eType & 0x0FFF );
339 			else
340 				// beides Variant: dann isses egal
341 				aNew.eType = SbxVARIANT;
342 			if( r.Get( aNew ) )
343 				Put( aNew );
344 		}
345 	}
346 	return *this;
347 }
348 
349 SbxValue::~SbxValue()
350 {
351 #ifndef C50
352 	Broadcast( SBX_HINT_DYING );
353 	SetFlag( SBX_WRITE );
354 	SbxValue::Clear();
355 #else
356 	// Provisorischer Fix fuer Solaris 5.0 Compiler Bug
357 	// bei Nutzung virtueller Vererbung. Virtuelle Calls
358 	// im Destruktor vermeiden. Statt Clear() zu rufen
359 	// moegliche Objekt-Referenzen direkt freigeben.
360 	if( aData.eType == SbxOBJECT )
361 	{
362 		if( aData.pObj && aData.pObj != this )
363 		{
364 			HACK(nicht bei Parent-Prop - sonst CyclicRef)
365 			SbxVariable *pThisVar = PTR_CAST(SbxVariable, this);
366 			sal_Bool bParentProp = pThisVar && 5345 ==
367 			( (sal_Int16) ( pThisVar->GetUserData() & 0xFFFF ) );
368 			if ( !bParentProp )
369 				aData.pObj->ReleaseRef();
370 		}
371 	}
372 	else if( aData.eType == SbxDECIMAL )
373 	{
374 		releaseDecimalPtr( aData.pDecimal );
375 	}
376 #endif
377 }
378 
379 void SbxValue::Clear()
380 {
381 	switch( aData.eType )
382 	{
383 		case SbxNULL:
384 		case SbxEMPTY:
385 		case SbxVOID:
386 			break;
387 		case SbxSTRING:
388 			delete aData.pOUString; aData.pOUString = NULL;
389 			break;
390 		case SbxOBJECT:
391 			if( aData.pObj )
392 			{
393 				if( aData.pObj != this )
394 				{
395 					HACK(nicht bei Parent-Prop - sonst CyclicRef)
396 					SbxVariable *pThisVar = PTR_CAST(SbxVariable, this);
397 					sal_Bool bParentProp = pThisVar && 5345 ==
398 					( (sal_Int16) ( pThisVar->GetUserData() & 0xFFFF ) );
399 					if ( !bParentProp )
400 						aData.pObj->ReleaseRef();
401 				}
402 				aData.pObj = NULL;
403 			}
404 			break;
405 		case SbxDECIMAL:
406 			if( aData.eType == SbxDECIMAL )
407 				releaseDecimalPtr( aData.pDecimal );
408 			break;
409 		case SbxDATAOBJECT:
410 			aData.pData = NULL; break;
411 		default:
412 		{
413 			SbxValues aEmpty;
414 			memset( &aEmpty, 0, sizeof( SbxValues ) );
415 			aEmpty.eType = GetType();
416 			Put( aEmpty );
417 		}
418 	}
419 }
420 
421 // Dummy
422 
423 void SbxValue::Broadcast( sal_uIntPtr )
424 {}
425 
426 //////////////////////////// Daten auslesen //////////////////////////////
427 
428 // Ermitteln der "richtigen" Variablen. Falls es ein Objekt ist, wird
429 // entweder das Objekt selbst oder dessen Default-Property angesprochen.
430 // Falls die Variable eine Variable oder ein Objekt enthaelt, wird
431 // dieses angesprochen.
432 
433 SbxValue* SbxValue::TheRealValue() const
434 {
435 	return TheRealValue( sal_True );
436 }
437 
438 // #55226 Zusaetzliche Info transportieren
439 bool handleToStringForCOMObjects( SbxObject* pObj, SbxValue* pVal );	// sbunoobj.cxx
440 
441 SbxValue* SbxValue::TheRealValue( sal_Bool bObjInObjError ) const
442 {
443 	SbxValue* p = (SbxValue*) this;
444 	for( ;; )
445 	{
446 		SbxDataType t = SbxDataType( p->aData.eType & 0x0FFF );
447 		if( t == SbxOBJECT )
448 		{
449 			// Der Block enthaelt ein Objekt oder eine Variable
450 			SbxObject* pObj = PTR_CAST(SbxObject,p->aData.pObj);
451 			if( pObj )
452 			{
453 				// Hat das Objekt eine Default-Property?
454 				SbxVariable* pDflt = pObj->GetDfltProperty();
455 
456 				// Falls dies ein Objekt ist und sich selbst enthaelt,
457 				// koennen wir nicht darauf zugreifen
458 				// #55226# Die alte Bedingung, um einen Fehler zu setzen,
459 				// ist nicht richtig, da z.B. eine ganz normale Variant-
460 				// Variable mit Objekt davon betroffen sein kann, wenn ein
461 				// anderer Wert zugewiesen werden soll. Daher mit Flag.
462 				if( bObjInObjError && !pDflt &&
463 					((SbxValue*) pObj)->aData.eType == SbxOBJECT &&
464 					((SbxValue*) pObj)->aData.pObj == pObj )
465 				{
466 					bool bSuccess = handleToStringForCOMObjects( pObj, p );
467 					if( !bSuccess )
468 					{
469 						SetError( SbxERR_BAD_PROP_VALUE );
470 						p = NULL;
471 					}
472 				}
473 				else if( pDflt )
474 					p = pDflt;
475 				/* ALT:
476 				else
477 					p = pDflt ? pDflt : (SbxVariable*) pObj;
478 				*/
479 				break;
480 			}
481 			// Haben wir ein Array?
482 			SbxArray* pArray = PTR_CAST(SbxArray,p->aData.pObj);
483 			if( pArray )
484 			{
485 				// Ggf. Parameter holen
486 				SbxArray* pPar = NULL;
487 				SbxVariable* pVar = PTR_CAST(SbxVariable,p);
488 				if( pVar )
489 					pPar = pVar->GetParameters();
490 				if( pPar )
491 				{
492 					// Haben wir ein dimensioniertes Array?
493 					SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,p->aData.pObj);
494 					if( pDimArray )
495 						p = pDimArray->Get( pPar );
496 					else
497 						p = pArray->Get( pPar->Get( 1 )->GetInteger() );
498 					break;
499 				}
500 			}
501 			// Sonst einen SbxValue annehmen
502 			SbxValue* pVal = PTR_CAST(SbxValue,p->aData.pObj);
503 			if( pVal )
504 				p = pVal;
505 			else
506 				break;
507 		}
508 		else
509 			break;
510 	}
511 	return p;
512 }
513 
514 sal_Bool SbxValue::Get( SbxValues& rRes ) const
515 {
516 	sal_Bool bRes = sal_False;
517 	SbxError eOld = GetError();
518 	if( eOld != SbxERR_OK )
519 		ResetError();
520 	if( !CanRead() )
521 	{
522 		SetError( SbxERR_PROP_WRITEONLY );
523 		rRes.pObj = NULL;
524 	}
525 	else
526 	{
527 		// Falls nach einem Objekt oder einem VARIANT gefragt wird, nicht
528 		// die wahren Werte suchen
529 		SbxValue* p = (SbxValue*) this;
530 		if( rRes.eType != SbxOBJECT && rRes.eType != SbxVARIANT )
531 			p = TheRealValue();
532 		if( p )
533 		{
534 			p->Broadcast( SBX_HINT_DATAWANTED );
535 			switch( rRes.eType )
536 			{
537 				case SbxEMPTY:
538 				case SbxVOID:
539 				case SbxNULL:	 break;
540 				case SbxVARIANT: rRes = p->aData; break;
541 				case SbxINTEGER: rRes.nInteger = ImpGetInteger( &p->aData ); break;
542 				case SbxLONG:	 rRes.nLong = ImpGetLong( &p->aData ); break;
543 				case SbxSALINT64:	rRes.nInt64 = ImpGetInt64( &p->aData ); break;
544 				case SbxSALUINT64:	rRes.uInt64 = ImpGetUInt64( &p->aData ); break;
545 				case SbxSINGLE:	 rRes.nSingle = ImpGetSingle( &p->aData ); break;
546 				case SbxDOUBLE:	 rRes.nDouble = ImpGetDouble( &p->aData ); break;
547 				case SbxCURRENCY:rRes.nLong64 = ImpGetCurrency( &p->aData ); break;
548 				case SbxDECIMAL: rRes.pDecimal = ImpGetDecimal( &p->aData ); break;
549 				case SbxDATE:	 rRes.nDouble = ImpGetDate( &p->aData ); break;
550 				case SbxBOOL:
551                     rRes.nUShort = sal::static_int_cast< sal_uInt16 >(
552                         ImpGetBool( &p->aData ) );
553                     break;
554 				case SbxCHAR:	 rRes.nChar = ImpGetChar( &p->aData ); break;
555 				case SbxBYTE:	 rRes.nByte = ImpGetByte( &p->aData ); break;
556 				case SbxUSHORT:	 rRes.nUShort = ImpGetUShort( &p->aData ); break;
557 				case SbxULONG:	 rRes.nULong = ImpGetULong( &p->aData ); break;
558 				case SbxLPSTR:
559 				case SbxSTRING:	 p->aPic = ImpGetString( &p->aData );
560 								 rRes.pOUString = &p->aPic; break;
561 				case SbxCoreSTRING:	p->aPic = ImpGetCoreString( &p->aData );
562 									rRes.pOUString = &p->aPic; break;
563 				case SbxINT:
564 #if SAL_TYPES_SIZEOFINT == 2
565 					rRes.nInt = (int) ImpGetInteger( &p->aData );
566 #else
567 					rRes.nInt = (int) ImpGetLong( &p->aData );
568 #endif
569 					break;
570 				case SbxUINT:
571 #if SAL_TYPES_SIZEOFINT == 2
572 					rRes.nUInt = (int) ImpGetUShort( &p->aData );
573 #else
574 					rRes.nUInt = (int) ImpGetULong( &p->aData );
575 #endif
576 					break;
577 				case SbxOBJECT:
578 					if( p->aData.eType == SbxOBJECT )
579 						rRes.pObj = p->aData.pObj;
580 					else
581 					{
582 						SetError( SbxERR_NO_OBJECT );
583 						rRes.pObj = NULL;
584 					}
585 					break;
586 				default:
587 					if( p->aData.eType == rRes.eType )
588 						rRes = p->aData;
589 					else
590 					{
591 						SetError( SbxERR_CONVERSION );
592 						rRes.pObj = NULL;
593 					}
594 			}
595 		}
596 		else
597 		{
598 			// Objekt enthielt sich selbst
599 			SbxDataType eTemp = rRes.eType;
600 			memset( &rRes, 0, sizeof( SbxValues ) );
601 			rRes.eType = eTemp;
602 		}
603 	}
604 	if( !IsError() )
605 	{
606 		bRes = sal_True;
607 		if( eOld != SbxERR_OK )
608 			SetError( eOld );
609 	}
610 	return bRes;
611 }
612 
613 sal_Bool SbxValue::GetNoBroadcast( SbxValues& rRes )
614 {
615 	sal_uInt16 nFlags_ = GetFlags();
616 	SetFlag( SBX_NO_BROADCAST );
617 	sal_Bool bRes = Get( rRes );
618 	SetFlags( nFlags_ );
619 	return bRes;
620 }
621 
622 const XubString& SbxValue::GetString() const
623 {
624 	SbxValues aRes;
625 	aRes.eType = SbxSTRING;
626 	if( Get( aRes ) )
627 		((SbxValue*) this)->aToolString = *aRes.pOUString;
628 	else
629 		((SbxValue*) this)->aToolString.Erase();
630 
631     return aToolString;
632 }
633 
634 const XubString& SbxValue::GetCoreString() const
635 {
636 	SbxValues aRes;
637 	aRes.eType = SbxCoreSTRING;
638 	if( Get( aRes ) )
639 		((SbxValue*) this)->aToolString = *aRes.pOUString;
640 	else
641 		((SbxValue*) this)->aToolString.Erase();
642 
643     return aToolString;
644 }
645 
646 ::rtl::OUString SbxValue::GetOUString() const
647 {
648     ::rtl::OUString aResult;
649     SbxValues aRes;
650     aRes.eType = SbxSTRING;
651     if( Get( aRes ) )
652         aResult = *aRes.pOUString;
653 
654     return aResult;
655 }
656 
657 sal_Bool SbxValue::HasObject() const
658 {
659 	ErrCode eErr = GetError();
660 	SbxValues aRes;
661 	aRes.eType = SbxOBJECT;
662 	Get( aRes );
663 	SetError( eErr );
664 	return 0 != aRes.pObj;
665 }
666 
667 sal_Bool SbxValue::GetBool() const
668 {
669 	SbxValues aRes;
670 	aRes.eType = SbxBOOL;
671 	Get( aRes );
672 	return sal_Bool( aRes.nUShort != 0 );
673 }
674 
675 #define GET( g, e, t, m ) \
676 t SbxValue::g() const { SbxValues aRes(e); Get( aRes ); return aRes.m; }
677 
678 GET( GetByte,     SbxBYTE,       sal_uInt8,             nByte )
679 GET( GetChar,     SbxCHAR,       xub_Unicode,           nChar )
680 GET( GetCurrency, SbxCURRENCY,   SbxINT64,         nLong64 )
681 GET( GetDate,     SbxDATE,       double,           nDouble )
682 GET( GetData,     SbxDATAOBJECT, void*,            pData )
683 GET( GetDouble,   SbxDOUBLE,     double,           nDouble )
684 GET( GetErr,      SbxERROR,      sal_uInt16,           nUShort )
685 GET( GetInt,      SbxINT,        int,              nInt )
686 GET( GetInteger,  SbxINTEGER,    sal_Int16,            nInteger )
687 GET( GetLong,     SbxLONG,       sal_Int32,            nLong )
688 GET( GetLong64,   SbxLONG64,     SbxINT64,         nLong64 )
689 GET( GetObject,   SbxOBJECT,     SbxBase*,         pObj )
690 GET( GetSingle,   SbxSINGLE,     float,            nSingle )
691 GET( GetULong,    SbxULONG,      sal_uInt32,           nULong )
692 GET( GetULong64,  SbxULONG64,    SbxUINT64,        nULong64 )
693 GET( GetUShort,   SbxUSHORT,     sal_uInt16,           nUShort )
694 GET( GetInt64,    SbxSALINT64,   sal_Int64,        nInt64 )
695 GET( GetUInt64,   SbxSALUINT64,  sal_uInt64,       uInt64 )
696 GET( GetDecimal,  SbxDECIMAL,    SbxDecimal*,      pDecimal )
697 
698 
699 //////////////////////////// Daten schreiben /////////////////////////////
700 
701 sal_Bool SbxValue::Put( const SbxValues& rVal )
702 {
703 	sal_Bool bRes = sal_False;
704 	SbxError eOld = GetError();
705 	if( eOld != SbxERR_OK )
706 		ResetError();
707 	if( !CanWrite() )
708 		SetError( SbxERR_PROP_READONLY );
709 	else if( rVal.eType & 0xF000 )
710 		SetError( SbxERR_NOTIMP );
711 	else
712 	{
713 		// Falls nach einem Objekt gefragt wird, nicht
714 		// die wahren Werte suchen
715 		SbxValue* p = this;
716 		if( rVal.eType != SbxOBJECT )
717 			p = TheRealValue( sal_False );	// #55226 Hier keinen Fehler erlauben
718 		if( p )
719 		{
720 			if( !p->CanWrite() )
721 				SetError( SbxERR_PROP_READONLY );
722 			else if( p->IsFixed() || p->SetType( (SbxDataType) ( rVal.eType & 0x0FFF ) ) )
723 			  switch( rVal.eType & 0x0FFF )
724 			{
725 				case SbxEMPTY:
726 				case SbxVOID:
727 				case SbxNULL:		break;
728 				case SbxINTEGER:	ImpPutInteger( &p->aData, rVal.nInteger ); break;
729 				case SbxLONG:		ImpPutLong( &p->aData, rVal.nLong ); break;
730 				case SbxSALINT64:	ImpPutInt64( &p->aData, rVal.nInt64 ); break;
731 				case SbxSALUINT64:	ImpPutUInt64( &p->aData, rVal.uInt64 ); break;
732 				case SbxSINGLE:		ImpPutSingle( &p->aData, rVal.nSingle ); break;
733 				case SbxDOUBLE:		ImpPutDouble( &p->aData, rVal.nDouble ); break;
734 				case SbxCURRENCY:	ImpPutCurrency( &p->aData, rVal.nLong64 ); break;
735 				case SbxDECIMAL:	ImpPutDecimal( &p->aData, rVal.pDecimal ); break;
736 				case SbxDATE:		ImpPutDate( &p->aData, rVal.nDouble ); break;
737 				case SbxBOOL:		ImpPutBool( &p->aData, rVal.nInteger ); break;
738 				case SbxCHAR:		ImpPutChar( &p->aData, rVal.nChar ); break;
739 				case SbxBYTE:		ImpPutByte( &p->aData, rVal.nByte ); break;
740 				case SbxUSHORT:		ImpPutUShort( &p->aData, rVal.nUShort ); break;
741 				case SbxULONG:		ImpPutULong( &p->aData, rVal.nULong ); break;
742 				case SbxLPSTR:
743 				case SbxSTRING:		ImpPutString( &p->aData, rVal.pOUString ); break;
744 				case SbxINT:
745 #if SAL_TYPES_SIZEOFINT == 2
746 					ImpPutInteger( &p->aData, (sal_Int16) rVal.nInt );
747 #else
748 					ImpPutLong( &p->aData, (sal_Int32) rVal.nInt );
749 #endif
750 					break;
751 				case SbxUINT:
752 #if SAL_TYPES_SIZEOFINT == 2
753 					ImpPutUShort( &p->aData, (sal_uInt16) rVal.nUInt );
754 #else
755 					ImpPutULong( &p->aData, (sal_uInt32) rVal.nUInt );
756 #endif
757 					break;
758 				case SbxOBJECT:
759 					if( !p->IsFixed() || p->aData.eType == SbxOBJECT )
760 					{
761 						// ist schon drin
762 						if( p->aData.eType == SbxOBJECT && p->aData.pObj == rVal.pObj )
763 							break;
764 
765 						// Nur den Werteteil loeschen!
766 						p->SbxValue::Clear();
767 
768 						// eingentliche Zuweisung
769 						p->aData.pObj = rVal.pObj;
770 
771 						// ggf. Ref-Count mitzaehlen
772 						if( p->aData.pObj && p->aData.pObj != p )
773 						{
774 							if ( p != this )
775                             {
776 								DBG_ERROR( "TheRealValue" );
777                             }
778 							HACK(nicht bei Parent-Prop - sonst CyclicRef)
779 							SbxVariable *pThisVar = PTR_CAST(SbxVariable, this);
780 							sal_Bool bParentProp = pThisVar && 5345 ==
781 									( (sal_Int16) ( pThisVar->GetUserData() & 0xFFFF ) );
782 							if ( !bParentProp )
783 								p->aData.pObj->AddRef();
784 						}
785 					}
786 					else
787 						SetError( SbxERR_CONVERSION );
788 					break;
789 				default:
790 					if( p->aData.eType == rVal.eType )
791 						p->aData = rVal;
792 					else
793 					{
794 						SetError( SbxERR_CONVERSION );
795 						if( !p->IsFixed() )
796 							p->aData.eType = SbxNULL;
797 					}
798 			}
799 			if( !IsError() )
800 			{
801 				p->SetModified( sal_True );
802 				p->Broadcast( SBX_HINT_DATACHANGED );
803 				if( eOld != SbxERR_OK )
804 					SetError( eOld );
805 				bRes = sal_True;
806 			}
807 		}
808 	}
809 	return bRes;
810 }
811 
812 // AB, 28.3.96:
813 // Methode, um bei speziellen Typen eine Vorbehandlung des Strings
814 // durchzufuehren. Insbesondere erforderlich fuer BASIC-IDE, damit
815 // die Ausgaben im Watch-Fenster mit PutStringExt zurueckgeschrieben
816 // werden koennen, wenn Floats mit ',' als Dezimaltrenner oder BOOLs
817 // explizit mit "TRUE" oder "FALSE" angegeben werden.
818 // Implementierung in ImpConvStringExt (SBXSCAN.CXX)
819 sal_Bool SbxValue::PutStringExt( const ::rtl::OUString& r )
820 {
821 	// Kopieren, bei Unicode gleich konvertieren
822 	::rtl::OUString aStr( r );
823 
824 	// Eigenen Typ bestimmen (nicht wie in Put() mit TheRealValue(),
825 	// Objekte werden sowieso nicht behandelt)
826 	SbxDataType eTargetType = SbxDataType( aData.eType & 0x0FFF );
827 
828 	// Source-Value basteln
829 	SbxValues aRes;
830 	aRes.eType = SbxSTRING;
831 
832 	// Nur, wenn wirklich was konvertiert wurde, Kopie nehmen,
833 	// sonst Original (Unicode bleibt erhalten)
834 	sal_Bool bRet;
835 	if( ImpConvStringExt( aStr, eTargetType ) )
836 		aRes.pOUString = (::rtl::OUString*)&aStr;
837 	else
838 		aRes.pOUString = (::rtl::OUString*)&r;
839 
840 	// #34939: Bei Strings. die eine Zahl enthalten und wenn this einen
841 	// Num-Typ hat, Fixed-Flag setzen, damit der Typ nicht veraendert wird
842 	sal_uInt16 nFlags_ = GetFlags();
843 	if( ( eTargetType >= SbxINTEGER && eTargetType <= SbxCURRENCY ) ||
844 		( eTargetType >= SbxCHAR && eTargetType <= SbxUINT ) ||
845 		eTargetType == SbxBOOL )
846 	{
847 		SbxValue aVal;
848 		aVal.Put( aRes );
849 		if( aVal.IsNumeric() )
850 			SetFlag( SBX_FIXED );
851 	}
852 
853 	Put( aRes );
854 	bRet = sal_Bool( !IsError() );
855 
856 	// Falls das mit dem FIXED einen Error gegeben hat, zuruecksetzen
857 	// (UI-Aktion sollte keinen Error ergeben, sondern nur scheitern)
858 	if( !bRet )
859 		ResetError();
860 
861 	SetFlags( nFlags_ );
862 	return bRet;
863 }
864 
865 sal_Bool SbxValue::PutString( const xub_Unicode* p )
866 {
867 	::rtl::OUString aVal( p );
868 	SbxValues aRes;
869 	aRes.eType = SbxSTRING;
870 	aRes.pOUString = &aVal;
871 	Put( aRes );
872 	return sal_Bool( !IsError() );
873 }
874 
875 sal_Bool SbxValue::PutBool( sal_Bool b )
876 {
877 	SbxValues aRes;
878 	aRes.eType = SbxBOOL;
879 	aRes.nUShort = sal::static_int_cast< sal_uInt16 >(b ? SbxTRUE : SbxFALSE);
880 	Put( aRes );
881 	return sal_Bool( !IsError() );
882 }
883 
884 sal_Bool SbxValue::PutEmpty()
885 {
886 	sal_Bool bRet = SetType( SbxEMPTY );
887 		SetModified( sal_True );
888 	return bRet;
889 }
890 
891 sal_Bool SbxValue::PutNull()
892 {
893 	sal_Bool bRet = SetType( SbxNULL );
894 	if( bRet )
895 		SetModified( sal_True );
896 	return bRet;
897 }
898 
899 
900 // Special decimal methods
901 sal_Bool SbxValue::PutDecimal( com::sun::star::bridge::oleautomation::Decimal& rAutomationDec )
902 {
903 	SbxValue::Clear();
904 	aData.pDecimal = new SbxDecimal( rAutomationDec );
905 	aData.pDecimal->addRef();
906 	aData.eType = SbxDECIMAL;
907 	return sal_True;
908 }
909 
910 sal_Bool SbxValue::fillAutomationDecimal
911 	( com::sun::star::bridge::oleautomation::Decimal& rAutomationDec )
912 {
913 	SbxDecimal* pDecimal = GetDecimal();
914 	if( pDecimal != NULL )
915 	{
916 		pDecimal->fillAutomationDecimal( rAutomationDec );
917 		return sal_True;
918 	}
919 	return sal_False;
920 }
921 
922 
923 sal_Bool SbxValue::PutpChar( const xub_Unicode* p )
924 {
925 	::rtl::OUString aVal( p );
926 	SbxValues aRes;
927 	aRes.eType = SbxLPSTR;
928 	aRes.pOUString = &aVal;
929 	Put( aRes );
930 	return sal_Bool( !IsError() );
931 }
932 
933 sal_Bool SbxValue::PutString( const ::rtl::OUString& r )
934 {
935 	SbxValues aRes;
936 	aRes.eType = SbxSTRING;
937 	aRes.pOUString = (::rtl::OUString*) &r;
938 	Put( aRes );
939 	return sal_Bool( !IsError() );
940 }
941 
942 
943 #define PUT( p, e, t, m ) \
944 sal_Bool SbxValue::p( t n ) \
945 { SbxValues aRes(e); aRes.m = n; Put( aRes ); return sal_Bool( !IsError() ); }
946 
947 PUT( PutByte,     SbxBYTE,       sal_uInt8,             nByte )
948 PUT( PutChar,     SbxCHAR,       xub_Unicode,      nChar )
949 PUT( PutCurrency, SbxCURRENCY,   const SbxINT64&,  nLong64 )
950 PUT( PutDate,     SbxDATE,       double,           nDouble )
951 PUT( PutData,     SbxDATAOBJECT, void*,            pData )
952 PUT( PutDouble,   SbxDOUBLE,     double,           nDouble )
953 PUT( PutErr,      SbxERROR,      sal_uInt16,           nUShort )
954 PUT( PutInt,      SbxINT,        int,              nInt )
955 PUT( PutInteger,  SbxINTEGER,    sal_Int16,            nInteger )
956 PUT( PutLong,     SbxLONG,       sal_Int32,            nLong )
957 PUT( PutLong64,   SbxLONG64,     const SbxINT64&,  nLong64 )
958 PUT( PutObject,   SbxOBJECT,     SbxBase*,         pObj )
959 PUT( PutSingle,   SbxSINGLE,     float,            nSingle )
960 PUT( PutULong,    SbxULONG,      sal_uInt32,           nULong )
961 PUT( PutULong64,  SbxULONG64,    const SbxUINT64&, nULong64 )
962 PUT( PutUShort,   SbxUSHORT,     sal_uInt16,           nUShort )
963 PUT( PutInt64,    SbxSALINT64,   sal_Int64,        nInt64 )
964 PUT( PutUInt64,   SbxSALUINT64,  sal_uInt64,       uInt64 )
965 PUT( PutDecimal,  SbxDECIMAL,    SbxDecimal*,      pDecimal )
966 
967 
968 ////////////////////////// Setzen des Datentyps ///////////////////////////
969 
970 sal_Bool SbxValue::IsFixed() const
971 {
972 	return ( (GetFlags() & SBX_FIXED) | (aData.eType & SbxBYREF) ) != 0;
973 }
974 
975 // Eine Variable ist numerisch, wenn sie EMPTY oder wirklich numerisch ist
976 // oder einen vollstaendig konvertierbaren String enthaelt
977 
978 // #41692, fuer RTL und Basic-Core getrennt implementieren
979 sal_Bool SbxValue::IsNumeric() const
980 {
981 	return ImpIsNumeric( /*bOnlyIntntl*/sal_False );
982 }
983 
984 sal_Bool SbxValue::IsNumericRTL() const
985 {
986 	return ImpIsNumeric( /*bOnlyIntntl*/sal_True );
987 }
988 
989 sal_Bool SbxValue::ImpIsNumeric( sal_Bool bOnlyIntntl ) const
990 {
991 
992 	if( !CanRead() )
993 	{
994 		SetError( SbxERR_PROP_WRITEONLY ); return sal_False;
995 	}
996 	// Downcast pruefen!!!
997 	if( this->ISA(SbxVariable) )
998 		((SbxVariable*)this)->Broadcast( SBX_HINT_DATAWANTED );
999 	SbxDataType t = GetType();
1000 	if( t == SbxSTRING )
1001 	{
1002 		if( aData.pOUString )
1003 		{
1004 			::rtl::OUString s( *aData.pOUString );
1005 			double n;
1006 			SbxDataType t2;
1007 			sal_uInt16 nLen = 0;
1008 			if( ImpScan( s, n, t2, &nLen, /*bAllowIntntl*/sal_False, bOnlyIntntl ) == SbxERR_OK )
1009 				return sal_Bool( nLen == s.getLength() );
1010 		}
1011 		return sal_False;
1012 	}
1013 	else
1014 		return sal_Bool( t == SbxEMPTY
1015 			|| ( t >= SbxINTEGER && t <= SbxCURRENCY )
1016 			|| ( t >= SbxCHAR && t <= SbxUINT ) );
1017 }
1018 
1019 SbxClassType SbxValue::GetClass() const
1020 {
1021 	return SbxCLASS_VALUE;
1022 }
1023 
1024 SbxDataType SbxValue::GetType() const
1025 {
1026 	return SbxDataType( aData.eType & 0x0FFF );
1027 }
1028 
1029 SbxDataType SbxValue::GetFullType() const
1030 {
1031 	return aData.eType;
1032 }
1033 
1034 sal_Bool SbxValue::SetType( SbxDataType t )
1035 {
1036 	DBG_ASSERT( !( t & 0xF000 ), "Setzen von BYREF|ARRAY verboten!" );
1037 	if( ( t == SbxEMPTY && aData.eType == SbxVOID )
1038 	 || ( aData.eType == SbxEMPTY && t == SbxVOID ) )
1039 		return sal_True;
1040 	if( ( t & 0x0FFF ) == SbxVARIANT )
1041 	{
1042 		// Versuch, den Datentyp auf Variant zu setzen
1043 		ResetFlag( SBX_FIXED );
1044 		if( IsFixed() )
1045 		{
1046 			SetError( SbxERR_CONVERSION ); return sal_False;
1047 		}
1048 		t = SbxEMPTY;
1049 	}
1050 	if( ( t & 0x0FFF ) != ( aData.eType & 0x0FFF ) )
1051 	{
1052 		if( !CanWrite() || IsFixed() )
1053 		{
1054 			SetError( SbxERR_CONVERSION ); return sal_False;
1055 		}
1056 		else
1057 		{
1058 			// Eventuelle Objekte freigeben
1059 			switch( aData.eType )
1060 			{
1061 				case SbxSTRING:
1062 					delete aData.pOUString;
1063 					break;
1064 				case SbxOBJECT:
1065 					if( aData.pObj && aData.pObj != this )
1066 					{
1067 						HACK(nicht bei Parent-Prop - sonst CyclicRef)
1068 						SbxVariable *pThisVar = PTR_CAST(SbxVariable, this);
1069 						sal_uInt16 nSlotId = pThisVar
1070 									? ( (sal_Int16) ( pThisVar->GetUserData() & 0xFFFF ) )
1071 									: 0;
1072 						DBG_ASSERT( nSlotId != 5345 || pThisVar->GetName() == UniString::CreateFromAscii( "Parent" ),
1073 									"SID_PARENTOBJECT heisst nicht 'Parent'" );
1074 						sal_Bool bParentProp = 5345 == nSlotId;
1075 						if ( !bParentProp )
1076 							aData.pObj->ReleaseRef();
1077 					}
1078 					break;
1079 				default: break;
1080 			}
1081 			// Das klappt immer, da auch die Float-Repraesentationen 0 sind.
1082 			memset( &aData, 0, sizeof( SbxValues ) );
1083 			aData.eType = t;
1084 		}
1085 	}
1086 	return sal_True;
1087 }
1088 
1089 sal_Bool SbxValue::Convert( SbxDataType eTo )
1090 {
1091 	eTo = SbxDataType( eTo & 0x0FFF );
1092 	if( ( aData.eType & 0x0FFF ) == eTo )
1093 		return sal_True;
1094 	if( !CanWrite() )
1095 		return sal_False;
1096 	if( eTo == SbxVARIANT )
1097 	{
1098 		// Versuch, den Datentyp auf Variant zu setzen
1099 		ResetFlag( SBX_FIXED );
1100 		if( IsFixed() )
1101 		{
1102 			SetError( SbxERR_CONVERSION ); return sal_False;
1103 		}
1104 		else
1105 			return sal_True;
1106 	}
1107 	// Convert from Null geht niemals. Einmal Null, immer Null!
1108 	if( aData.eType == SbxNULL )
1109 	{
1110 		SetError( SbxERR_CONVERSION ); return sal_False;
1111 	}
1112 
1113 	// Konversion der Daten:
1114 	SbxValues aNew;
1115 	aNew.eType = eTo;
1116 	if( Get( aNew ) )
1117 	{
1118 		// Der Datentyp konnte konvertiert werden. Bei Fixed-Elementen
1119 		// ist hier Ende, da die Daten nicht uebernommen zu werden brauchen
1120 		if( !IsFixed() )
1121 		{
1122 			SetType( eTo );
1123 			Put( aNew );
1124 			SetModified( sal_True );
1125 		}
1126 		Broadcast( SBX_HINT_CONVERTED );
1127 		return sal_True;
1128 	}
1129 	else
1130 		return sal_False;
1131 }
1132 ////////////////////////////////// Rechnen /////////////////////////////////
1133 
1134 sal_Bool SbxValue::Compute( SbxOperator eOp, const SbxValue& rOp )
1135 {
1136 	bool bVBAInterop =  SbiRuntime::isVBAEnabled();
1137 
1138 	SbxDataType eThisType = GetType();
1139 	SbxDataType eOpType = rOp.GetType();
1140 	SbxError eOld = GetError();
1141 	if( eOld != SbxERR_OK )
1142 		ResetError();
1143 	if( !CanWrite() )
1144 		SetError( SbxERR_PROP_READONLY );
1145 	else if( !rOp.CanRead() )
1146 		SetError( SbxERR_PROP_WRITEONLY );
1147 	// Sonderregel 1: Ist ein Operand Null, ist das Ergebnis Null
1148 	else if( eThisType == SbxNULL || eOpType == SbxNULL )
1149 		SetType( SbxNULL );
1150 	// Sonderregel 2: Ist ein Operand Empty, ist das Ergebnis der 2. Operand
1151 	else if( eThisType == SbxEMPTY
1152 	&& !bVBAInterop
1153 	)
1154 		*this = rOp;
1155 	// 13.2.96: Nicht schon vor Get auf SbxEMPTY pruefen
1156 	else
1157 	{
1158 		SbxValues aL, aR;
1159 		bool bDecimal = false;
1160 		if( bVBAInterop && ( ( eThisType == SbxSTRING && eOpType != SbxSTRING ) ||
1161 			 ( eThisType != SbxSTRING && eOpType == SbxSTRING ) ) &&
1162 			 ( eOp == SbxMUL || eOp == SbxDIV || eOp == SbxPLUS || eOp == SbxMINUS ) )
1163 		{
1164 			goto Lbl_OpIsDouble;
1165 		}
1166 		else if( eThisType == SbxSTRING || eOp == SbxCAT || ( bVBAInterop && ( eOpType == SbxSTRING ) && (  eOp == SbxPLUS ) ) )
1167 		{
1168 			if( eOp == SbxCAT || eOp == SbxPLUS )
1169 			{
1170 				// AB 5.11.1999, OUString beruecksichtigen
1171 				aL.eType = aR.eType = SbxSTRING;
1172 				rOp.Get( aR );
1173 				// AB 8.12.1999, #70399: Hier wieder GetType() rufen, Get() kann Typ aendern!
1174 				if( rOp.GetType() == SbxEMPTY )
1175 					goto Lbl_OpIsEmpty;
1176 				Get( aL );
1177 
1178 				// #30576: Erstmal testen, ob Wandlung geklappt hat
1179 				if( aL.pOUString != NULL && aR.pOUString != NULL )
1180 				{
1181 					*aL.pOUString += *aR.pOUString;
1182 				}
1183 				// Nicht einmal Left OK?
1184 				else if( aL.pOUString == NULL )
1185 				{
1186 					aL.pOUString = new ::rtl::OUString();
1187 				}
1188 				Put( aL );
1189 			}
1190 			else
1191 				SetError( SbxERR_CONVERSION );
1192 		}
1193 		else if( eOpType == SbxSTRING && rOp.IsFixed() )
1194 		{	// Numerisch: rechts darf kein String stehen
1195 			SetError( SbxERR_CONVERSION );
1196 		}
1197 		else if( ( eOp >= SbxIDIV && eOp <= SbxNOT ) || eOp == SbxMOD )
1198 		{
1199 			if( GetType() == eOpType )
1200 			{
1201 				if( GetType() == SbxULONG64
1202 					|| GetType() == SbxLONG64
1203 					|| GetType() == SbxCURRENCY
1204 					|| GetType() == SbxULONG )
1205 					aL.eType = aR.eType = GetType();
1206 //				else if( GetType() == SbxDouble || GetType() == SbxSingle )
1207 //					aL.eType = aR.eType = SbxLONG64;
1208 				else
1209 					aL.eType = aR.eType = SbxLONG;
1210 			}
1211 			else if( GetType() == SbxCURRENCY || eOpType == SbxCURRENCY
1212 					 || GetType() == SbxULONG64 || eOpType == SbxULONG64
1213 					 || GetType() == SbxLONG64 || eOpType == SbxLONG64 )
1214 				aL.eType = aR.eType = SbxLONG64;
1215 //			else if( GetType() == SbxDouble || rOP.GetType() == SbxDouble
1216 //			         || GetType() == SbxSingle || rOP.GetType() == SbxSingle )
1217 //				aL.eType = aR.eType = SbxLONG64;
1218 			else
1219 				aL.eType = aR.eType = SbxLONG;
1220 
1221 			if( rOp.Get( aR ) )
1222 			{
1223 				if( rOp.GetType() == SbxEMPTY )
1224 				{
1225 					if ( !bVBAInterop || ( bVBAInterop && ( eOp != SbxNOT  ) ) )
1226 						goto Lbl_OpIsEmpty;
1227 				}
1228 				if( Get( aL ) ) switch( eOp )
1229 				{
1230 					case SbxIDIV:
1231 						if( aL.eType == SbxCURRENCY )
1232 							aL.eType = SbxLONG64;
1233 						if( aL.eType == SbxLONG64 )
1234 							if( !aR.nLong64 ) SetError( SbxERR_ZERODIV );
1235 							else aL.nLong64 /= aR.nLong64;
1236 						else if( aL.eType == SbxULONG64 )
1237 							if( !aR.nULong64 ) SetError( SbxERR_ZERODIV );
1238 							else aL.nULong64 /= aR.nULong64;
1239 						else if( aL.eType == SbxLONG )
1240 							if( !aR.nLong ) SetError( SbxERR_ZERODIV );
1241 							else aL.nLong /= aR.nLong;
1242 						else
1243 							if( !aR.nULong ) SetError( SbxERR_ZERODIV );
1244 							else aL.nULong /= aR.nULong;
1245 						break;
1246 					case SbxMOD:
1247 						if( aL.eType == SbxCURRENCY )
1248 							aL.eType = SbxLONG64;
1249 						if( aL.eType == SbxLONG64 )
1250 							if( !aR.nLong64 ) SetError( SbxERR_ZERODIV );
1251 							else aL.nLong64 %= aR.nLong64;
1252 						else if( aL.eType == SbxULONG64 )
1253 							if( !aR.nULong64 ) SetError( SbxERR_ZERODIV );
1254 							else aL.nULong64 %= aR.nULong64;
1255 						else if( aL.eType == SbxLONG )
1256 							if( !aR.nLong ) SetError( SbxERR_ZERODIV );
1257 							else aL.nLong %= aR.nLong;
1258 						else
1259 							if( !aR.nULong ) SetError( SbxERR_ZERODIV );
1260 							else aL.nULong %= aR.nULong;
1261 						break;
1262 					case SbxAND:
1263 						if( aL.eType != SbxLONG && aL.eType != SbxULONG )
1264 							aL.nLong64 &= aR.nLong64;
1265 						else
1266 							aL.nLong &= aR.nLong;
1267 						break;
1268 					case SbxOR:
1269 						if( aL.eType != SbxLONG && aL.eType != SbxULONG )
1270 							aL.nLong64 |= aR.nLong64;
1271 						else
1272 							aL.nLong |= aR.nLong;
1273 						break;
1274 					case SbxXOR:
1275 						if( aL.eType != SbxLONG && aL.eType != SbxULONG )
1276 							aL.nLong64 ^= aR.nLong64;
1277 						else
1278 							aL.nLong ^= aR.nLong;
1279 						break;
1280 					case SbxEQV:
1281 						if( aL.eType != SbxLONG && aL.eType != SbxULONG )
1282 							aL.nLong64 = (aL.nLong64 & aR.nLong64) | (~aL.nLong64 & ~aR.nLong64);
1283 						else
1284 							aL.nLong = (aL.nLong & aR.nLong) | (~aL.nLong & ~aR.nLong);
1285 						break;
1286 					case SbxIMP:
1287 						if( aL.eType != SbxLONG && aL.eType != SbxULONG )
1288 							aL.nLong64 = ~aL.nLong64 | aR.nLong64;
1289 						else
1290 							aL.nLong = ~aL.nLong | aR.nLong;
1291 						break;
1292 					case SbxNOT:
1293 						if( aL.eType != SbxLONG && aL.eType != SbxULONG )
1294 							aL.nLong64 = ~aL.nLong64;
1295 						else
1296 							aL.nLong = ~aL.nLong;
1297 						break;
1298 					default: break;
1299 				}
1300 			}
1301 		}
1302 		else if( ( GetType() == SbxDECIMAL || rOp.GetType() == SbxDECIMAL ) &&
1303 			     ( eOp == SbxMUL || eOp == SbxDIV || eOp == SbxPLUS || eOp == SbxMINUS || eOp == SbxNEG ) )
1304 		{
1305 			aL.eType = aR.eType = SbxDECIMAL;
1306 			bDecimal = true;
1307 			if( rOp.Get( aR ) )
1308 			{
1309 				if( rOp.GetType() == SbxEMPTY )
1310 				{
1311 					releaseDecimalPtr( aL.pDecimal );
1312 					goto Lbl_OpIsEmpty;
1313 				}
1314 				if( Get( aL ) )
1315 				{
1316 					if( aL.pDecimal && aR.pDecimal )
1317 					{
1318 						bool bOk = true;
1319 						switch( eOp )
1320 						{
1321 							case SbxMUL:
1322 								bOk = ( *(aL.pDecimal) *= *(aR.pDecimal) );
1323 								break;
1324 							case SbxDIV:
1325 								if( aR.pDecimal->isZero() )
1326 									SetError( SbxERR_ZERODIV );
1327 								else
1328 									bOk = ( *(aL.pDecimal) /= *(aR.pDecimal) );
1329 								break;
1330 							case SbxPLUS:
1331 								bOk = ( *(aL.pDecimal) += *(aR.pDecimal) );
1332 								break;
1333 							case SbxMINUS:
1334 								bOk = ( *(aL.pDecimal) -= *(aR.pDecimal) );
1335 								break;
1336 							case SbxNEG:
1337 								bOk = ( aL.pDecimal->neg() );
1338 								break;
1339 							default:
1340 								SetError( SbxERR_NOTIMP );
1341 						}
1342 						if( !bOk )
1343 							SetError( SbxERR_OVERFLOW );
1344 					}
1345 					else
1346 					{
1347 						SetError( SbxERR_CONVERSION );
1348 					}
1349 				}
1350 			}
1351 		}
1352 		else if( GetType() == SbxCURRENCY || rOp.GetType() == SbxCURRENCY )
1353 		{
1354 			aL.eType = SbxCURRENCY;
1355 			aR.eType = SbxCURRENCY;
1356 
1357 			if( rOp.Get( aR ) )
1358 			{
1359 				static BigInt n10K( 10000 );
1360 
1361 				if( rOp.GetType() == SbxEMPTY )
1362 					goto Lbl_OpIsEmpty;
1363 
1364 				if( Get( aL ) ) switch( eOp )
1365 				{
1366 					case SbxMUL:
1367 					{
1368 						// #i20704 Implement directly
1369 						BigInt b1( aL.nLong64 );
1370 						BigInt b2( aR.nLong64 );
1371 						b1 *= b2;
1372 						b1 /= n10K;
1373 						double d = double( b1 ) / 10000.0;
1374 						if( d > SbxMAXCURR || d < SbxMINCURR )
1375 							SetError( SbxERR_OVERFLOW );
1376 						else
1377 							b1.INT64( &aL.nLong64 );
1378 						break;
1379 					}
1380 					case SbxDIV:
1381 						if( !aR.nLong64 )
1382 						{
1383 							SetError( SbxERR_ZERODIV );
1384 						}
1385 						else
1386 						{
1387 							// #i20704 Implement directly
1388 							BigInt b1( aL.nLong64 );
1389 							BigInt b2( aR.nLong64 );
1390 							b1 *= n10K;
1391 							b1 /= b2;
1392 							double d = double( b1 ) / 10000.0;
1393 							if( d > SbxMAXCURR || d < SbxMINCURR )
1394 								SetError( SbxERR_OVERFLOW );
1395 							else
1396 								b1.INT64( &aL.nLong64 );
1397 						}
1398 						break;
1399 					case SbxPLUS:
1400 						aL.nLong64 += aR.nLong64; break;
1401 					case SbxMINUS:
1402 						aL.nLong64 -= aR.nLong64; break;
1403 					case SbxNEG:
1404 						aL.nLong64 = -aL.nLong64; break;
1405 					default:
1406 						SetError( SbxERR_NOTIMP );
1407 				}
1408 			}
1409 		}
1410 		else
1411 Lbl_OpIsDouble:
1412 		{	// Andere Operatoren
1413 			aL.eType = aR.eType = SbxDOUBLE;
1414 			if( rOp.Get( aR ) )
1415 			{
1416 				if( rOp.GetType() == SbxEMPTY )
1417 				{
1418 					if ( !bVBAInterop || ( bVBAInterop && ( eOp != SbxNEG ) ) )
1419 						goto Lbl_OpIsEmpty;
1420 				}
1421 				if( Get( aL ) )
1422 				{
1423 					switch( eOp )
1424 					{
1425 						case SbxEXP:
1426 							aL.nDouble = pow( aL.nDouble, aR.nDouble );
1427 							break;
1428 						case SbxMUL:
1429 							aL.nDouble *= aR.nDouble; break;
1430 						case SbxDIV:
1431 							if( !aR.nDouble ) SetError( SbxERR_ZERODIV );
1432 							else aL.nDouble /= aR.nDouble; break;
1433 						case SbxPLUS:
1434 							aL.nDouble += aR.nDouble; break;
1435 						case SbxMINUS:
1436 							aL.nDouble -= aR.nDouble; break;
1437 						case SbxNEG:
1438 							aL.nDouble = -aL.nDouble; break;
1439 						default:
1440 							SetError( SbxERR_NOTIMP );
1441 					}
1442 
1443 					// #45465 Date braucht bei + eine Spezial-Behandlung
1444 					if( eOp == SbxPLUS && (GetType() == SbxDATE || rOp.GetType() == SbxDATE ) )
1445 						aL.eType = SbxDATE;
1446 				}
1447 			}
1448 
1449 		}
1450 		if( !IsError() )
1451 			Put( aL );
1452 		if( bDecimal )
1453 		{
1454 			releaseDecimalPtr( aL.pDecimal );
1455 			releaseDecimalPtr( aR.pDecimal );
1456 		}
1457 	}
1458 Lbl_OpIsEmpty:
1459 
1460 	sal_Bool bRes = sal_Bool( !IsError() );
1461 	if( bRes && eOld != SbxERR_OK )
1462 		SetError( eOld );
1463 	return bRes;
1464 }
1465 
1466 // Die Vergleichs-Routine liefert sal_True oder sal_False.
1467 
1468 sal_Bool SbxValue::Compare( SbxOperator eOp, const SbxValue& rOp ) const
1469 {
1470 	bool bVBAInterop =  SbiRuntime::isVBAEnabled();
1471 
1472 	sal_Bool bRes = sal_False;
1473 	SbxError eOld = GetError();
1474 	if( eOld != SbxERR_OK )
1475 		ResetError();
1476 	if( !CanRead() || !rOp.CanRead() )
1477 		SetError( SbxERR_PROP_WRITEONLY );
1478 	else if( GetType() == SbxNULL && rOp.GetType() == SbxNULL && !bVBAInterop )
1479     {
1480 		bRes = sal_True;
1481     }
1482 	else if( GetType() == SbxEMPTY && rOp.GetType() == SbxEMPTY )
1483 		bRes = !bVBAInterop ? sal_True : ( eOp == SbxEQ ? sal_True : sal_False );
1484 	// Sonderregel 1: Ist ein Operand Null, ist das Ergebnis FALSE
1485 	else if( GetType() == SbxNULL || rOp.GetType() == SbxNULL )
1486 		bRes = sal_False;
1487 	// Sonderregel 2: Wenn beide Variant sind und einer ist numerisch,
1488 	// und der andere ein String, ist num < str
1489 	else if( !IsFixed() && !rOp.IsFixed()
1490 	 && ( rOp.GetType() == SbxSTRING && GetType() != SbxSTRING && IsNumeric() ) && !bVBAInterop
1491 	)
1492 		bRes = sal_Bool( eOp == SbxLT || eOp == SbxLE || eOp == SbxNE );
1493 	else if( !IsFixed() && !rOp.IsFixed()
1494 	 && ( GetType() == SbxSTRING && rOp.GetType() != SbxSTRING && rOp.IsNumeric() )
1495 && !bVBAInterop
1496 	)
1497 		bRes = sal_Bool( eOp == SbxGT || eOp == SbxGE || eOp == SbxNE );
1498 	else
1499 	{
1500 		SbxValues aL, aR;
1501 		// Wenn einer der Operanden ein String ist,
1502 		// findet ein Stringvergleich statt
1503 		if( GetType() == SbxSTRING || rOp.GetType() == SbxSTRING )
1504 		{
1505 			aL.eType = aR.eType = SbxSTRING;
1506 			if( Get( aL ) && rOp.Get( aR ) ) switch( eOp )
1507 			{
1508 				case SbxEQ:
1509 					bRes = sal_Bool( *aL.pOUString == *aR.pOUString ); break;
1510 				case SbxNE:
1511 					bRes = sal_Bool( *aL.pOUString != *aR.pOUString ); break;
1512 				case SbxLT:
1513 					bRes = sal_Bool( *aL.pOUString <  *aR.pOUString ); break;
1514 				case SbxGT:
1515 					bRes = sal_Bool( *aL.pOUString >  *aR.pOUString ); break;
1516 				case SbxLE:
1517 					bRes = sal_Bool( *aL.pOUString <= *aR.pOUString ); break;
1518 				case SbxGE:
1519 					bRes = sal_Bool( *aL.pOUString >= *aR.pOUString ); break;
1520 				default:
1521 					SetError( SbxERR_NOTIMP );
1522 			}
1523 		}
1524 		// AB 19.12.95: Wenn SbxSINGLE beteiligt, auf SINGLE konvertieren,
1525 		//				sonst gibt es numerische Fehler
1526 		else if( GetType() == SbxSINGLE || rOp.GetType() == SbxSINGLE )
1527 		{
1528 			aL.eType = aR.eType = SbxSINGLE;
1529 			if( Get( aL ) && rOp.Get( aR ) )
1530 			  switch( eOp )
1531 			{
1532 				case SbxEQ:
1533 					bRes = sal_Bool( aL.nSingle == aR.nSingle ); break;
1534 				case SbxNE:
1535 					bRes = sal_Bool( aL.nSingle != aR.nSingle ); break;
1536 				case SbxLT:
1537 					bRes = sal_Bool( aL.nSingle <  aR.nSingle ); break;
1538 				case SbxGT:
1539 					bRes = sal_Bool( aL.nSingle >  aR.nSingle ); break;
1540 				case SbxLE:
1541 					bRes = sal_Bool( aL.nSingle <= aR.nSingle ); break;
1542 				case SbxGE:
1543 					bRes = sal_Bool( aL.nSingle >= aR.nSingle ); break;
1544 				default:
1545 					SetError( SbxERR_NOTIMP );
1546 			}
1547 		}
1548 		else if( GetType() == SbxDECIMAL && rOp.GetType() == SbxDECIMAL )
1549 		{
1550 			aL.eType = aR.eType = SbxDECIMAL;
1551 			Get( aL );
1552 			rOp.Get( aR );
1553 			if( aL.pDecimal && aR.pDecimal )
1554 			{
1555 				SbxDecimal::CmpResult eRes = compare( *aL.pDecimal, *aR.pDecimal );
1556 				switch( eOp )
1557 				{
1558 					case SbxEQ:
1559 						bRes = sal_Bool( eRes == SbxDecimal::EQ ); break;
1560 					case SbxNE:
1561 						bRes = sal_Bool( eRes != SbxDecimal::EQ ); break;
1562 					case SbxLT:
1563 						bRes = sal_Bool( eRes == SbxDecimal::LT ); break;
1564 					case SbxGT:
1565 						bRes = sal_Bool( eRes == SbxDecimal::GT ); break;
1566 					case SbxLE:
1567 						bRes = sal_Bool( eRes != SbxDecimal::GT ); break;
1568 					case SbxGE:
1569 						bRes = sal_Bool( eRes != SbxDecimal::LT ); break;
1570 					default:
1571 						SetError( SbxERR_NOTIMP );
1572 				}
1573 			}
1574 			else
1575 			{
1576 				SetError( SbxERR_CONVERSION );
1577 			}
1578 			releaseDecimalPtr( aL.pDecimal );
1579 			releaseDecimalPtr( aR.pDecimal );
1580 		}
1581 		// Alles andere auf SbxDOUBLE-Basis vergleichen
1582 		else
1583 		{
1584 			aL.eType = aR.eType = SbxDOUBLE;
1585 			//if( Get( aL ) && rOp.Get( aR ) )
1586 			bool bGetL = Get( aL );
1587 			bool bGetR = rOp.Get( aR );
1588 			if( bGetL && bGetR )
1589 			  switch( eOp )
1590 			{
1591 				case SbxEQ:
1592 					bRes = sal_Bool( aL.nDouble == aR.nDouble ); break;
1593 				case SbxNE:
1594 					bRes = sal_Bool( aL.nDouble != aR.nDouble ); break;
1595 				case SbxLT:
1596 					bRes = sal_Bool( aL.nDouble <  aR.nDouble ); break;
1597 				case SbxGT:
1598 					bRes = sal_Bool( aL.nDouble >  aR.nDouble ); break;
1599 				case SbxLE:
1600 					bRes = sal_Bool( aL.nDouble <= aR.nDouble ); break;
1601 				case SbxGE:
1602 					bRes = sal_Bool( aL.nDouble >= aR.nDouble ); break;
1603 				default:
1604 					SetError( SbxERR_NOTIMP );
1605 			}
1606 			// at least one value was got
1607 			// if this is VBA then a conversion error for one
1608 			// side will yield a false result of an equality test
1609 			else if ( bGetR || bGetL )
1610 			{
1611 				if ( bVBAInterop && eOp == SbxEQ && GetError() == SbxERR_CONVERSION )
1612 				{
1613 					ResetError();
1614 					bRes = sal_False;
1615 				}
1616 			}
1617 		}
1618 	}
1619 	if( eOld != SbxERR_OK )
1620 		SetError( eOld );
1621 	return bRes;
1622 }
1623 
1624 ///////////////////////////// Lesen/Schreiben ////////////////////////////
1625 
1626 sal_Bool SbxValue::LoadData( SvStream& r, sal_uInt16 )
1627 {
1628 	SbxValue::Clear();
1629 	sal_uInt16 nType;
1630 	r >> nType;
1631 	aData.eType = SbxDataType( nType );
1632 	switch( nType )
1633 	{
1634 		case SbxBOOL:
1635 		case SbxINTEGER:
1636 			r >> aData.nInteger; break;
1637 		case SbxLONG:
1638 			r >> aData.nLong; break;
1639 		case SbxSINGLE:
1640 		{
1641 			// Floats als ASCII
1642 			XubString aVal;
1643 			r.ReadByteString( aVal, RTL_TEXTENCODING_ASCII_US );
1644 			double d;
1645 			SbxDataType t;
1646 			if( ImpScan( aVal, d, t, NULL ) != SbxERR_OK || t == SbxDOUBLE )
1647 			{
1648 				aData.nSingle = 0.0F;
1649 				return sal_False;
1650 			}
1651 			aData.nSingle = (float) d;
1652 			break;
1653 		}
1654 		case SbxDATE:
1655 		case SbxDOUBLE:
1656 		{
1657 			// Floats als ASCII
1658 			XubString aVal;
1659 			r.ReadByteString( aVal, RTL_TEXTENCODING_ASCII_US );
1660 			SbxDataType t;
1661 			if( ImpScan( aVal, aData.nDouble, t, NULL ) != SbxERR_OK )
1662 			{
1663 				aData.nDouble = 0.0;
1664 				return sal_False;
1665 			}
1666 			break;
1667 		}
1668 		case SbxULONG64:
1669 		{
1670 			r >> aData.nULong64.nHigh >> aData.nULong64.nLow;
1671 			break;
1672 		}
1673 		case SbxLONG64:
1674 		case SbxCURRENCY:
1675 		{
1676 			r >> aData.nLong64.nHigh >> aData.nLong64.nLow;
1677 			break;
1678 		}
1679 		case SbxSTRING:
1680 		{
1681 			XubString aVal;
1682 			r.ReadByteString( aVal, RTL_TEXTENCODING_ASCII_US );
1683 			if( aVal.Len() )
1684 				aData.pOUString = new ::rtl::OUString( aVal );
1685 			else
1686 				aData.pOUString = NULL; // JSM 22.09.1995
1687 			break;
1688 		}
1689 		case SbxERROR:
1690 		case SbxUSHORT:
1691 			r >> aData.nUShort; break;
1692 		case SbxOBJECT:
1693 		{
1694 			sal_uInt8 nMode;
1695 			r >> nMode;
1696 			switch( nMode )
1697 			{
1698 				case 0:
1699 					aData.pObj = NULL;
1700 					break;
1701 				case 1:
1702 					aData.pObj = SbxBase::Load( r );
1703 					return sal_Bool( aData.pObj != NULL );
1704 				case 2:
1705 					aData.pObj = this;
1706 					break;
1707 			}
1708 			break;
1709 		}
1710 		case SbxCHAR:
1711 		{
1712 			char c;
1713 			r >> c;
1714 			aData.nChar = c;
1715 			break;
1716 		}
1717 		case SbxBYTE:
1718 			r >> aData.nByte; break;
1719 		case SbxULONG:
1720 			r >> aData.nULong; break;
1721 		case SbxINT:
1722 		{
1723 			sal_uInt8 n;
1724 			r >> n;
1725 			// Passt der Int auf diesem System?
1726 			if( n > SAL_TYPES_SIZEOFINT )
1727 				r >> aData.nLong, aData.eType = SbxLONG;
1728 			else
1729 				r >> aData.nInt;
1730 			break;
1731 		}
1732 		case SbxUINT:
1733 		{
1734 			sal_uInt8 n;
1735 			r >> n;
1736 			// Passt der UInt auf diesem System?
1737 			if( n > SAL_TYPES_SIZEOFINT )
1738 				r >> aData.nULong, aData.eType = SbxULONG;
1739 			else
1740 				r >> (sal_uInt32&)aData.nUInt;
1741 			break;
1742 		}
1743 		case SbxEMPTY:
1744 		case SbxNULL:
1745 		case SbxVOID:
1746 			break;
1747 		case SbxDATAOBJECT:
1748 			r >> aData.nLong;
1749 			break;
1750 		// #78919 For backwards compatibility
1751 		case SbxWSTRING:
1752 		case SbxWCHAR:
1753 			break;
1754 		default:
1755 			memset (&aData,0,sizeof(aData));
1756 			ResetFlag(SBX_FIXED);
1757 			aData.eType = SbxNULL;
1758 			DBG_ASSERT( !this, "Nicht unterstuetzer Datentyp geladen" );
1759 			return sal_False;
1760 	}
1761 	return sal_True;
1762 }
1763 
1764 sal_Bool SbxValue::StoreData( SvStream& r ) const
1765 {
1766 	sal_uInt16 nType = sal::static_int_cast< sal_uInt16 >(aData.eType);
1767 	r << nType;
1768 	switch( nType & 0x0FFF )
1769 	{
1770 		case SbxBOOL:
1771 		case SbxINTEGER:
1772 			r << aData.nInteger; break;
1773 		case SbxLONG:
1774 			r << aData.nLong; break;
1775 		case SbxDATE:
1776 			// #49935: Als double speichern, sonst Fehler beim Einlesen
1777 			((SbxValue*)this)->aData.eType = (SbxDataType)( ( nType & 0xF000 ) | SbxDOUBLE );
1778 			r.WriteByteString( GetCoreString(), RTL_TEXTENCODING_ASCII_US );
1779 			((SbxValue*)this)->aData.eType = (SbxDataType)nType;
1780 			break;
1781 		case SbxSINGLE:
1782 		case SbxDOUBLE:
1783 			r.WriteByteString( GetCoreString(), RTL_TEXTENCODING_ASCII_US );
1784 			break;
1785 		case SbxULONG64:
1786 		{
1787 			r << aData.nULong64.nHigh << aData.nULong64.nLow;
1788 			break;
1789 		}
1790 		case SbxLONG64:
1791 		case SbxCURRENCY:
1792 		{
1793 			r << aData.nLong64.nHigh << aData.nLong64.nLow;
1794 			break;
1795 		}
1796 		case SbxSTRING:
1797 			if( aData.pOUString )
1798 			{
1799 				r.WriteByteString( *aData.pOUString, RTL_TEXTENCODING_ASCII_US );
1800 			}
1801 			else
1802 			{
1803 				String aEmpty;
1804 				r.WriteByteString( aEmpty, RTL_TEXTENCODING_ASCII_US );
1805 			}
1806 			break;
1807 		case SbxERROR:
1808 		case SbxUSHORT:
1809 			r << aData.nUShort; break;
1810 		case SbxOBJECT:
1811 			// sich selbst als Objektptr speichern geht nicht!
1812 			if( aData.pObj )
1813 			{
1814 				if( PTR_CAST(SbxValue,aData.pObj) != this )
1815 				{
1816 					r << (sal_uInt8) 1;
1817 					return aData.pObj->Store( r );
1818 				}
1819 				else
1820 					r << (sal_uInt8) 2;
1821 			}
1822 			else
1823 				r << (sal_uInt8) 0;
1824 			break;
1825 		case SbxCHAR:
1826 		{
1827 			char c = sal::static_int_cast< char >(aData.nChar);
1828 			r << c;
1829 			break;
1830 		}
1831 		case SbxBYTE:
1832 			r << aData.nByte; break;
1833 		case SbxULONG:
1834 			r << aData.nULong; break;
1835 		case SbxINT:
1836 		{
1837 			sal_uInt8 n = SAL_TYPES_SIZEOFINT;
1838 			r << n << (sal_Int32)aData.nInt;
1839 			break;
1840 		}
1841 		case SbxUINT:
1842 		{
1843 			sal_uInt8 n = SAL_TYPES_SIZEOFINT;
1844 			r << n << (sal_uInt32)aData.nUInt;
1845 			break;
1846 		}
1847 		case SbxEMPTY:
1848 		case SbxNULL:
1849 		case SbxVOID:
1850 			break;
1851 		case SbxDATAOBJECT:
1852 			r << aData.nLong;
1853 			break;
1854 		// #78919 For backwards compatibility
1855 		case SbxWSTRING:
1856 		case SbxWCHAR:
1857 			break;
1858 		default:
1859 			DBG_ASSERT( !this, "Speichern eines nicht unterstuetzten Datentyps" );
1860 			return sal_False;
1861 	}
1862 	return sal_True;
1863 }
1864 
1865