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