1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_basic.hxx" 30 31 #include <basic/sbx.hxx> 32 #include <tools/errcode.hxx> 33 34 #define _TLBIGINT_INT64 35 #include <tools/bigint.hxx> 36 37 #include <basic/sbxvar.hxx> 38 #include "sbxconv.hxx" 39 40 static ::rtl::OUString ImpCurrencyToString( const SbxINT64& ); 41 static SbxINT64 ImpStringToCurrency( const ::rtl::OUString& ); 42 43 SbxINT64 ImpGetCurrency( const SbxValues* p ) 44 { 45 SbxValues aTmp; 46 SbxINT64 nRes; 47 start: 48 switch( +p->eType ) 49 { 50 case SbxNULL: 51 SbxBase::SetError( SbxERR_CONVERSION ); 52 case SbxEMPTY: 53 nRes.SetNull(); break; 54 case SbxCHAR: 55 nRes = ImpDoubleToCurrency( (double)p->nChar ); break; 56 case SbxBYTE: 57 nRes = ImpDoubleToCurrency( (double)p->nByte ); break; 58 case SbxINTEGER: 59 case SbxBOOL: 60 nRes = ImpDoubleToCurrency( (double)p->nInteger ); break; 61 case SbxERROR: 62 case SbxUSHORT: 63 nRes = ImpDoubleToCurrency( (double)p->nUShort ); break; 64 case SbxCURRENCY: 65 nRes = p->nLong64; break; 66 case SbxLONG: 67 nRes = ImpDoubleToCurrency( (double)p->nLong ); 68 break; 69 case SbxULONG: 70 nRes = ImpDoubleToCurrency( (double)p->nULong ); 71 break; 72 case SbxSALINT64: 73 nRes = ImpDoubleToCurrency( (double)p->nInt64 ); 74 break; 75 case SbxSALUINT64: 76 nRes = ImpDoubleToCurrency( ImpSalUInt64ToDouble( p->uInt64 ) ); 77 break; 78 case SbxSINGLE: 79 if( p->nSingle > SbxMAXCURR ) 80 { 81 SbxBase::SetError( SbxERR_OVERFLOW ); nRes.SetMax(); 82 } 83 else if( p->nSingle < SbxMINCURR ) 84 { 85 SbxBase::SetError( SbxERR_OVERFLOW ); nRes.SetMin(); 86 } 87 else 88 nRes = ImpDoubleToCurrency( (double)p->nSingle ); 89 break; 90 case SbxDATE: 91 case SbxDOUBLE: 92 if( p->nDouble > SbxMAXCURR ) 93 { 94 SbxBase::SetError( SbxERR_OVERFLOW ); nRes.SetMax(); 95 } 96 else if( p->nDouble < SbxMINCURR ) 97 { 98 SbxBase::SetError( SbxERR_OVERFLOW ); nRes.SetMin(); 99 } 100 else 101 nRes = ImpDoubleToCurrency( p->nDouble ); 102 break; 103 case SbxDECIMAL: 104 case SbxBYREF | SbxDECIMAL: 105 { 106 double d = 0.0; 107 if( p->pDecimal ) 108 p->pDecimal->getDouble( d ); 109 if( d > SbxMAXCURR ) 110 { 111 SbxBase::SetError( SbxERR_OVERFLOW ); nRes.SetMax(); 112 } 113 else if( d < SbxMINCURR ) 114 { 115 SbxBase::SetError( SbxERR_OVERFLOW ); nRes.SetMin(); 116 } 117 else 118 nRes = ImpDoubleToCurrency( d ); 119 break; 120 } 121 case SbxBYREF | SbxSTRING: 122 case SbxSTRING: 123 case SbxLPSTR: 124 if( !p->pOUString ) 125 nRes.SetNull(); 126 else 127 nRes = ImpStringToCurrency( *p->pOUString ); 128 break; 129 case SbxOBJECT: 130 { 131 SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); 132 if( pVal ) 133 nRes = pVal->GetCurrency(); 134 else 135 { 136 SbxBase::SetError( SbxERR_NO_OBJECT ); nRes.SetNull(); 137 } 138 break; 139 } 140 141 case SbxBYREF | SbxCHAR: 142 nRes = ImpDoubleToCurrency( (double)*p->pChar ); break; 143 case SbxBYREF | SbxBYTE: 144 nRes = ImpDoubleToCurrency( (double)*p->pByte ); break; 145 case SbxBYREF | SbxINTEGER: 146 case SbxBYREF | SbxBOOL: 147 nRes = ImpDoubleToCurrency( (double)*p->pInteger ); break; 148 case SbxBYREF | SbxERROR: 149 case SbxBYREF | SbxUSHORT: 150 nRes = ImpDoubleToCurrency( (double)*p->pUShort ); break; 151 case SbxBYREF | SbxCURRENCY: 152 nRes = *p->pLong64; break; 153 154 // ab hier muss getestet werden 155 case SbxBYREF | SbxLONG: 156 aTmp.nLong = *p->pLong; goto ref; 157 case SbxBYREF | SbxULONG: 158 aTmp.nULong = *p->pULong; goto ref; 159 case SbxBYREF | SbxSINGLE: 160 aTmp.nSingle = *p->pSingle; goto ref; 161 case SbxBYREF | SbxDATE: 162 case SbxBYREF | SbxDOUBLE: 163 aTmp.nDouble = *p->pDouble; goto ref; 164 case SbxBYREF | SbxSALINT64: 165 aTmp.nInt64 = *p->pnInt64; goto ref; 166 case SbxBYREF | SbxSALUINT64: 167 aTmp.uInt64 = *p->puInt64; goto ref; 168 ref: 169 aTmp.eType = SbxDataType( p->eType & 0x0FFF ); 170 p = &aTmp; goto start; 171 172 default: 173 SbxBase::SetError( SbxERR_CONVERSION ); nRes.SetNull(); 174 } 175 return nRes; 176 } 177 178 void ImpPutCurrency( SbxValues* p, const SbxINT64 &r ) 179 { 180 double dVal = ImpCurrencyToDouble( r ); 181 SbxValues aTmp; 182 start: 183 switch( +p->eType ) 184 { 185 // Hier sind Tests notwendig 186 case SbxCHAR: 187 aTmp.pChar = &p->nChar; goto direct; 188 case SbxBYTE: 189 aTmp.pByte = &p->nByte; goto direct; 190 case SbxINTEGER: 191 case SbxBOOL: 192 aTmp.pInteger = &p->nInteger; goto direct; 193 case SbxLONG: 194 aTmp.pLong = &p->nLong; goto direct; 195 case SbxULONG: 196 aTmp.pULong = &p->nULong; goto direct; 197 case SbxERROR: 198 case SbxUSHORT: 199 aTmp.pUShort = &p->nUShort; goto direct; 200 direct: 201 aTmp.eType = SbxDataType( p->eType | SbxBYREF ); 202 p = &aTmp; goto start; 203 204 // ab hier nicht mehr 205 case SbxSINGLE: 206 p->nSingle = (float)dVal; break; 207 case SbxDATE: 208 case SbxDOUBLE: 209 p->nDouble = dVal; break; 210 case SbxSALINT64: 211 p->nInt64 = ImpDoubleToSalInt64( dVal ); break; 212 case SbxSALUINT64: 213 p->uInt64 = ImpDoubleToSalUInt64( dVal ); break; 214 case SbxCURRENCY: 215 p->nLong64 = r; break; 216 case SbxDECIMAL: 217 case SbxBYREF | SbxDECIMAL: 218 { 219 SbxDecimal* pDec = ImpCreateDecimal( p ); 220 if( !pDec->setDouble( dVal ) ) 221 SbxBase::SetError( SbxERR_OVERFLOW ); 222 break; 223 } 224 case SbxBYREF | SbxSTRING: 225 case SbxSTRING: 226 case SbxLPSTR: 227 if( !p->pOUString ) 228 p->pOUString = new ::rtl::OUString; 229 230 *p->pOUString = ImpCurrencyToString( r ); 231 break; 232 case SbxOBJECT: 233 { 234 SbxValue* pVal = PTR_CAST(SbxValue,p->pObj); 235 if( pVal ) 236 pVal->PutCurrency( r ); 237 else 238 SbxBase::SetError( SbxERR_NO_OBJECT ); 239 break; 240 } 241 case SbxBYREF | SbxCHAR: 242 if( dVal > SbxMAXCHAR ) 243 { 244 SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMAXCHAR; 245 } 246 else if( dVal < SbxMINCHAR ) 247 { 248 SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMINCHAR; 249 } 250 *p->pChar = (xub_Unicode) dVal; break; 251 case SbxBYREF | SbxBYTE: 252 if( dVal > SbxMAXBYTE ) 253 { 254 SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMAXBYTE; 255 } 256 else if( dVal < 0 ) 257 { 258 SbxBase::SetError( SbxERR_OVERFLOW ); dVal = 0; 259 } 260 *p->pByte = (sal_uInt8) dVal; break; 261 case SbxBYREF | SbxINTEGER: 262 case SbxBYREF | SbxBOOL: 263 if( dVal > SbxMAXINT ) 264 { 265 SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMAXINT; 266 } 267 else if( dVal < SbxMININT ) 268 { 269 SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMININT; 270 } 271 *p->pInteger = (sal_Int16) dVal; break; 272 case SbxBYREF | SbxERROR: 273 case SbxBYREF | SbxUSHORT: 274 if( dVal > SbxMAXUINT ) 275 { 276 SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMAXUINT; 277 } 278 else if( dVal < 0 ) 279 { 280 SbxBase::SetError( SbxERR_OVERFLOW ); dVal = 0; 281 } 282 *p->pUShort = (sal_uInt16) dVal; break; 283 case SbxBYREF | SbxLONG: 284 if( dVal > SbxMAXLNG ) 285 { 286 SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMAXLNG; 287 } 288 else if( dVal < SbxMINLNG ) 289 { 290 SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMINLNG; 291 } 292 *p->pLong = (sal_Int32) dVal; break; 293 case SbxBYREF | SbxULONG: 294 if( dVal > SbxMAXULNG ) 295 { 296 SbxBase::SetError( SbxERR_OVERFLOW ); dVal = SbxMAXULNG; 297 } 298 else if( dVal < 0 ) 299 { 300 SbxBase::SetError( SbxERR_OVERFLOW ); dVal = 0; 301 } 302 *p->pULong = (sal_uInt32) dVal; break; 303 case SbxBYREF | SbxSALINT64: 304 *p->pnInt64 = ImpDoubleToSalInt64( dVal ); break; 305 case SbxBYREF | SbxSALUINT64: 306 *p->puInt64 = ImpDoubleToSalUInt64( dVal ); break; 307 case SbxBYREF | SbxSINGLE: 308 *p->pSingle = (float) dVal; break; 309 case SbxBYREF | SbxDATE: 310 case SbxBYREF | SbxDOUBLE: 311 *p->pDouble = (double) dVal; break; 312 case SbxBYREF | SbxCURRENCY: 313 *p->pLong64 = r; break; 314 315 default: 316 SbxBase::SetError( SbxERR_CONVERSION ); 317 } 318 } 319 320 // Hilfs-Funktionen zur Wandlung 321 322 static ::rtl::OUString ImpCurrencyToString( const SbxINT64 &r ) 323 { 324 BigInt a10000 = 10000; 325 326 //return GetpApp()->GetAppInternational().GetCurr( BigInt( r ), 4 ); 327 BigInt aInt( r ); 328 aInt.Abs(); 329 BigInt aFrac = aInt; 330 aInt /= a10000; 331 aFrac %= a10000; 332 aFrac += a10000; 333 334 ::rtl::OUString aString; 335 if( r.nHigh < 0 ) 336 aString = ::rtl::OUString( (sal_Unicode)'-' ); 337 aString += aInt.GetString(); 338 aString += ::rtl::OUString( (sal_Unicode)'.' ); 339 aString += aFrac.GetString().GetBuffer()+1; 340 return aString; 341 } 342 343 static SbxINT64 ImpStringToCurrency( const ::rtl::OUString &r ) 344 { 345 int nDec = 4; 346 String aStr; 347 const sal_Unicode* p = r.getStr(); 348 349 if( *p == '-' ) 350 aStr += *p++; 351 352 while( *p >= '0' && *p <= '9' ) { 353 aStr += *p++; 354 if( *p == ',' ) 355 p++; 356 } 357 358 if( *p == '.' ) { 359 p++; 360 while( nDec && *p >= '0' && *p <= '9' ) { 361 aStr += *p++; 362 nDec--; 363 } 364 } 365 while( nDec ) { 366 aStr += '0'; 367 nDec--; 368 } 369 370 BigInt aBig( aStr ); 371 SbxINT64 nRes; 372 aBig.INT64( &nRes ); 373 return nRes; 374 } 375 376 double ImpINT64ToDouble( const SbxINT64 &r ) 377 { return (double)r.nHigh*(double)4294967296.0 + (double)r.nLow; } 378 379 SbxINT64 ImpDoubleToINT64( double d ) 380 { 381 SbxINT64 nRes; 382 nRes.Set( d ); 383 return nRes; 384 } 385 386 double ImpUINT64ToDouble( const SbxUINT64 &r ) 387 { return (double)r.nHigh*(double)4294967296.0 + (double)r.nLow; } 388 389 SbxUINT64 ImpDoubleToUINT64( double d ) 390 { 391 SbxUINT64 nRes; 392 nRes.Set( d ); 393 return nRes; 394 } 395 396