1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
23 #include <tools/debug.hxx>
24 #include <tools/stream.hxx>
26 #include <basic/sbx.hxx>
27 #include "sbunoobj.hxx"
28 #include "sbxconv.hxx"
29 #include "runtime.hxx"
31 TYPEINIT1(SbxValue
,SbxBase
)
33 ///////////////////////////// constructors
35 SbxValue::SbxValue() : SbxBase()
37 aData
.eType
= SbxEMPTY
;
40 SbxValue::SbxValue( SbxDataType t
, void* p
) : SbxBase()
53 case SbxINTEGER
: n
|= SbxBYREF
; aData
.pInteger
= static_cast<sal_Int16
*>(p
); break;
54 case SbxSALUINT64
: n
|= SbxBYREF
; aData
.puInt64
= static_cast<sal_uInt64
*>(p
); break;
56 case SbxCURRENCY
: n
|= SbxBYREF
; aData
.pnInt64
= static_cast<sal_Int64
*>(p
); break;
57 case SbxLONG
: n
|= SbxBYREF
; aData
.pLong
= static_cast<sal_Int32
*>(p
); break;
58 case SbxSINGLE
: n
|= SbxBYREF
; aData
.pSingle
= static_cast<float*>(p
); break;
60 case SbxDOUBLE
: n
|= SbxBYREF
; aData
.pDouble
= static_cast<double*>(p
); break;
61 case SbxSTRING
: n
|= SbxBYREF
; aData
.pOUString
= static_cast<OUString
*>(p
); break;
64 case SbxBOOL
: n
|= SbxBYREF
; aData
.pUShort
= static_cast<sal_uInt16
*>(p
); break;
65 case SbxULONG
: n
|= SbxBYREF
; aData
.pULong
= static_cast<sal_uInt32
*>(p
); break;
66 case SbxCHAR
: n
|= SbxBYREF
; aData
.pChar
= static_cast<sal_Unicode
*>(p
); break;
67 case SbxBYTE
: n
|= SbxBYREF
; aData
.pByte
= static_cast<sal_uInt8
*>(p
); break;
68 case SbxINT
: n
|= SbxBYREF
; aData
.pInt
= static_cast<int*>(p
); break;
70 aData
.pObj
= static_cast<SbxBase
*>(p
);
72 aData
.pObj
->AddFirstRef();
75 aData
.pDecimal
= static_cast<SbxDecimal
*>(p
);
77 aData
.pDecimal
->addRef();
80 DBG_ASSERT( false, "Improper pointer argument" );
85 memset( &aData
, 0, sizeof( SbxValues
) );
86 aData
.eType
= SbxDataType( n
);
89 SbxValue::SbxValue( const SbxValue
& r
)
90 : SvRefBase( r
), SbxBase( r
)
94 SetError( SbxERR_PROP_WRITEONLY
);
96 aData
.eType
= SbxNULL
;
100 const_cast<SbxValue
*>(&r
)->Broadcast( SBX_HINT_DATAWANTED
);
102 // Copy pointer, increment references
103 switch( aData
.eType
)
106 if( aData
.pOUString
)
107 aData
.pOUString
= new OUString( *aData
.pOUString
);
111 aData
.pObj
->AddFirstRef();
115 aData
.pDecimal
->addRef();
122 SbxValue
& SbxValue::operator=( const SbxValue
& r
)
127 SetError( SbxERR_PROP_READONLY
);
130 // string -> byte array
131 if( IsFixed() && (aData
.eType
== SbxOBJECT
)
132 && aData
.pObj
&& ( aData
.pObj
->GetType() == (SbxARRAY
| SbxBYTE
) )
133 && (r
.aData
.eType
== SbxSTRING
) )
135 OUString aStr
= r
.GetOUString();
136 SbxArray
* pArr
= StringToByteArray(aStr
);
140 // byte array -> string
141 if( r
.IsFixed() && (r
.aData
.eType
== SbxOBJECT
)
142 && r
.aData
.pObj
&& ( r
.aData
.pObj
->GetType() == (SbxARRAY
| SbxBYTE
) )
143 && (aData
.eType
== SbxSTRING
) )
145 SbxBase
* pObj
= r
.GetObject();
146 SbxArray
* pArr
= PTR_CAST(SbxArray
, pObj
);
149 OUString aStr
= ByteArrayToString( pArr
);
154 // Readout the content of the variables
157 // then the type has to match
158 aNew
.eType
= aData
.eType
;
159 else if( r
.IsFixed() )
160 // Source fixed: copy the type
161 aNew
.eType
= SbxDataType( r
.aData
.eType
& 0x0FFF );
163 // both variant: then don't care
164 aNew
.eType
= SbxVARIANT
;
172 SbxValue::~SbxValue()
174 Broadcast( SBX_HINT_DYING
);
175 SetFlag( SBX_WRITE
);
179 void SbxValue::Clear()
181 switch( aData
.eType
)
188 delete aData
.pOUString
; aData
.pOUString
= NULL
;
193 if( aData
.pObj
!= this )
195 SAL_INFO("basic.sbx", "Not at Parent-Prop - otherwise CyclicRef");
196 SbxVariable
*pThisVar
= PTR_CAST(SbxVariable
, this);
197 bool bParentProp
= pThisVar
&& 5345 ==
198 ( (sal_Int16
) ( pThisVar
->GetUserData() & 0xFFFF ) );
200 aData
.pObj
->ReleaseRef();
206 if( aData
.eType
== SbxDECIMAL
)
207 releaseDecimalPtr( aData
.pDecimal
);
210 aData
.pData
= NULL
; break;
214 memset( &aEmpty
, 0, sizeof( SbxValues
) );
215 aEmpty
.eType
= GetType();
223 void SbxValue::Broadcast( sal_uIntPtr
)
226 //////////////////////////// Readout data
228 // Detect the "right" variables. If it is an object, will be addressed either
229 // the object itself or its default property.
230 // If the variable contain a variable or an object, this will be
233 SbxValue
* SbxValue::TheRealValue() const
235 return TheRealValue( true );
238 SbxValue
* SbxValue::TheRealValue( bool bObjInObjError
) const
240 SbxValue
* p
= const_cast<SbxValue
*>(this);
243 SbxDataType t
= SbxDataType( p
->aData
.eType
& 0x0FFF );
246 // The block contains an object or a variable
247 SbxObject
* pObj
= PTR_CAST(SbxObject
,p
->aData
.pObj
);
250 // Has the object a default property?
251 SbxVariable
* pDflt
= pObj
->GetDfltProperty();
253 // If this is an object and contains itself,
254 // we cannot access on it
255 // The old condition to set an error is not correct,
256 // because e.g. a regular variant variable with an object
257 // could be affected if another value should be assigned.
258 // Therefore with flag.
259 if( bObjInObjError
&& !pDflt
&&
260 ((SbxValue
*) pObj
)->aData
.eType
== SbxOBJECT
&&
261 ((SbxValue
*) pObj
)->aData
.pObj
== pObj
)
263 #if !HAVE_FEATURE_SCRIPTING
264 const bool bSuccess
= false;
266 bool bSuccess
= handleToStringForCOMObjects( pObj
, p
);
270 SetError( SbxERR_BAD_PROP_VALUE
);
278 // Did we have an array?
279 SbxArray
* pArray
= PTR_CAST(SbxArray
,p
->aData
.pObj
);
282 // When indicated get the parameter
283 SbxArray
* pPar
= NULL
;
284 SbxVariable
* pVar
= PTR_CAST(SbxVariable
,p
);
286 pPar
= pVar
->GetParameters();
289 // Did we have a dimensioned array?
290 SbxDimArray
* pDimArray
= PTR_CAST(SbxDimArray
,p
->aData
.pObj
);
292 p
= pDimArray
->Get( pPar
);
294 p
= pArray
->Get( pPar
->Get( 1 )->GetInteger() );
298 // Otherwise guess a SbxValue
299 SbxValue
* pVal
= PTR_CAST(SbxValue
,p
->aData
.pObj
);
311 bool SbxValue::Get( SbxValues
& rRes
) const
314 SbxError eOld
= GetError();
315 if( eOld
!= SbxERR_OK
)
319 SetError( SbxERR_PROP_WRITEONLY
);
324 // If an object or a VARIANT is requested, don't search the real values
325 SbxValue
* p
= const_cast<SbxValue
*>(this);
326 if( rRes
.eType
!= SbxOBJECT
&& rRes
.eType
!= SbxVARIANT
)
330 p
->Broadcast( SBX_HINT_DATAWANTED
);
336 case SbxVARIANT
: rRes
= p
->aData
; break;
337 case SbxINTEGER
: rRes
.nInteger
= ImpGetInteger( &p
->aData
); break;
338 case SbxLONG
: rRes
.nLong
= ImpGetLong( &p
->aData
); break;
339 case SbxSALINT64
: rRes
.nInt64
= ImpGetInt64( &p
->aData
); break;
340 case SbxSALUINT64
: rRes
.uInt64
= ImpGetUInt64( &p
->aData
); break;
341 case SbxSINGLE
: rRes
.nSingle
= ImpGetSingle( &p
->aData
); break;
342 case SbxDOUBLE
: rRes
.nDouble
= ImpGetDouble( &p
->aData
); break;
343 case SbxCURRENCY
:rRes
.nInt64
= ImpGetCurrency( &p
->aData
); break;
344 case SbxDECIMAL
: rRes
.pDecimal
= ImpGetDecimal( &p
->aData
); break;
345 case SbxDATE
: rRes
.nDouble
= ImpGetDate( &p
->aData
); break;
347 rRes
.nUShort
= sal::static_int_cast
< sal_uInt16
>(
348 ImpGetBool( &p
->aData
) );
350 case SbxCHAR
: rRes
.nChar
= ImpGetChar( &p
->aData
); break;
351 case SbxBYTE
: rRes
.nByte
= ImpGetByte( &p
->aData
); break;
352 case SbxUSHORT
: rRes
.nUShort
= ImpGetUShort( &p
->aData
); break;
353 case SbxULONG
: rRes
.nULong
= ImpGetULong( &p
->aData
); break;
355 case SbxSTRING
: p
->aPic
= ImpGetString( &p
->aData
);
356 rRes
.pOUString
= &p
->aPic
; break;
357 case SbxCoreSTRING
: p
->aPic
= ImpGetCoreString( &p
->aData
);
358 rRes
.pOUString
= &p
->aPic
; break;
360 #if SAL_TYPES_SIZEOFINT == 2
361 rRes
.nInt
= (int) ImpGetInteger( &p
->aData
);
363 rRes
.nInt
= (int) ImpGetLong( &p
->aData
);
367 #if SAL_TYPES_SIZEOFINT == 2
368 rRes
.nUInt
= (int) ImpGetUShort( &p
->aData
);
370 rRes
.nUInt
= (int) ImpGetULong( &p
->aData
);
374 if( p
->aData
.eType
== SbxOBJECT
)
375 rRes
.pObj
= p
->aData
.pObj
;
378 SetError( SbxERR_NO_OBJECT
);
383 if( p
->aData
.eType
== rRes
.eType
)
387 SetError( SbxERR_CONVERSION
);
394 // Object contained itself
395 SbxDataType eTemp
= rRes
.eType
;
396 memset( &rRes
, 0, sizeof( SbxValues
) );
403 if( eOld
!= SbxERR_OK
)
409 const OUString
& SbxValue::GetCoreString() const
412 aRes
.eType
= SbxCoreSTRING
;
415 const_cast<SbxValue
*>(this)->aToolString
= *aRes
.pOUString
;
419 const_cast<SbxValue
*>(this)->aToolString
.clear();
424 OUString
SbxValue::GetOUString() const
428 aRes
.eType
= SbxSTRING
;
431 aResult
= *aRes
.pOUString
;
436 bool SbxValue::GetBool() const
439 aRes
.eType
= SbxBOOL
;
441 return aRes
.nUShort
!= 0;
444 #define GET( g, e, t, m ) \
445 t SbxValue::g() const { SbxValues aRes(e); Get( aRes ); return aRes.m; }
447 GET( GetByte
, SbxBYTE
, sal_uInt8
, nByte
)
448 GET( GetChar
, SbxCHAR
, sal_Unicode
, nChar
)
449 GET( GetCurrency
, SbxCURRENCY
, sal_Int64
, nInt64
)
450 GET( GetDate
, SbxDATE
, double, nDouble
)
451 GET( GetDouble
, SbxDOUBLE
, double, nDouble
)
452 GET( GetInteger
, SbxINTEGER
, sal_Int16
, nInteger
)
453 GET( GetLong
, SbxLONG
, sal_Int32
, nLong
)
454 GET( GetObject
, SbxOBJECT
, SbxBase
*, pObj
)
455 GET( GetSingle
, SbxSINGLE
, float, nSingle
)
456 GET( GetULong
, SbxULONG
, sal_uInt32
, nULong
)
457 GET( GetUShort
, SbxUSHORT
, sal_uInt16
, nUShort
)
458 GET( GetInt64
, SbxSALINT64
, sal_Int64
, nInt64
)
459 GET( GetUInt64
, SbxSALUINT64
, sal_uInt64
, uInt64
)
460 GET( GetDecimal
, SbxDECIMAL
, SbxDecimal
*, pDecimal
)
463 //////////////////////////// Write data
465 bool SbxValue::Put( const SbxValues
& rVal
)
468 SbxError eOld
= GetError();
469 if( eOld
!= SbxERR_OK
)
472 SetError( SbxERR_PROP_READONLY
);
473 else if( rVal
.eType
& 0xF000 )
474 SetError( SbxERR_NOTIMP
);
477 // If an object is requested, don't search the real values
479 if( rVal
.eType
!= SbxOBJECT
)
480 p
= TheRealValue( false ); // Don't allow an error here
484 SetError( SbxERR_PROP_READONLY
);
485 else if( p
->IsFixed() || p
->SetType( (SbxDataType
) ( rVal
.eType
& 0x0FFF ) ) )
486 switch( rVal
.eType
& 0x0FFF )
491 case SbxINTEGER
: ImpPutInteger( &p
->aData
, rVal
.nInteger
); break;
492 case SbxLONG
: ImpPutLong( &p
->aData
, rVal
.nLong
); break;
493 case SbxSALINT64
: ImpPutInt64( &p
->aData
, rVal
.nInt64
); break;
494 case SbxSALUINT64
: ImpPutUInt64( &p
->aData
, rVal
.uInt64
); break;
495 case SbxSINGLE
: ImpPutSingle( &p
->aData
, rVal
.nSingle
); break;
496 case SbxDOUBLE
: ImpPutDouble( &p
->aData
, rVal
.nDouble
); break;
497 case SbxCURRENCY
: ImpPutCurrency( &p
->aData
, rVal
.nInt64
); break;
498 case SbxDECIMAL
: ImpPutDecimal( &p
->aData
, rVal
.pDecimal
); break;
499 case SbxDATE
: ImpPutDate( &p
->aData
, rVal
.nDouble
); break;
500 case SbxBOOL
: ImpPutBool( &p
->aData
, rVal
.nInteger
); break;
501 case SbxCHAR
: ImpPutChar( &p
->aData
, rVal
.nChar
); break;
502 case SbxBYTE
: ImpPutByte( &p
->aData
, rVal
.nByte
); break;
503 case SbxUSHORT
: ImpPutUShort( &p
->aData
, rVal
.nUShort
); break;
504 case SbxULONG
: ImpPutULong( &p
->aData
, rVal
.nULong
); break;
506 case SbxSTRING
: ImpPutString( &p
->aData
, rVal
.pOUString
); break;
508 #if SAL_TYPES_SIZEOFINT == 2
509 ImpPutInteger( &p
->aData
, (sal_Int16
) rVal
.nInt
);
511 ImpPutLong( &p
->aData
, (sal_Int32
) rVal
.nInt
);
515 #if SAL_TYPES_SIZEOFINT == 2
516 ImpPutUShort( &p
->aData
, (sal_uInt16
) rVal
.nUInt
);
518 ImpPutULong( &p
->aData
, (sal_uInt32
) rVal
.nUInt
);
522 if( !p
->IsFixed() || p
->aData
.eType
== SbxOBJECT
)
525 if( p
->aData
.eType
== SbxOBJECT
&& p
->aData
.pObj
== rVal
.pObj
)
528 // Delete only the value part!
529 p
->SbxValue::Clear();
532 p
->aData
.pObj
= rVal
.pObj
;
534 // if necessary increment Ref-Count
535 if( p
->aData
.pObj
&& p
->aData
.pObj
!= p
)
539 OSL_FAIL( "TheRealValue" );
541 SAL_INFO("basic.sbx", "Not at Parent-Prop - otherwise CyclicRef");
542 SbxVariable
*pThisVar
= PTR_CAST(SbxVariable
, this);
543 bool bParentProp
= pThisVar
&& 5345 ==
544 ( (sal_Int16
) ( pThisVar
->GetUserData() & 0xFFFF ) );
546 p
->aData
.pObj
->AddFirstRef();
550 SetError( SbxERR_CONVERSION
);
553 if( p
->aData
.eType
== rVal
.eType
)
557 SetError( SbxERR_CONVERSION
);
559 p
->aData
.eType
= SbxNULL
;
564 p
->SetModified( true );
565 p
->Broadcast( SBX_HINT_DATACHANGED
);
566 if( eOld
!= SbxERR_OK
)
576 // Method to execute a pretreatment of the strings at special types.
577 // In particular necessary for BASIC-IDE, so that
578 // the output in the Watch-Window can be written back with PutStringExt,
579 // if Float were declared with ',' as the decimal separator or BOOl
580 // explicit with "TRUE" or "FALSE".
581 // Implementation in ImpConvStringExt (SBXSCAN.CXX)
582 bool SbxValue::PutStringExt( const OUString
& r
)
584 // Copy; if it is Unicode convert it immediately
587 // Identify the own type (not as in Put() with TheRealValue(),
588 // Objects are not handled anyway)
589 SbxDataType eTargetType
= SbxDataType( aData
.eType
& 0x0FFF );
591 // tinker a Source-Value
593 aRes
.eType
= SbxSTRING
;
595 // Only if really something was converted, take the copy,
596 // otherwise take the original (Unicode remains)
598 if( ImpConvStringExt( aStr
, eTargetType
) )
599 aRes
.pOUString
= &aStr
;
601 aRes
.pOUString
= const_cast<OUString
*>(&r
);
603 // #34939: For Strings which contain a number, and if this has a Num-Type,
604 // set a Fixed flag so that the type will not be changed
605 SbxFlagBits nFlags_
= GetFlags();
606 if( ( eTargetType
>= SbxINTEGER
&& eTargetType
<= SbxCURRENCY
) ||
607 ( eTargetType
>= SbxCHAR
&& eTargetType
<= SbxUINT
) ||
608 eTargetType
== SbxBOOL
)
612 if( aVal
.IsNumeric() )
613 SetFlag( SBX_FIXED
);
617 bRet
= bool( !IsError() );
619 // If FIXED resulted in an error, set it back
620 // (UI-Action should not result in an error, but simply fail)
628 bool SbxValue::PutBool( bool b
)
631 aRes
.eType
= SbxBOOL
;
632 aRes
.nUShort
= sal::static_int_cast
< sal_uInt16
>(b
? SbxTRUE
: SbxFALSE
);
637 bool SbxValue::PutEmpty()
639 bool bRet
= SetType( SbxEMPTY
);
644 bool SbxValue::PutNull()
646 bool bRet
= SetType( SbxNULL
);
653 // Special decimal methods
654 bool SbxValue::PutDecimal( com::sun::star::bridge::oleautomation::Decimal
& rAutomationDec
)
657 aData
.pDecimal
= new SbxDecimal( rAutomationDec
);
658 aData
.pDecimal
->addRef();
659 aData
.eType
= SbxDECIMAL
;
663 bool SbxValue::fillAutomationDecimal
664 ( com::sun::star::bridge::oleautomation::Decimal
& rAutomationDec
) const
666 SbxDecimal
* pDecimal
= GetDecimal();
667 if( pDecimal
!= NULL
)
669 pDecimal
->fillAutomationDecimal( rAutomationDec
);
676 bool SbxValue::PutString( const OUString
& r
)
679 aRes
.eType
= SbxSTRING
;
680 aRes
.pOUString
= const_cast<OUString
*>(&r
);
686 #define PUT( p, e, t, m ) \
687 bool SbxValue::p( t n ) \
688 { SbxValues aRes(e); aRes.m = n; Put( aRes ); return !IsError(); }
690 PUT( PutByte
, SbxBYTE
, sal_uInt8
, nByte
)
691 PUT( PutChar
, SbxCHAR
, sal_Unicode
, nChar
)
692 PUT( PutCurrency
, SbxCURRENCY
, const sal_Int64
&, nInt64
)
693 PUT( PutDate
, SbxDATE
, double, nDouble
)
694 PUT( PutDouble
, SbxDOUBLE
, double, nDouble
)
695 PUT( PutErr
, SbxERROR
, sal_uInt16
, nUShort
)
696 PUT( PutInteger
, SbxINTEGER
, sal_Int16
, nInteger
)
697 PUT( PutLong
, SbxLONG
, sal_Int32
, nLong
)
698 PUT( PutObject
, SbxOBJECT
, SbxBase
*, pObj
)
699 PUT( PutSingle
, SbxSINGLE
, float, nSingle
)
700 PUT( PutULong
, SbxULONG
, sal_uInt32
, nULong
)
701 PUT( PutUShort
, SbxUSHORT
, sal_uInt16
, nUShort
)
702 PUT( PutInt64
, SbxSALINT64
, sal_Int64
, nInt64
)
703 PUT( PutUInt64
, SbxSALUINT64
, sal_uInt64
, uInt64
)
704 PUT( PutDecimal
, SbxDECIMAL
, SbxDecimal
*, pDecimal
)
706 ////////////////////////// Setting of the data type
708 bool SbxValue::IsFixed() const
710 return ((GetFlags() & SBX_FIXED
) != SBX_NONE
) || ((aData
.eType
& SbxBYREF
) != 0);
713 // A variable is numeric, if it is EMPTY or really numeric
714 // or if it contains a complete convertible String
716 // #41692, implement it for RTL and Basic-Core separately
717 bool SbxValue::IsNumeric() const
719 return ImpIsNumeric( /*bOnlyIntntl*/false );
722 bool SbxValue::IsNumericRTL() const
724 return ImpIsNumeric( /*bOnlyIntntl*/true );
727 bool SbxValue::ImpIsNumeric( bool bOnlyIntntl
) const
732 SetError( SbxERR_PROP_WRITEONLY
);
736 if( this->ISA(SbxVariable
) )
737 const_cast<SbxVariable
*>(static_cast<const SbxVariable
*>(this))->Broadcast( SBX_HINT_DATAWANTED
);
738 SbxDataType t
= GetType();
741 if( aData
.pOUString
)
743 OUString
s( *aData
.pOUString
);
747 if( ImpScan( s
, n
, t2
, &nLen
, /*bAllowIntntl*/false, bOnlyIntntl
) == SbxERR_OK
)
748 return nLen
== s
.getLength();
754 || ( t
>= SbxINTEGER
&& t
<= SbxCURRENCY
)
755 || ( t
>= SbxCHAR
&& t
<= SbxUINT
);
758 SbxClassType
SbxValue::GetClass() const
760 return SbxCLASS_VALUE
;
763 SbxDataType
SbxValue::GetType() const
765 return SbxDataType( aData
.eType
& 0x0FFF );
769 bool SbxValue::SetType( SbxDataType t
)
771 DBG_ASSERT( !( t
& 0xF000 ), "SetType of BYREF|ARRAY is forbidden!" );
772 if( ( t
== SbxEMPTY
&& aData
.eType
== SbxVOID
)
773 || ( aData
.eType
== SbxEMPTY
&& t
== SbxVOID
) )
775 if( ( t
& 0x0FFF ) == SbxVARIANT
)
777 // Try to set the data type to Variant
778 ResetFlag( SBX_FIXED
);
781 SetError( SbxERR_CONVERSION
);
786 if( ( t
& 0x0FFF ) != ( aData
.eType
& 0x0FFF ) )
788 if( !CanWrite() || IsFixed() )
790 SetError( SbxERR_CONVERSION
);
795 // De-allocate potential objects
796 switch( aData
.eType
)
799 delete aData
.pOUString
;
802 if( aData
.pObj
&& aData
.pObj
!= this )
804 SAL_WARN("basic.sbx", "Not at Parent-Prop - otherwise CyclicRef");
805 SbxVariable
*pThisVar
= PTR_CAST(SbxVariable
, this);
806 sal_uInt16 nSlotId
= pThisVar
807 ? ( (sal_Int16
) ( pThisVar
->GetUserData() & 0xFFFF ) )
809 DBG_ASSERT( nSlotId
!= 5345 || pThisVar
->GetName() == "Parent",
810 "SID_PARENTOBJECT is not named 'Parent'" );
811 bool bParentProp
= 5345 == nSlotId
;
813 aData
.pObj
->ReleaseRef();
818 // This works always, because the Float representations are 0 as well.
819 memset( &aData
, 0, sizeof( SbxValues
) );
826 bool SbxValue::Convert( SbxDataType eTo
)
828 eTo
= SbxDataType( eTo
& 0x0FFF );
829 if( ( aData
.eType
& 0x0FFF ) == eTo
)
833 if( eTo
== SbxVARIANT
)
835 // Trial to set the data type to Variant
836 ResetFlag( SBX_FIXED
);
839 SetError( SbxERR_CONVERSION
);
845 // Converting from null doesn't work. Once null, always null!
846 if( aData
.eType
== SbxNULL
)
848 SetError( SbxERR_CONVERSION
);
852 // Conversion of the data:
857 // The data type could be converted. It ends here with fixed elements,
858 // because the data had not to be taken over
865 Broadcast( SBX_HINT_CONVERTED
);
871 ////////////////////////////////// Calculating
873 bool SbxValue::Compute( SbxOperator eOp
, const SbxValue
& rOp
)
875 #if !HAVE_FEATURE_SCRIPTING
876 const bool bVBAInterop
= false;
878 bool bVBAInterop
= SbiRuntime::isVBAEnabled();
880 SbxDataType eThisType
= GetType();
881 SbxDataType eOpType
= rOp
.GetType();
882 SbxError eOld
= GetError();
883 if( eOld
!= SbxERR_OK
)
886 SetError( SbxERR_PROP_READONLY
);
887 else if( !rOp
.CanRead() )
888 SetError( SbxERR_PROP_WRITEONLY
);
889 // Special rule 1: If one operand is null, the result is null
890 else if( eThisType
== SbxNULL
|| eOpType
== SbxNULL
)
892 // Special rule 2: If the operand is Empty, the result is the 2. operand
893 else if( eThisType
== SbxEMPTY
897 // 1996-2-13: Don't test for SbxEMPTY before Get
901 bool bDecimal
= false;
902 if( bVBAInterop
&& ( ( eThisType
== SbxSTRING
&& eOpType
!= SbxSTRING
&& eOpType
!= SbxEMPTY
) ||
903 ( eThisType
!= SbxSTRING
&& eThisType
!= SbxEMPTY
&& eOpType
== SbxSTRING
) ) &&
904 ( eOp
== SbxMUL
|| eOp
== SbxDIV
|| eOp
== SbxPLUS
|| eOp
== SbxMINUS
) )
908 else if( eThisType
== SbxSTRING
|| eOp
== SbxCAT
|| ( bVBAInterop
&& ( eOpType
== SbxSTRING
) && ( eOp
== SbxPLUS
) ) )
910 if( eOp
== SbxCAT
|| eOp
== SbxPLUS
)
912 // From 1999-11-5, keep OUString in mind
913 aL
.eType
= aR
.eType
= SbxSTRING
;
915 // From 1999-12-8, #70399: Here call GetType() again, Get() can change the type!
916 if( rOp
.GetType() == SbxEMPTY
)
920 // #30576: To begin with test, if the conversion worked
921 if( aL
.pOUString
!= NULL
&& aR
.pOUString
!= NULL
)
923 *aL
.pOUString
+= *aR
.pOUString
;
926 else if( aL
.pOUString
== NULL
)
928 aL
.pOUString
= new OUString();
933 SetError( SbxERR_CONVERSION
);
935 else if( eOpType
== SbxSTRING
&& rOp
.IsFixed() )
936 { // Numeric: there is no String allowed on the right side
937 SetError( SbxERR_CONVERSION
);
938 // falls all the way out
940 else if( ( eOp
>= SbxIDIV
&& eOp
<= SbxNOT
) || eOp
== SbxMOD
)
942 if( GetType() == eOpType
)
944 if( GetType() == SbxSALUINT64
|| GetType() == SbxSALINT64
945 || GetType() == SbxCURRENCY
|| GetType() == SbxULONG
)
946 aL
.eType
= aR
.eType
= GetType();
947 else if ( bVBAInterop
&& eOpType
== SbxBOOL
)
948 aL
.eType
= aR
.eType
= SbxBOOL
;
950 aL
.eType
= aR
.eType
= SbxLONG
;
953 aL
.eType
= aR
.eType
= SbxLONG
;
955 if( rOp
.Get( aR
) ) // re-do Get after type assigns above
957 if( rOp
.GetType() == SbxEMPTY
)
959 if ( !bVBAInterop
|| ( bVBAInterop
&& ( eOp
!= SbxNOT
) ) )
962 if( Get( aL
) ) switch( eOp
)
965 if( aL
.eType
== SbxCURRENCY
)
966 if( !aR
.nInt64
) SetError( SbxERR_ZERODIV
);
968 aL
.nInt64
/= aR
.nInt64
;
969 aL
.nInt64
*= CURRENCY_FACTOR
;
971 else if( aL
.eType
== SbxSALUINT64
)
972 if( !aR
.uInt64
) SetError( SbxERR_ZERODIV
);
973 else aL
.uInt64
/= aR
.uInt64
;
974 else if( aL
.eType
== SbxSALINT64
)
975 if( !aR
.nInt64
) SetError( SbxERR_ZERODIV
);
976 else aL
.nInt64
/= aR
.nInt64
;
977 else if( aL
.eType
== SbxLONG
)
978 if( !aR
.nLong
) SetError( SbxERR_ZERODIV
);
979 else aL
.nLong
/= aR
.nLong
;
981 if( !aR
.nULong
) SetError( SbxERR_ZERODIV
);
982 else aL
.nULong
/= aR
.nULong
;
985 if( aL
.eType
== SbxCURRENCY
|| aL
.eType
== SbxSALINT64
)
986 if( !aR
.nInt64
) SetError( SbxERR_ZERODIV
);
987 else aL
.nInt64
%= aR
.nInt64
;
988 else if( aL
.eType
== SbxSALUINT64
)
989 if( !aR
.uInt64
) SetError( SbxERR_ZERODIV
);
990 else aL
.uInt64
%= aR
.uInt64
;
991 else if( aL
.eType
== SbxLONG
)
992 if( !aR
.nLong
) SetError( SbxERR_ZERODIV
);
993 else aL
.nLong
%= aR
.nLong
;
995 if( !aR
.nULong
) SetError( SbxERR_ZERODIV
);
996 else aL
.nULong
%= aR
.nULong
;
999 if( aL
.eType
!= SbxLONG
&& aL
.eType
!= SbxULONG
)
1000 aL
.nInt64
&= aR
.nInt64
;
1002 aL
.nLong
&= aR
.nLong
;
1005 if( aL
.eType
!= SbxLONG
&& aL
.eType
!= SbxULONG
)
1006 aL
.nInt64
|= aR
.nInt64
;
1008 aL
.nLong
|= aR
.nLong
;
1011 if( aL
.eType
!= SbxLONG
&& aL
.eType
!= SbxULONG
)
1012 aL
.nInt64
^= aR
.nInt64
;
1014 aL
.nLong
^= aR
.nLong
;
1017 if( aL
.eType
!= SbxLONG
&& aL
.eType
!= SbxULONG
)
1018 aL
.nInt64
= (aL
.nInt64
& aR
.nInt64
) | (~aL
.nInt64
& ~aR
.nInt64
);
1020 aL
.nLong
= (aL
.nLong
& aR
.nLong
) | (~aL
.nLong
& ~aR
.nLong
);
1023 if( aL
.eType
!= SbxLONG
&& aL
.eType
!= SbxULONG
)
1024 aL
.nInt64
= ~aL
.nInt64
| aR
.nInt64
;
1026 aL
.nLong
= ~aL
.nLong
| aR
.nLong
;
1029 if( aL
.eType
!= SbxLONG
&& aL
.eType
!= SbxULONG
)
1031 if ( aL
.eType
!= SbxBOOL
)
1032 aL
.nInt64
= ~aL
.nInt64
;
1034 aL
.nLong
= ~aL
.nLong
;
1037 aL
.nLong
= ~aL
.nLong
;
1043 else if( ( GetType() == SbxDECIMAL
|| rOp
.GetType() == SbxDECIMAL
)
1044 && ( eOp
== SbxMUL
|| eOp
== SbxDIV
|| eOp
== SbxPLUS
|| eOp
== SbxMINUS
|| eOp
== SbxNEG
) )
1046 aL
.eType
= aR
.eType
= SbxDECIMAL
;
1050 if( rOp
.GetType() == SbxEMPTY
)
1052 releaseDecimalPtr( aL
.pDecimal
);
1057 if( aL
.pDecimal
&& aR
.pDecimal
)
1063 bOk
= ( *(aL
.pDecimal
) *= *(aR
.pDecimal
) );
1066 if( aR
.pDecimal
->isZero() )
1067 SetError( SbxERR_ZERODIV
);
1069 bOk
= ( *(aL
.pDecimal
) /= *(aR
.pDecimal
) );
1072 bOk
= ( *(aL
.pDecimal
) += *(aR
.pDecimal
) );
1075 bOk
= ( *(aL
.pDecimal
) -= *(aR
.pDecimal
) );
1078 bOk
= ( aL
.pDecimal
->neg() );
1081 SetError( SbxERR_NOTIMP
);
1084 SetError( SbxERR_OVERFLOW
);
1088 SetError( SbxERR_CONVERSION
);
1093 else if( GetType() == SbxCURRENCY
|| rOp
.GetType() == SbxCURRENCY
)
1095 aL
.eType
= SbxCURRENCY
;
1096 aR
.eType
= SbxCURRENCY
;
1100 if( rOp
.GetType() == SbxEMPTY
)
1103 if( Get( aL
) ) switch( eOp
)
1107 // first overflow check: see if product will fit - test real value of product (hence 2 curr factors)
1108 dTest
= (double)aL
.nInt64
* (double)aR
.nInt64
/ (double)CURRENCY_FACTOR_SQUARE
;
1109 if( dTest
< SbxMINCURR
|| SbxMAXCURR
< dTest
)
1111 aL
.nInt64
= SAL_MAX_INT64
;
1112 if( dTest
< SbxMINCURR
) aL
.nInt64
= SAL_MIN_INT64
;
1113 SetError( SbxERR_OVERFLOW
);
1116 // second overflow check: see if unscaled product overflows - if so use doubles
1117 dTest
= (double)aL
.nInt64
* (double)aR
.nInt64
;
1118 if( dTest
< SAL_MIN_INT64
|| SAL_MAX_INT64
< dTest
)
1120 aL
.nInt64
= (sal_Int64
)( dTest
/ (double)CURRENCY_FACTOR
);
1123 // precise calc: multiply then scale back (move decimal pt)
1124 aL
.nInt64
*= aR
.nInt64
;
1125 aL
.nInt64
/= CURRENCY_FACTOR
;
1131 SetError( SbxERR_ZERODIV
);
1134 // first overflow check: see if quotient will fit - calc real value of quotient (curr factors cancel)
1135 dTest
= (double)aL
.nInt64
/ (double)aR
.nInt64
;
1136 if( dTest
< SbxMINCURR
|| SbxMAXCURR
< dTest
)
1138 SetError( SbxERR_OVERFLOW
);
1141 // second overflow check: see if scaled dividend overflows - if so use doubles
1142 dTest
= (double)aL
.nInt64
* (double)CURRENCY_FACTOR
;
1143 if( dTest
< SAL_MIN_INT64
|| SAL_MAX_INT64
< dTest
)
1145 aL
.nInt64
= (sal_Int64
)(dTest
/ (double)aR
.nInt64
);
1148 // precise calc: scale (move decimal pt) then divide
1149 aL
.nInt64
*= CURRENCY_FACTOR
;
1150 aL
.nInt64
/= aR
.nInt64
;
1154 dTest
= ( (double)aL
.nInt64
+ (double)aR
.nInt64
) / (double)CURRENCY_FACTOR
;
1155 if( dTest
< SbxMINCURR
|| SbxMAXCURR
< dTest
)
1157 SetError( SbxERR_OVERFLOW
);
1160 aL
.nInt64
+= aR
.nInt64
;
1164 dTest
= ( (double)aL
.nInt64
- (double)aR
.nInt64
) / (double)CURRENCY_FACTOR
;
1165 if( dTest
< SbxMINCURR
|| SbxMAXCURR
< dTest
)
1167 SetError( SbxERR_OVERFLOW
);
1170 aL
.nInt64
-= aR
.nInt64
;
1173 aL
.nInt64
= -aL
.nInt64
;
1176 SetError( SbxERR_NOTIMP
);
1182 { // other types and operators including Date, Double and Single
1183 aL
.eType
= aR
.eType
= SbxDOUBLE
;
1186 if( rOp
.GetType() == SbxEMPTY
)
1188 if ( !bVBAInterop
|| ( bVBAInterop
&& ( eOp
!= SbxNEG
) ) )
1196 aL
.nDouble
= pow( aL
.nDouble
, aR
.nDouble
);
1199 aL
.nDouble
*= aR
.nDouble
; break;
1201 if( !aR
.nDouble
) SetError( SbxERR_ZERODIV
);
1202 else aL
.nDouble
/= aR
.nDouble
; break;
1204 aL
.nDouble
+= aR
.nDouble
; break;
1206 aL
.nDouble
-= aR
.nDouble
; break;
1208 aL
.nDouble
= -aL
.nDouble
; break;
1210 SetError( SbxERR_NOTIMP
);
1212 // Date with "+" or "-" needs special handling that
1213 // forces the Date type. If the operation is '+' the
1214 // result is always a Date, if '-' the result is only
1215 // a Date if one of lhs or rhs ( but not both ) is already
1217 if( ( GetType() == SbxDATE
|| rOp
.GetType() == SbxDATE
) )
1219 if( eOp
== SbxPLUS
|| ( ( eOp
== SbxMINUS
) && ( GetType() != rOp
.GetType() ) ) )
1231 releaseDecimalPtr( aL
.pDecimal
);
1232 releaseDecimalPtr( aR
.pDecimal
);
1237 bool bRes
= !IsError();
1238 if( bRes
&& eOld
!= SbxERR_OK
)
1243 // The comparison routine deliver TRUE or FALSE.
1245 bool SbxValue::Compare( SbxOperator eOp
, const SbxValue
& rOp
) const
1247 #if !HAVE_FEATURE_SCRIPTING
1248 const bool bVBAInterop
= false;
1250 bool bVBAInterop
= SbiRuntime::isVBAEnabled();
1254 SbxError eOld
= GetError();
1255 if( eOld
!= SbxERR_OK
)
1257 if( !CanRead() || !rOp
.CanRead() )
1258 SetError( SbxERR_PROP_WRITEONLY
);
1259 else if( GetType() == SbxNULL
&& rOp
.GetType() == SbxNULL
&& !bVBAInterop
)
1263 else if( GetType() == SbxEMPTY
&& rOp
.GetType() == SbxEMPTY
)
1264 bRes
= !bVBAInterop
|| ( eOp
== SbxEQ
);
1265 // Special rule 1: If an operand is null, the result is FALSE
1266 else if( GetType() == SbxNULL
|| rOp
.GetType() == SbxNULL
)
1268 // Special rule 2: If both are variant and one is numeric
1269 // and the other is a String, num is < str
1270 else if( !IsFixed() && !rOp
.IsFixed()
1271 && ( rOp
.GetType() == SbxSTRING
&& GetType() != SbxSTRING
&& IsNumeric() ) && !bVBAInterop
1273 bRes
= eOp
== SbxLT
|| eOp
== SbxLE
|| eOp
== SbxNE
;
1274 else if( !IsFixed() && !rOp
.IsFixed()
1275 && ( GetType() == SbxSTRING
&& rOp
.GetType() != SbxSTRING
&& rOp
.IsNumeric() )
1278 bRes
= eOp
== SbxGT
|| eOp
== SbxGE
|| eOp
== SbxNE
;
1282 // If one of the operands is a String,
1283 // a String comparing take place
1284 if( GetType() == SbxSTRING
|| rOp
.GetType() == SbxSTRING
)
1286 aL
.eType
= aR
.eType
= SbxSTRING
;
1287 if( Get( aL
) && rOp
.Get( aR
) ) switch( eOp
)
1290 bRes
= ( *aL
.pOUString
== *aR
.pOUString
); break;
1292 bRes
= ( *aL
.pOUString
!= *aR
.pOUString
); break;
1294 bRes
= ( *aL
.pOUString
< *aR
.pOUString
); break;
1296 bRes
= ( *aL
.pOUString
> *aR
.pOUString
); break;
1298 bRes
= ( *aL
.pOUString
<= *aR
.pOUString
); break;
1300 bRes
= ( *aL
.pOUString
>= *aR
.pOUString
); break;
1302 SetError( SbxERR_NOTIMP
);
1305 // From 1995-12-19: If SbxSINGLE participate, then convert to SINGLE,
1306 // otherwise it shows a numeric error
1307 else if( GetType() == SbxSINGLE
|| rOp
.GetType() == SbxSINGLE
)
1309 aL
.eType
= aR
.eType
= SbxSINGLE
;
1310 if( Get( aL
) && rOp
.Get( aR
) )
1314 bRes
= ( aL
.nSingle
== aR
.nSingle
); break;
1316 bRes
= ( aL
.nSingle
!= aR
.nSingle
); break;
1318 bRes
= ( aL
.nSingle
< aR
.nSingle
); break;
1320 bRes
= ( aL
.nSingle
> aR
.nSingle
); break;
1322 bRes
= ( aL
.nSingle
<= aR
.nSingle
); break;
1324 bRes
= ( aL
.nSingle
>= aR
.nSingle
); break;
1326 SetError( SbxERR_NOTIMP
);
1329 else if( GetType() == SbxDECIMAL
&& rOp
.GetType() == SbxDECIMAL
)
1331 aL
.eType
= aR
.eType
= SbxDECIMAL
;
1334 if( aL
.pDecimal
&& aR
.pDecimal
)
1336 SbxDecimal::CmpResult eRes
= compare( *aL
.pDecimal
, *aR
.pDecimal
);
1340 bRes
= ( eRes
== SbxDecimal::EQ
); break;
1342 bRes
= ( eRes
!= SbxDecimal::EQ
); break;
1344 bRes
= ( eRes
== SbxDecimal::LT
); break;
1346 bRes
= ( eRes
== SbxDecimal::GT
); break;
1348 bRes
= ( eRes
!= SbxDecimal::GT
); break;
1350 bRes
= ( eRes
!= SbxDecimal::LT
); break;
1352 SetError( SbxERR_NOTIMP
);
1357 SetError( SbxERR_CONVERSION
);
1359 releaseDecimalPtr( aL
.pDecimal
);
1360 releaseDecimalPtr( aR
.pDecimal
);
1362 // Everything else comparing on a SbxDOUBLE-Basis
1365 aL
.eType
= aR
.eType
= SbxDOUBLE
;
1366 bool bGetL
= Get( aL
);
1367 bool bGetR
= rOp
.Get( aR
);
1368 if( bGetL
&& bGetR
)
1372 bRes
= ( aL
.nDouble
== aR
.nDouble
); break;
1374 bRes
= ( aL
.nDouble
!= aR
.nDouble
); break;
1376 bRes
= ( aL
.nDouble
< aR
.nDouble
); break;
1378 bRes
= ( aL
.nDouble
> aR
.nDouble
); break;
1380 bRes
= ( aL
.nDouble
<= aR
.nDouble
); break;
1382 bRes
= ( aL
.nDouble
>= aR
.nDouble
); break;
1384 SetError( SbxERR_NOTIMP
);
1386 // at least one value was got
1387 // if this is VBA then a conversion error for one
1388 // side will yield a false result of an equality test
1389 else if ( bGetR
|| bGetL
)
1391 if ( bVBAInterop
&& eOp
== SbxEQ
&& GetError() == SbxERR_CONVERSION
)
1399 if( eOld
!= SbxERR_OK
)
1404 ///////////////////////////// Reading/Writing
1406 bool SbxValue::LoadData( SvStream
& r
, sal_uInt16
)
1408 // #TODO see if these types are really dumped to any stream
1409 // more than likely this is functionality used in the binfilter alone
1412 r
.ReadUInt16( nType
);
1413 aData
.eType
= SbxDataType( nType
);
1418 r
.ReadInt16( aData
.nInteger
); break;
1420 r
.ReadInt32( aData
.nLong
); break;
1424 OUString aVal
= read_uInt16_lenPrefixed_uInt8s_ToOUString(r
,
1425 RTL_TEXTENCODING_ASCII_US
);
1428 if( ImpScan( aVal
, d
, t
, NULL
) != SbxERR_OK
|| t
== SbxDOUBLE
)
1430 aData
.nSingle
= 0.0F
;
1433 aData
.nSingle
= (float) d
;
1440 OUString aVal
= read_uInt16_lenPrefixed_uInt8s_ToOUString(r
,
1441 RTL_TEXTENCODING_ASCII_US
);
1443 if( ImpScan( aVal
, aData
.nDouble
, t
, NULL
) != SbxERR_OK
)
1445 aData
.nDouble
= 0.0;
1451 r
.ReadInt64(aData
.nInt64
);
1454 r
.ReadUInt64( aData
.uInt64
);
1458 sal_uInt32 tmpHi
= 0;
1459 sal_uInt32 tmpLo
= 0;
1460 r
.ReadUInt32( tmpHi
).ReadUInt32( tmpLo
);
1461 aData
.nInt64
= ((sal_Int64
)tmpHi
<< 32);
1462 aData
.nInt64
|= (sal_Int64
)tmpLo
;
1467 OUString aVal
= read_uInt16_lenPrefixed_uInt8s_ToOUString(r
,
1468 RTL_TEXTENCODING_ASCII_US
);
1469 if( !aVal
.isEmpty() )
1470 aData
.pOUString
= new OUString( aVal
);
1472 aData
.pOUString
= NULL
; // JSM 1995-09-22
1477 r
.ReadUInt16( aData
.nUShort
); break;
1481 r
.ReadUChar( nMode
);
1488 aData
.pObj
= SbxBase::Load( r
);
1489 return ( aData
.pObj
!= NULL
);
1504 r
.ReadUChar( aData
.nByte
); break;
1506 r
.ReadUInt32( aData
.nULong
); break;
1511 // Match the Int on this system?
1512 if( n
> SAL_TYPES_SIZEOFINT
)
1513 r
.ReadInt32( aData
.nLong
), aData
.eType
= SbxLONG
;
1516 r
.ReadInt32( nInt
);
1525 // Match the UInt on this system?
1526 if( n
> SAL_TYPES_SIZEOFINT
)
1527 r
.ReadUInt32( aData
.nULong
), aData
.eType
= SbxULONG
;
1530 r
.ReadUInt32( nUInt
);
1531 aData
.nUInt
= nUInt
;
1540 r
.ReadInt32( aData
.nLong
);
1542 // #78919 For backwards compatibility
1547 memset (&aData
,0,sizeof(aData
));
1548 ResetFlag(SBX_FIXED
);
1549 aData
.eType
= SbxNULL
;
1550 DBG_ASSERT( false, "Loaded a non-supported data type" );
1557 bool SbxValue::StoreData( SvStream
& r
) const
1559 sal_uInt16 nType
= sal::static_int_cast
< sal_uInt16
>(aData
.eType
);
1560 r
.WriteUInt16( nType
);
1561 switch( nType
& 0x0FFF )
1565 r
.WriteInt16( aData
.nInteger
); break;
1567 r
.WriteInt32( aData
.nLong
); break;
1569 // #49935: Save as double, otherwise an error during the read in
1570 const_cast<SbxValue
*>(this)->aData
.eType
= (SbxDataType
)( ( nType
& 0xF000 ) | SbxDOUBLE
);
1571 write_uInt16_lenPrefixed_uInt8s_FromOUString(r
, GetCoreString(), RTL_TEXTENCODING_ASCII_US
);
1572 const_cast<SbxValue
*>(this)->aData
.eType
= (SbxDataType
)nType
;
1576 write_uInt16_lenPrefixed_uInt8s_FromOUString(r
, GetCoreString(), RTL_TEXTENCODING_ASCII_US
);
1580 // see comment in SbxValue::StoreData
1581 r
.WriteUInt64( aData
.uInt64
);
1585 sal_Int32 tmpHi
= ( (aData
.nInt64
>> 32) & 0xFFFFFFFF );
1586 sal_Int32 tmpLo
= ( sal_Int32
)aData
.nInt64
;
1587 r
.WriteInt32( tmpHi
).WriteInt32( tmpLo
);
1591 if( aData
.pOUString
)
1593 write_uInt16_lenPrefixed_uInt8s_FromOUString(r
, *aData
.pOUString
, RTL_TEXTENCODING_ASCII_US
);
1597 write_uInt16_lenPrefixed_uInt8s_FromOUString(r
, OUString(), RTL_TEXTENCODING_ASCII_US
);
1602 r
.WriteUInt16( aData
.nUShort
); break;
1604 // to save itself as Objectptr does not work!
1607 if( PTR_CAST(SbxValue
,aData
.pObj
) != this )
1610 return aData
.pObj
->Store( r
);
1620 char c
= sal::static_int_cast
< char >(aData
.nChar
);
1625 r
.WriteUChar( aData
.nByte
); break;
1627 r
.WriteUInt32( aData
.nULong
); break;
1630 sal_uInt8 n
= SAL_TYPES_SIZEOFINT
;
1631 r
.WriteUChar( n
).WriteInt32( aData
.nInt
);
1636 sal_uInt8 n
= SAL_TYPES_SIZEOFINT
;
1637 r
.WriteUChar( n
).WriteUInt32( aData
.nUInt
);
1645 r
.WriteInt32( aData
.nLong
);
1647 // #78919 For backwards compatibility
1652 DBG_ASSERT( false, "Saving a non-supported data type" );
1658 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */