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 .
23 #include <basic/sbxform.hxx>
24 #include <rtl/ustrbuf.hxx>
27 TODO: are there any Star-Basic characteristics unconsidered?
29 what means: * as placeholder
31 COMMENT: Visual-Basic treats the following (invalid) format-strings
34 ##0##.##0## --> ##000.000##
36 (this class behaves the same way)
39 #include <stdio.h> // for: sprintf()
40 #include <float.h> // for: DBL_DIG, DBL_EPSILON
41 #include <math.h> // for: floor(), fabs(), log10(), pow()
43 //=================================================================
44 //=========================== DEFINES =============================
45 //=================================================================
49 #define MAX_NO_OF_DIGITS DBL_DIG
50 #define MAX_DOUBLE_BUFFER_LENGTH MAX_NO_OF_DIGITS + 9
51 // +1 for leading sign
52 // +1 for digit before the decimal point
53 // +1 for decimal point
54 // +2 for exponent E and exp. leading sign
55 // +3 for the exponent's value
58 // Defines for the digits:
59 #define ASCII_0 '0' // 48
60 #define ASCII_9 '9' // 57
62 #define CREATE_1000SEP_CHAR '@'
64 #define FORMAT_SEPARATOR ';'
66 // predefined formats for the Format$()-command:
67 #define BASICFORMAT_GENERALNUMBER "General Number"
68 #define BASICFORMAT_CURRENCY "Currency"
69 #define BASICFORMAT_FIXED "Fixed"
70 #define BASICFORMAT_STANDARD "Standard"
71 #define BASICFORMAT_PERCENT "Percent"
72 #define BASICFORMAT_SCIENTIFIC "Scientific"
73 #define BASICFORMAT_YESNO "Yes/No"
74 #define BASICFORMAT_TRUEFALSE "True/False"
75 #define BASICFORMAT_ONOFF "On/Off"
77 #define EMPTYFORMATSTRING ""
79 // Comment: Visual-Basic has a maximum of 12 positions after the
80 // decimal point for floating-point-numbers.
81 // all format-strings are compatible to Visual-Basic:
82 #define GENERALNUMBER_FORMAT "0.############"
83 #define FIXED_FORMAT "0.00"
84 #define STANDARD_FORMAT "@0.00"
85 #define PERCENT_FORMAT "0.00%"
86 #define SCIENTIFIC_FORMAT "#.00E+00"
87 // Comment: the character @ means that thousand-separators shall
88 // be generated. That's a StarBasic 'extension'.
90 //=================================================================
93 double get_number_of_digits( double dNumber
)
94 //double floor_log10_fabs( double dNumber )
97 return 0.0; // used to be 1.0, now 0.0 because of #40025;
99 return floor( log10( fabs( dNumber
) ) );
102 //=================================================================
103 //======================= IMPLEMENTATION ==========================
104 //=================================================================
106 SbxBasicFormater::SbxBasicFormater( sal_Unicode _cDecPoint
, sal_Unicode _cThousandSep
,
112 OUString _sFalseStrg
,
113 OUString _sCurrencyStrg
,
114 OUString _sCurrencyFormatStrg
)
116 cDecPoint
= _cDecPoint
;
117 cThousandSep
= _cThousandSep
;
119 sOffStrg
= _sOffStrg
;
120 sYesStrg
= _sYesStrg
;
122 sTrueStrg
= _sTrueStrg
;
123 sFalseStrg
= _sFalseStrg
;
124 sCurrencyStrg
= _sCurrencyStrg
;
125 sCurrencyFormatStrg
= _sCurrencyFormatStrg
;
128 // function for ouput of a error-text (for debugging)
129 // displaces all characters of the string, starting from nStartPos
130 // for one position to larger indexes, i. e. place for a new
131 // character (which is to be inserted) is created.
132 // ATTENTION: the string MUST be long enough!
133 inline void SbxBasicFormater::ShiftString( OUStringBuffer
& sStrg
, sal_uInt16 nStartPos
)
135 sStrg
.remove(nStartPos
,1);
138 void SbxBasicFormater::AppendDigit( OUStringBuffer
& sStrg
, short nDigit
)
140 if( nDigit
>=0 && nDigit
<=9 )
142 sStrg
.append((sal_Unicode
)(nDigit
+ASCII_0
));
146 void SbxBasicFormater::LeftShiftDecimalPoint( OUStringBuffer
& sStrg
)
150 for(sal_Int32 i
= 0; i
< sStrg
.getLength(); i
++)
152 if(sStrg
[i
] == cDecPoint
)
160 sStrg
[nPos
] = sStrg
[nPos
- 1];
161 sStrg
[nPos
- 1] = cDecPoint
;
165 // returns a flag if rounding a 9
166 void SbxBasicFormater::StrRoundDigit( OUStringBuffer
& sStrg
, short nPos
, sal_Bool
& bOverflow
)
172 bOverflow
= sal_False
;
173 sal_Unicode c
= sStrg
[nPos
];
174 if( nPos
> 0 && (c
== cDecPoint
|| c
== cThousandSep
) )
176 StrRoundDigit( sStrg
, nPos
- 1, bOverflow
);
177 // CHANGE from 9.3.1997: end the method immediately after recursive call!
182 // in a valid format-string the number's output should be done
183 // in one piece, i. e. special characters should ONLY be in
184 // front OR behind the number and not right in the middle of
185 // the format information for the number
186 while( nPos
>= 0 && ( sStrg
[nPos
] < ASCII_0
|| sStrg
[nPos
] > ASCII_9
))
192 ShiftString( sStrg
, 0 );
193 sStrg
[0] = (sal_Unicode
)'1';
194 bOverflow
= sal_True
;
198 sal_Unicode c2
= sStrg
[nPos
];
199 if( c2
>= ASCII_0
&& c2
<= ASCII_9
)
203 sStrg
[nPos
] = (sal_Unicode
)'0';
204 StrRoundDigit( sStrg
, nPos
- 1, bOverflow
);
208 sStrg
[nPos
] = c2
+ 1;
213 ShiftString( sStrg
,nPos
+1 );
214 sStrg
[nPos
+ 1] = (sal_Unicode
)'1';
215 bOverflow
= sal_True
;
220 void SbxBasicFormater::StrRoundDigit( OUStringBuffer
& sStrg
, short nPos
)
224 StrRoundDigit( sStrg
, nPos
, bOverflow
);
227 void SbxBasicFormater::ParseBack( OUStringBuffer
& sStrg
, const OUString
& sFormatStrg
,
230 for( sal_Int32 i
= nFormatPos
;
231 i
>0 && sFormatStrg
[ i
] == (sal_Unicode
)'#' && sStrg
[sStrg
.getLength() - 1] == (sal_Unicode
)'0';
234 sStrg
.setLength(sStrg
.getLength() - 1 );
241 void SbxBasicFormater::InitScan( double _dNum
)
243 char sBuffer
[ MAX_DOUBLE_BUFFER_LENGTH
];
246 InitExp( get_number_of_digits( dNum
) );
247 // maximum of 15 positions behind the decimal point, example: -1.234000000000000E-001
248 /*int nCount =*/ sprintf( sBuffer
,"%+22.15lE",dNum
);
249 sSciNumStrg
= OUString::createFromAscii( sBuffer
);
253 void SbxBasicFormater::InitExp( double _dNewExp
)
255 char sBuffer
[ MAX_DOUBLE_BUFFER_LENGTH
];
256 nNumExp
= (short)_dNewExp
;
257 /*int nCount =*/ sprintf( sBuffer
,"%+i",nNumExp
);
258 sNumExpStrg
= OUString::createFromAscii( sBuffer
);
259 nExpExp
= (short)get_number_of_digits( (double)nNumExp
);
263 short SbxBasicFormater::GetDigitAtPosScan( short nPos
, sal_Bool
& bFoundFirstDigit
)
265 // trying to read a higher digit,
266 // e. g. position 4 in 1.234,
267 // or to read a digit outside of the
268 // number's dissolution (double)
269 if( nPos
>nNumExp
|| abs(nNumExp
-nPos
)>MAX_NO_OF_DIGITS
)
273 // determine the index of the position in the number-string:
274 // skip the leading sign
276 // skip the decimal point if necessary
280 // query of the number's first valid digit --> set flag
282 bFoundFirstDigit
= sal_True
;
283 return (short)(sSciNumStrg
[ no
] - ASCII_0
);
286 short SbxBasicFormater::GetDigitAtPosExpScan( short nPos
, sal_Bool
& bFoundFirstDigit
)
295 bFoundFirstDigit
= sal_True
;
296 return (short)(sNumExpStrg
[ no
] - ASCII_0
);
299 // a value for the exponent can be given because the number maybe shall
300 // not be displayed in a normed way (e. g. 1.2345e-03) but maybe 123.345e-3 !
301 short SbxBasicFormater::GetDigitAtPosExpScan( double dNewExponent
, short nPos
,
302 sal_Bool
& bFoundFirstDigit
)
304 InitExp( dNewExponent
);
306 return GetDigitAtPosExpScan( nPos
,bFoundFirstDigit
);
311 /* Problems with the following method:
313 TODO: an 'intelligent' peek-parser might be needed to detect rounding
314 mistakes at double-numbers - e. g. for 0.00115 #.#e-000
316 problem with: format( 0.3345 , "0.000" )
317 problem with: format( 0.00115 , "0.0000" )
320 // returns the digit at the given '10 system'-position,
321 // i. e. positive nPos for positions before the decimal
322 // point and negative for positions after.
323 // nPos==0 means first position after the decimalpoint, so 10^0.
324 // returns 0..9 for valid digits and -1 for not existing,
325 // i. e. if the passed number is too small
326 // (e. g. position 5 of dNumber=123).
327 // Furthermore in dNextNumber the number shorted by leading
328 // positions (till nPos) is returned, e. g.
329 // GetDigitAtPos( 3434.565 , 2 , dNewNumber ) --> dNewNumber = 434.565
330 // In bFoundFirstDigit a flag is set if a digit has been found,
331 // this is used to prevent 'errors' on parsing 202
332 // ATTENTION: apparently there are sometimes still problems with rounding mistakes!
333 short SbxBasicFormater::GetDigitAtPos( double dNumber
, short nPos
,
334 double& dNextNumber
, sal_Bool
& bFoundFirstDigit
)
339 dNumber
= fabs( dNumber
);
341 nMaxDigit
= (short)get_number_of_digits( dNumber
);
342 // error only at numbers > 0, i. e. for digits before
344 if( nMaxDigit
<nPos
&& !bFoundFirstDigit
&& nPos
>=0 )
347 bFoundFirstDigit
= sal_True
;
348 for( short i
=nMaxDigit
; i
>=nPos
; i
-- )
350 double dI
= (double)i
;
351 double dTemp1
= pow( 10.0,dI
);
353 dDigit
= floor( pow( 10.0,log10( fabs( dNumber
) )-dI
) );
354 dNumber
-= dTemp1
* dDigit
;
356 // for optimized loop run
357 dNextNumber
= dNumber
;
359 return RoundDigit( dDigit
);
363 short SbxBasicFormater::RoundDigit( double dNumber
)
365 if( dNumber
<0.0 || dNumber
>10.0 )
367 short nTempHigh
= (short)(dNumber
+0.5); // maybe floor( )
373 // Copies the respective part of the format-string, if existing, and returns it.
374 // So a new string is created, which has to be freed by the caller later.
375 OUString
SbxBasicFormater::GetPosFormatString( const OUString
& sFormatStrg
, sal_Bool
& bFound
)
377 bFound
= sal_False
; // default...
378 sal_Int32 nPos
= sFormatStrg
.indexOf( FORMAT_SEPARATOR
);
383 // the format-string for positive numbers is
384 // everything before the first ';'
385 return sFormatStrg
.copy( 0,nPos
);
389 aRetStr
= OUString::createFromAscii( EMPTYFORMATSTRING
);
393 // see also GetPosFormatString()
394 OUString
SbxBasicFormater::GetNegFormatString( const OUString
& sFormatStrg
, sal_Bool
& bFound
)
396 bFound
= sal_False
; // default...
397 sal_Int32 nPos
= sFormatStrg
.indexOf( FORMAT_SEPARATOR
);
401 // the format-string for negative numbers is
402 // everything between the first and the second ';'
403 OUString sTempStrg
= sFormatStrg
.copy( nPos
+1 );
404 nPos
= sTempStrg
.indexOf( FORMAT_SEPARATOR
);
412 return sTempStrg
.copy( 0,nPos
);
416 aRetStr
= OUString::createFromAscii( EMPTYFORMATSTRING
);
420 // see also GetPosFormatString()
421 OUString
SbxBasicFormater::Get0FormatString( const OUString
& sFormatStrg
, sal_Bool
& bFound
)
423 bFound
= sal_False
; // default...
424 sal_Int32 nPos
= sFormatStrg
.indexOf( FORMAT_SEPARATOR
);
428 // the format string for the zero is
429 // everything after the second ';'
430 OUString sTempStrg
= sFormatStrg
.copy( nPos
+1 );
431 nPos
= sTempStrg
.indexOf( FORMAT_SEPARATOR
);
435 sTempStrg
= sTempStrg
.copy( nPos
+1 );
436 nPos
= sTempStrg
.indexOf( FORMAT_SEPARATOR
);
443 return sTempStrg
.copy( 0,nPos
);
449 aRetStr
= OUString::createFromAscii( EMPTYFORMATSTRING
);
453 // see also GetPosFormatString()
454 OUString
SbxBasicFormater::GetNullFormatString( const OUString
& sFormatStrg
, sal_Bool
& bFound
)
456 bFound
= sal_False
; // default...
457 sal_Int32 nPos
= sFormatStrg
.indexOf( FORMAT_SEPARATOR
);
461 // the format-string for the Null is
462 // everything after the third ';'
463 OUString sTempStrg
= sFormatStrg
.copy( nPos
+1 );
464 nPos
= sTempStrg
.indexOf( FORMAT_SEPARATOR
);
467 sTempStrg
= sTempStrg
.copy( nPos
+1 );
468 nPos
= sTempStrg
.indexOf( FORMAT_SEPARATOR
);
472 return sTempStrg
.copy( nPos
+1 );
478 aRetStr
= OUString::createFromAscii( EMPTYFORMATSTRING
);
482 // returns value <> 0 in case of an error
483 short SbxBasicFormater::AnalyseFormatString( const OUString
& sFormatStrg
,
484 short& nNoOfDigitsLeft
, short& nNoOfDigitsRight
,
485 short& nNoOfOptionalDigitsLeft
,
486 short& nNoOfExponentDigits
, short& nNoOfOptionalExponentDigits
,
487 sal_Bool
& bPercent
, sal_Bool
& bCurrency
, sal_Bool
& bScientific
,
488 sal_Bool
& bGenerateThousandSeparator
,
489 short& nMultipleThousandSeparators
)
494 nLen
= sFormatStrg
.getLength();
496 nNoOfDigitsRight
= 0;
497 nNoOfOptionalDigitsLeft
= 0;
498 nNoOfExponentDigits
= 0;
499 nNoOfOptionalExponentDigits
= 0;
500 bPercent
= sal_False
;
501 bCurrency
= sal_False
;
502 bScientific
= sal_False
;
503 // from 11.7.97: as soon as a comma (point?) is found in the format string,
504 // all three decimal powers are marked (i. e. thousand, million, ...)
505 bGenerateThousandSeparator
= sFormatStrg
.indexOf( ',' ) >= 0;
506 nMultipleThousandSeparators
= 0;
508 for( sal_Int32 i
= 0; i
< nLen
; i
++ )
510 sal_Unicode c
= sFormatStrg
[ i
];
518 // TODO here maybe better error inspection of the mantissa for valid syntax (see grammar)h
519 // ATTENTION: 'undefined' behaviour if # and 0 are combined!
520 // REMARK: #-placeholders are actually useless for
521 // scientific display before the decimal point!
524 nNoOfOptionalDigitsLeft
++;
531 else if( nState
==-1 ) // search 0 in the exponent
533 if( c
=='#' ) // # switches on the condition
535 nNoOfOptionalExponentDigits
++;
538 nNoOfExponentDigits
++;
540 else if( nState
==-2 ) // search # in the exponent
544 // ERROR: 0 after # in the exponent is NOT allowed!!
547 nNoOfOptionalExponentDigits
++;
548 nNoOfExponentDigits
++;
555 return -1; // ERROR: too many decimal points
562 bCurrency
= sal_True
;
566 sal_Unicode ch
= sFormatStrg
[ i
+1 ];
568 if( ch
!=0 && (ch
==',' || ch
=='.') )
570 nMultipleThousandSeparators
++;
576 // #i13821 not when no digits before
577 if( nNoOfDigitsLeft
> 0 || nNoOfDigitsRight
> 0 )
579 nState
= -1; // abort counting digits
580 bScientific
= sal_True
;
583 // OWN command-character which turns on
584 // the creation of thousand-separators
589 case CREATE_1000SEP_CHAR
:
590 bGenerateThousandSeparator
= sal_True
;
597 // the flag bCreateSign says that at the mantissa a leading sign
599 void SbxBasicFormater::ScanFormatString( double dNumber
,
600 const OUString
& sFormatStrg
, OUString
& sReturnStrgFinal
,
601 sal_Bool bCreateSign
)
603 short /*nErr,*/nNoOfDigitsLeft
,nNoOfDigitsRight
,nNoOfOptionalDigitsLeft
,
604 nNoOfExponentDigits
,nNoOfOptionalExponentDigits
,
605 nMultipleThousandSeparators
;
606 sal_Bool bPercent
,bCurrency
,bScientific
,bGenerateThousandSeparator
;
608 OUStringBuffer sReturnStrg
= OUStringBuffer();
610 // analyse the format-string, i. e. determine the following values:
612 - number of digits before decimal point
613 - number of digits after decimal point
614 - optional digits before decimal point
615 - number of digits in the exponent
616 - optional digits in the exponent
617 - percent-character found?
618 - () for negative leading sign?
619 - exponetial-notation?
620 - shall thousand-separators be generated?
621 - is a percent-character being found? --> dNumber *= 100.0;
622 - are there thousand-separators in a row?
623 ,, or ,. --> dNumber /= 1000.0;
624 - other errors? multiple decimal points, E's, etc.
625 --> errors are simply ignored at the moment
627 AnalyseFormatString( sFormatStrg
, nNoOfDigitsLeft
, nNoOfDigitsRight
,
628 nNoOfOptionalDigitsLeft
, nNoOfExponentDigits
,
629 nNoOfOptionalExponentDigits
,
630 bPercent
, bCurrency
, bScientific
,
631 bGenerateThousandSeparator
, nMultipleThousandSeparators
);
632 // special handling for special characters
637 // TODO: this condition (,, or ,.) is NOT Visual-Basic compatible!
638 // Question: shall this stay here (requirements)?
639 if( nMultipleThousandSeparators
)
645 short nState
,nDigitPos
,nExponentPos
,nMaxDigit
,nMaxExponentDigit
;
646 sal_Bool bFirstDigit
,bFirstExponentDigit
,bFoundFirstDigit
,
647 bIsNegative
,bZeroSpaceOn
, bSignHappend
,bDigitPosNegative
;
649 bSignHappend
= sal_False
;
650 bFoundFirstDigit
= sal_False
;
651 bIsNegative
= dNumber
< 0.0;
652 nLen
= sFormatStrg
.getLength();
653 dExponent
= get_number_of_digits( dNumber
);
655 nMaxExponentDigit
= 0;
656 nMaxDigit
= (short)dExponent
;
657 bDigitPosNegative
= false;
660 dExponent
= dExponent
- (double)(nNoOfDigitsLeft
-1);
661 nDigitPos
= nMaxDigit
;
662 nMaxExponentDigit
= (short)get_number_of_digits( dExponent
);
663 nExponentPos
= nNoOfExponentDigits
- 1 - nNoOfOptionalExponentDigits
;
667 nDigitPos
= nNoOfDigitsLeft
- 1; // counting starts at 0, 10^0
668 // no exponent-data is needed here!
669 bDigitPosNegative
= (nDigitPos
< 0);
671 bFirstDigit
= sal_True
;
672 bFirstExponentDigit
= sal_True
;
673 nState
= 0; // 0 --> mantissa; 1 --> exponent
680 // scanning the format-string:
681 sal_Unicode cForce
= 0;
682 for( i
= 0; i
< nLen
; i
++ )
692 c
= sFormatStrg
[ i
];
700 // handling of the mantissa
703 // remark: at bCurrency the negative
704 // leading sign shall be shown with ()
705 if( bIsNegative
&& !bCreateSign
&& !bSignHappend
)
707 bSignHappend
= sal_True
;
708 sReturnStrg
.append('-');
710 // output redundant positions, i. e. those which
711 // are undocumented by the format-string
712 if( nMaxDigit
> nDigitPos
)
714 for( short j
= nMaxDigit
; j
> nDigitPos
; j
-- )
718 AppendDigit( sReturnStrg
, nTempDigit
= GetDigitAtPosScan( j
, bFoundFirstDigit
) );
720 AppendDigit( sReturnStrg
, nTempDigit
= GetDigitAtPos( dNumber
, j
, dNumber
, bFoundFirstDigit
) );
722 if( nTempDigit
!=_NO_DIGIT
)
724 bFirstDigit
= sal_False
;
726 if( bGenerateThousandSeparator
&& ( c
=='0' || nMaxDigit
>= nDigitPos
) && j
> 0 && (j
% 3 == 0) )
728 sReturnStrg
.append(cThousandSep
);
734 if( nMaxDigit
<nDigitPos
&& ( c
=='0' || bZeroSpaceOn
) )
736 AppendDigit( sReturnStrg
, 0 );
737 bFirstDigit
= sal_False
;
739 // Remark: in Visual-Basic the first 0 turns on the 0 for
740 // all the following # (up to the decimal point),
741 // this behaviour is simulated here with the flag.
742 if( bGenerateThousandSeparator
&& ( c
=='0' || nMaxDigit
>= nDigitPos
) && nDigitPos
> 0 && (nDigitPos
% 3 == 0) )
744 sReturnStrg
.append(cThousandSep
);
751 AppendDigit( sReturnStrg
, nTempDigit
= GetDigitAtPosScan( nDigitPos
, bFoundFirstDigit
) );
753 AppendDigit( sReturnStrg
, nTempDigit
= GetDigitAtPos( dNumber
, nDigitPos
, dNumber
, bFoundFirstDigit
) );
756 if( nTempDigit
!= _NO_DIGIT
)
758 bFirstDigit
= sal_False
;
760 if( bGenerateThousandSeparator
&& ( c
=='0' || nMaxDigit
>=nDigitPos
) && nDigitPos
>0 && (nDigitPos
% 3 == 0) )
762 sReturnStrg
.append(cThousandSep
);
769 // handling the exponent
770 if( bFirstExponentDigit
)
772 // leading sign has been given out at e/E already
773 bFirstExponentDigit
= sal_False
;
774 if( nMaxExponentDigit
> nExponentPos
)
775 // output redundant positions, i. e. those which
776 // are undocumented by the format-string
778 for( short j
= nMaxExponentDigit
; j
> nExponentPos
; j
-- )
781 AppendDigit( sReturnStrg
, GetDigitAtPosExpScan( dExponent
, j
, bFoundFirstDigit
) );
783 AppendDigit( sReturnStrg
,GetDigitAtPos( dExponent
, j
, dExponent
, bFoundFirstDigit
) );
789 if( nMaxExponentDigit
< nExponentPos
&& c
=='0' )
791 AppendDigit( sReturnStrg
, 0 );
796 AppendDigit( sReturnStrg
, GetDigitAtPosExpScan( dExponent
, nExponentPos
, bFoundFirstDigit
) );
798 AppendDigit( sReturnStrg
, GetDigitAtPos( dExponent
, nExponentPos
, dExponent
, bFoundFirstDigit
) );
805 if( bDigitPosNegative
) // #i13821: If no digits before .
807 bDigitPosNegative
= false;
813 sReturnStrg
.append(cDecPoint
);
816 // maybe remove redundant 0s, e. g. 4.500e4 in 0.0##e-00
817 ParseBack( sReturnStrg
, sFormatStrg
, i
-1 );
818 sReturnStrg
.append('%');
822 // does mantissa have to be rounded, before the exponent is displayed?
824 // is there a mantissa at all?
827 // apparently not, i. e. invalid format string, e. g. E000.00
828 // so ignore these e and E characters
829 // maybe output an error (like in Visual Basic)?
831 // #i13821: VB 6 behaviour
832 sReturnStrg
.append(c
);
836 sal_Bool bOverflow
= sal_False
;
838 short nNextDigit
= GetDigitAtPosScan( nDigitPos
, bFoundFirstDigit
);
840 short nNextDigit
= GetDigitAtPos( dNumber
, nDigitPos
, dNumber
, bFoundFirstDigit
);
844 StrRoundDigit( sReturnStrg
, sReturnStrg
.getLength() - 1, bOverflow
);
848 // a leading 9 has been rounded
849 LeftShiftDecimalPoint( sReturnStrg
);
850 sReturnStrg
[sReturnStrg
.getLength() - 1] = 0;
853 // maybe remove redundant 0s, e. g. 4.500e4 in 0.0##e-00
854 ParseBack( sReturnStrg
, sFormatStrg
, i
-1 );
856 // change the scanner's condition
858 // output exponent character
859 sReturnStrg
.append(c
);
860 // i++; // MANIPULATION of the loop-variable!
861 c
= sFormatStrg
[ ++i
];
862 // output leading sign / exponent
867 if( dExponent
< 0.0 )
869 sReturnStrg
.append('-');
874 if( dExponent
< 0.0 )
876 sReturnStrg
.append('-');
880 sReturnStrg
.append('+');
891 // maybe remove redundant 0s, e. g. 4.500e4 in 0.0##e-00
892 ParseBack( sReturnStrg
, sFormatStrg
, i
-1 );
895 sReturnStrg
.append(c
);
899 // append the string for the currency:
900 sReturnStrg
.append(sCurrencyStrg
);
905 ParseBack( sReturnStrg
, sFormatStrg
, i
-1 );
906 sReturnStrg
.append(c
);
909 ParseBack( sReturnStrg
, sFormatStrg
, i
-1 );
910 // special character found, output next
911 // character directly (if existing)
912 c
= sFormatStrg
[ ++i
];
915 sReturnStrg
.append(c
);
918 case CREATE_1000SEP_CHAR
:
919 // ignore here, action has already been
920 // executed in AnalyseFormatString
923 // output characters and digits, too (like in Visual-Basic)
924 if( ( c
>='a' && c
<='z' ) ||
925 ( c
>='A' && c
<='Z' ) ||
926 ( c
>='1' && c
<='9' ) )
928 sReturnStrg
.append(c
);
933 // scan completed - rounding necessary?
937 short nNextDigit
= GetDigitAtPosScan( nDigitPos
, bFoundFirstDigit
);
939 short nNextDigit
= GetDigitAtPos( dNumber
, nDigitPos
, dNumber
, bFoundFirstDigit
);
943 StrRoundDigit( sReturnStrg
, sReturnStrg
.getLength() - 1 );
947 if( nNoOfDigitsRight
>0 )
949 ParseBack( sReturnStrg
, sFormatStrg
, sFormatStrg
.getLength()-1 );
951 sReturnStrgFinal
= sReturnStrg
.makeStringAndClear();
954 OUString
SbxBasicFormater::BasicFormatNull( OUString sFormatStrg
)
956 sal_Bool bNullFormatFound
;
957 OUString sNullFormatStrg
= GetNullFormatString( sFormatStrg
, bNullFormatFound
);
959 if( bNullFormatFound
)
961 return sNullFormatStrg
;
964 aRetStr
= OUString::createFromAscii( "null" );
968 OUString
SbxBasicFormater::BasicFormat( double dNumber
, OUString sFormatStrg
)
970 sal_Bool bPosFormatFound
,bNegFormatFound
,b0FormatFound
;
972 // analyse format-string concerning predefined formats:
973 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_GENERALNUMBER
) )
975 sFormatStrg
= OUString::createFromAscii( GENERALNUMBER_FORMAT
);
977 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_CURRENCY
) )
979 sFormatStrg
= sCurrencyFormatStrg
;
981 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_FIXED
) )
983 sFormatStrg
= OUString::createFromAscii( FIXED_FORMAT
);
985 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_STANDARD
) )
987 sFormatStrg
= OUString::createFromAscii( STANDARD_FORMAT
);
989 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_PERCENT
) )
991 sFormatStrg
= OUString::createFromAscii( PERCENT_FORMAT
);
993 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_SCIENTIFIC
) )
995 sFormatStrg
= OUString::createFromAscii( SCIENTIFIC_FORMAT
);
997 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_YESNO
) )
999 return ( dNumber
==0.0 ) ? sNoStrg
: sYesStrg
;
1001 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_TRUEFALSE
) )
1003 return ( dNumber
==0.0 ) ? sFalseStrg
: sTrueStrg
;
1005 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_ONOFF
) )
1007 return ( dNumber
==0.0 ) ? sOffStrg
: sOnStrg
;
1010 // analyse format-string concerning ';', i. e. format-strings for
1011 // positive-, negative- and 0-values
1012 OUString sPosFormatStrg
= GetPosFormatString( sFormatStrg
, bPosFormatFound
);
1013 OUString sNegFormatStrg
= GetNegFormatString( sFormatStrg
, bNegFormatFound
);
1014 OUString s0FormatStrg
= Get0FormatString( sFormatStrg
, b0FormatFound
);
1016 OUString sReturnStrg
;
1021 sTempStrg
= sFormatStrg
;
1024 if( s0FormatStrg
.isEmpty() && bPosFormatFound
)
1026 sTempStrg
= sPosFormatStrg
;
1030 sTempStrg
= s0FormatStrg
;
1033 else if( bPosFormatFound
)
1035 sTempStrg
= sPosFormatStrg
;
1037 ScanFormatString( dNumber
, sTempStrg
, sReturnStrg
,/*bCreateSign=*/sal_False
);
1043 if( bNegFormatFound
)
1045 if( sNegFormatStrg
.isEmpty() && bPosFormatFound
)
1048 sTempStrg
+= sPosFormatStrg
;
1052 sTempStrg
= sNegFormatStrg
;
1057 sTempStrg
= sFormatStrg
;
1059 // if NO format-string especially for negative
1060 // values is given, output the leading sign
1061 ScanFormatString( dNumber
, sTempStrg
, sReturnStrg
,/*bCreateSign=*/bNegFormatFound
/*sNegFormatStrg!=EMPTYFORMATSTRING*/ );
1063 else // if( dNumber>0.0 )
1065 ScanFormatString( dNumber
,
1066 (/*sPosFormatStrg!=EMPTYFORMATSTRING*/bPosFormatFound
? sPosFormatStrg
: sFormatStrg
),
1067 sReturnStrg
,/*bCreateSign=*/sal_False
);
1073 sal_Bool
SbxBasicFormater::isBasicFormat( OUString sFormatStrg
)
1075 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_GENERALNUMBER
) )
1079 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_CURRENCY
) )
1083 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_FIXED
) )
1087 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_STANDARD
) )
1091 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_PERCENT
) )
1095 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_SCIENTIFIC
) )
1099 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_YESNO
) )
1103 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_TRUEFALSE
) )
1107 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_ONOFF
) )
1114 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */