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)
45 #define MAX_NO_OF_DIGITS DBL_DIG
46 #define MAX_DOUBLE_BUFFER_LENGTH MAX_NO_OF_DIGITS + 9
47 // +1 for leading sign
48 // +1 for digit before the decimal point
49 // +1 for decimal point
50 // +2 for exponent E and exp. leading sign
51 // +3 for the exponent's value
54 // Defines for the digits:
55 #define ASCII_0 '0' // 48
56 #define ASCII_9 '9' // 57
58 #define CREATE_1000SEP_CHAR '@'
60 #define FORMAT_SEPARATOR ';'
62 // predefined formats for the Format$()-command:
63 #define BASICFORMAT_GENERALNUMBER "General Number"
64 #define BASICFORMAT_CURRENCY "Currency"
65 #define BASICFORMAT_FIXED "Fixed"
66 #define BASICFORMAT_STANDARD "Standard"
67 #define BASICFORMAT_PERCENT "Percent"
68 #define BASICFORMAT_SCIENTIFIC "Scientific"
69 #define BASICFORMAT_YESNO "Yes/No"
70 #define BASICFORMAT_TRUEFALSE "True/False"
71 #define BASICFORMAT_ONOFF "On/Off"
73 // Comment: Visual-Basic has a maximum of 12 positions after the
74 // decimal point for floating-point-numbers.
75 // all format-strings are compatible to Visual-Basic:
76 #define GENERALNUMBER_FORMAT "0.############"
77 #define FIXED_FORMAT "0.00"
78 #define STANDARD_FORMAT "@0.00"
79 #define PERCENT_FORMAT "0.00%"
80 #define SCIENTIFIC_FORMAT "#.00E+00"
81 // Comment: the character @ means that thousand-separators shall
82 // be generated. That's a StarBasic 'extension'.
87 double get_number_of_digits( double dNumber
)
88 //double floor_log10_fabs( double dNumber )
91 return 0.0; // used to be 1.0, now 0.0 because of #40025;
93 return floor( log10( fabs( dNumber
) ) );
97 SbxBasicFormater::SbxBasicFormater( sal_Unicode _cDecPoint
, sal_Unicode _cThousandSep
,
98 const OUString
& _sOnStrg
,
99 const OUString
& _sOffStrg
,
100 const OUString
& _sYesStrg
,
101 const OUString
& _sNoStrg
,
102 const OUString
& _sTrueStrg
,
103 const OUString
& _sFalseStrg
,
104 const OUString
& _sCurrencyStrg
,
105 const OUString
& _sCurrencyFormatStrg
)
106 : cDecPoint(_cDecPoint
)
107 , cThousandSep(_cThousandSep
)
109 , sOffStrg(_sOffStrg
)
110 , sYesStrg(_sYesStrg
)
112 , sTrueStrg(_sTrueStrg
)
113 , sFalseStrg(_sFalseStrg
)
114 , sCurrencyStrg(_sCurrencyStrg
)
115 , sCurrencyFormatStrg(_sCurrencyFormatStrg
)
122 // function for ouput of a error-text (for debugging)
123 // displaces all characters of the string, starting from nStartPos
124 // for one position to larger indexes, i. e. place for a new
125 // character (which is to be inserted) is created.
126 // ATTENTION: the string MUST be long enough!
127 inline void SbxBasicFormater::ShiftString( OUStringBuffer
& sStrg
, sal_uInt16 nStartPos
)
129 sStrg
.remove(nStartPos
,1);
132 void SbxBasicFormater::AppendDigit( OUStringBuffer
& sStrg
, short nDigit
)
134 if( nDigit
>=0 && nDigit
<=9 )
136 sStrg
.append((sal_Unicode
)(nDigit
+ASCII_0
));
140 void SbxBasicFormater::LeftShiftDecimalPoint( OUStringBuffer
& sStrg
)
144 for(sal_Int32 i
= 0; i
< sStrg
.getLength(); i
++)
146 if(sStrg
[i
] == cDecPoint
)
154 sStrg
[nPos
] = sStrg
[nPos
- 1];
155 sStrg
[nPos
- 1] = cDecPoint
;
159 // returns a flag if rounding a 9
160 void SbxBasicFormater::StrRoundDigit( OUStringBuffer
& sStrg
, short nPos
, bool& bOverflow
)
167 sal_Unicode c
= sStrg
[nPos
];
168 if( nPos
> 0 && (c
== cDecPoint
|| c
== cThousandSep
) )
170 StrRoundDigit( sStrg
, nPos
- 1, bOverflow
);
171 // CHANGE from 9.3.1997: end the method immediately after recursive call!
176 // in a valid format-string the number's output should be done
177 // in one piece, i. e. special characters should ONLY be in
178 // front OR behind the number and not right in the middle of
179 // the format information for the number
180 while( nPos
>= 0 && ( sStrg
[nPos
] < ASCII_0
|| sStrg
[nPos
] > ASCII_9
))
186 ShiftString( sStrg
, 0 );
187 sStrg
[0] = (sal_Unicode
)'1';
192 sal_Unicode c2
= sStrg
[nPos
];
193 if( c2
>= ASCII_0
&& c2
<= ASCII_9
)
197 sStrg
[nPos
] = (sal_Unicode
)'0';
198 StrRoundDigit( sStrg
, nPos
- 1, bOverflow
);
202 sStrg
[nPos
] = c2
+ 1;
207 ShiftString( sStrg
,nPos
+1 );
208 sStrg
[nPos
+ 1] = (sal_Unicode
)'1';
214 void SbxBasicFormater::StrRoundDigit( OUStringBuffer
& sStrg
, short nPos
)
218 StrRoundDigit( sStrg
, nPos
, bOverflow
);
221 void SbxBasicFormater::ParseBack( OUStringBuffer
& sStrg
, const OUString
& sFormatStrg
,
224 for( sal_Int32 i
= nFormatPos
;
225 i
>0 && sFormatStrg
[ i
] == (sal_Unicode
)'#' && sStrg
[sStrg
.getLength() - 1] == (sal_Unicode
)'0';
228 sStrg
.setLength(sStrg
.getLength() - 1 );
235 void SbxBasicFormater::InitScan( double _dNum
)
237 char sBuffer
[ MAX_DOUBLE_BUFFER_LENGTH
];
240 InitExp( get_number_of_digits( dNum
) );
241 // maximum of 15 positions behind the decimal point, example: -1.234000000000000E-001
242 /*int nCount =*/ sprintf( sBuffer
,"%+22.15lE",dNum
);
243 sSciNumStrg
= OUString::createFromAscii( sBuffer
);
247 void SbxBasicFormater::InitExp( double _dNewExp
)
249 char sBuffer
[ MAX_DOUBLE_BUFFER_LENGTH
];
250 nNumExp
= (short)_dNewExp
;
251 /*int nCount =*/ sprintf( sBuffer
,"%+i",nNumExp
);
252 sNumExpStrg
= OUString::createFromAscii( sBuffer
);
253 nExpExp
= (short)get_number_of_digits( (double)nNumExp
);
257 short SbxBasicFormater::GetDigitAtPosScan( short nPos
, bool& bFoundFirstDigit
)
259 // trying to read a higher digit,
260 // e. g. position 4 in 1.234,
261 // or to read a digit outside of the
262 // number's dissolution (double)
263 if( nPos
>nNumExp
|| abs(nNumExp
-nPos
)>MAX_NO_OF_DIGITS
)
267 // determine the index of the position in the number-string:
268 // skip the leading sign
270 // skip the decimal point if necessary
274 // query of the number's first valid digit --> set flag
276 bFoundFirstDigit
= true;
277 return (short)(sSciNumStrg
[ no
] - ASCII_0
);
280 short SbxBasicFormater::GetDigitAtPosExpScan( short nPos
, bool& bFoundFirstDigit
)
289 bFoundFirstDigit
= true;
290 return (short)(sNumExpStrg
[ no
] - ASCII_0
);
293 // a value for the exponent can be given because the number maybe shall
294 // not be displayed in a normed way (e. g. 1.2345e-03) but maybe 123.345e-3 !
295 short SbxBasicFormater::GetDigitAtPosExpScan( double dNewExponent
, short nPos
,
296 bool& bFoundFirstDigit
)
298 InitExp( dNewExponent
);
300 return GetDigitAtPosExpScan( nPos
,bFoundFirstDigit
);
305 /* Problems with the following method:
307 TODO: an 'intelligent' peek-parser might be needed to detect rounding
308 mistakes at double-numbers - e. g. for 0.00115 #.#e-000
310 problem with: format( 0.3345 , "0.000" )
311 problem with: format( 0.00115 , "0.0000" )
314 // returns the digit at the given '10 system'-position,
315 // i. e. positive nPos for positions before the decimal
316 // point and negative for positions after.
317 // nPos==0 means first position after the decimalpoint, so 10^0.
318 // returns 0..9 for valid digits and -1 for not existing,
319 // i. e. if the passed number is too small
320 // (e. g. position 5 of dNumber=123).
321 // Furthermore in dNextNumber the number shorted by leading
322 // positions (till nPos) is returned, e. g.
323 // GetDigitAtPos( 3434.565 , 2 , dNewNumber ) --> dNewNumber = 434.565
324 // In bFoundFirstDigit a flag is set if a digit has been found,
325 // this is used to prevent 'errors' on parsing 202
326 // ATTENTION: apparently there are sometimes still problems with rounding mistakes!
327 short SbxBasicFormater::GetDigitAtPos( double dNumber
, short nPos
,
328 double& dNextNumber
, bool& bFoundFirstDigit
)
333 dNumber
= fabs( dNumber
);
335 nMaxDigit
= (short)get_number_of_digits( dNumber
);
336 // error only at numbers > 0, i. e. for digits before
338 if( nMaxDigit
<nPos
&& !bFoundFirstDigit
&& nPos
>=0 )
341 bFoundFirstDigit
= true;
342 for( short i
=nMaxDigit
; i
>=nPos
; i
-- )
344 double dI
= (double)i
;
345 double dTemp1
= pow( 10.0,dI
);
347 dDigit
= floor( pow( 10.0,log10( fabs( dNumber
) )-dI
) );
348 dNumber
-= dTemp1
* dDigit
;
350 // for optimized loop run
351 dNextNumber
= dNumber
;
353 return RoundDigit( dDigit
);
357 short SbxBasicFormater::RoundDigit( double dNumber
)
359 if( dNumber
<0.0 || dNumber
>10.0 )
361 short nTempHigh
= (short)(dNumber
+0.5); // maybe floor( )
367 // Copies the respective part of the format-string, if existing, and returns it.
368 // So a new string is created, which has to be freed by the caller later.
369 OUString
SbxBasicFormater::GetPosFormatString( const OUString
& sFormatStrg
, bool & bFound
)
371 bFound
= false; // default...
372 sal_Int32 nPos
= sFormatStrg
.indexOf( FORMAT_SEPARATOR
);
377 // the format-string for positive numbers is
378 // everything before the first ';'
379 return sFormatStrg
.copy( 0,nPos
);
385 // see also GetPosFormatString()
386 OUString
SbxBasicFormater::GetNegFormatString( const OUString
& sFormatStrg
, bool & bFound
)
388 bFound
= false; // default...
389 sal_Int32 nPos
= sFormatStrg
.indexOf( FORMAT_SEPARATOR
);
393 // the format-string for negative numbers is
394 // everything between the first and the second ';'
395 OUString sTempStrg
= sFormatStrg
.copy( nPos
+1 );
396 nPos
= sTempStrg
.indexOf( FORMAT_SEPARATOR
);
404 return sTempStrg
.copy( 0,nPos
);
410 // see also GetPosFormatString()
411 OUString
SbxBasicFormater::Get0FormatString( const OUString
& sFormatStrg
, bool & bFound
)
413 bFound
= false; // default...
414 sal_Int32 nPos
= sFormatStrg
.indexOf( FORMAT_SEPARATOR
);
418 // the format string for the zero is
419 // everything after the second ';'
420 OUString sTempStrg
= sFormatStrg
.copy( nPos
+1 );
421 nPos
= sTempStrg
.indexOf( FORMAT_SEPARATOR
);
425 sTempStrg
= sTempStrg
.copy( nPos
+1 );
426 nPos
= sTempStrg
.indexOf( FORMAT_SEPARATOR
);
433 return sTempStrg
.copy( 0,nPos
);
441 // see also GetPosFormatString()
442 OUString
SbxBasicFormater::GetNullFormatString( const OUString
& sFormatStrg
, bool & bFound
)
444 bFound
= false; // default...
445 sal_Int32 nPos
= sFormatStrg
.indexOf( FORMAT_SEPARATOR
);
449 // the format-string for the Null is
450 // everything after the third ';'
451 OUString sTempStrg
= sFormatStrg
.copy( nPos
+1 );
452 nPos
= sTempStrg
.indexOf( FORMAT_SEPARATOR
);
455 sTempStrg
= sTempStrg
.copy( nPos
+1 );
456 nPos
= sTempStrg
.indexOf( FORMAT_SEPARATOR
);
460 return sTempStrg
.copy( nPos
+1 );
468 // returns value <> 0 in case of an error
469 short SbxBasicFormater::AnalyseFormatString( const OUString
& sFormatStrg
,
470 short& nNoOfDigitsLeft
, short& nNoOfDigitsRight
,
471 short& nNoOfOptionalDigitsLeft
,
472 short& nNoOfExponentDigits
, short& nNoOfOptionalExponentDigits
,
473 bool& bPercent
, bool& bCurrency
, bool& bScientific
,
474 bool& bGenerateThousandSeparator
,
475 short& nMultipleThousandSeparators
)
480 nLen
= sFormatStrg
.getLength();
482 nNoOfDigitsRight
= 0;
483 nNoOfOptionalDigitsLeft
= 0;
484 nNoOfExponentDigits
= 0;
485 nNoOfOptionalExponentDigits
= 0;
489 // from 11.7.97: as soon as a comma (point?) is found in the format string,
490 // all three decimal powers are marked (i. e. thousand, million, ...)
491 bGenerateThousandSeparator
= sFormatStrg
.indexOf( ',' ) >= 0;
492 nMultipleThousandSeparators
= 0;
494 for( sal_Int32 i
= 0; i
< nLen
; i
++ )
496 sal_Unicode c
= sFormatStrg
[ i
];
504 // TODO here maybe better error inspection of the mantissa for valid syntax (see grammar)h
505 // ATTENTION: 'undefined' behaviour if # and 0 are combined!
506 // REMARK: #-placeholders are actually useless for
507 // scientific display before the decimal point!
510 nNoOfOptionalDigitsLeft
++;
517 else if( nState
==-1 ) // search 0 in the exponent
519 if( c
=='#' ) // # switches on the condition
521 nNoOfOptionalExponentDigits
++;
524 nNoOfExponentDigits
++;
526 else if( nState
==-2 ) // search # in the exponent
530 // ERROR: 0 after # in the exponent is NOT allowed!!
533 nNoOfOptionalExponentDigits
++;
534 nNoOfExponentDigits
++;
541 return -1; // ERROR: too many decimal points
552 sal_Unicode ch
= sFormatStrg
[ i
+1 ];
554 if( ch
!=0 && (ch
==',' || ch
=='.') )
556 nMultipleThousandSeparators
++;
562 // #i13821 not when no digits before
563 if( nNoOfDigitsLeft
> 0 || nNoOfDigitsRight
> 0 )
565 nState
= -1; // abort counting digits
569 // OWN command-character which turns on
570 // the creation of thousand-separators
575 case CREATE_1000SEP_CHAR
:
576 bGenerateThousandSeparator
= true;
583 // the flag bCreateSign says that at the mantissa a leading sign
585 void SbxBasicFormater::ScanFormatString( double dNumber
,
586 const OUString
& sFormatStrg
, OUString
& sReturnStrgFinal
,
589 short /*nErr,*/nNoOfDigitsLeft
,nNoOfDigitsRight
,nNoOfOptionalDigitsLeft
,
590 nNoOfExponentDigits
,nNoOfOptionalExponentDigits
,
591 nMultipleThousandSeparators
;
592 bool bPercent
,bCurrency
,bScientific
,bGenerateThousandSeparator
;
594 OUStringBuffer sReturnStrg
= OUStringBuffer();
596 // analyse the format-string, i. e. determine the following values:
598 - number of digits before decimal point
599 - number of digits after decimal point
600 - optional digits before decimal point
601 - number of digits in the exponent
602 - optional digits in the exponent
603 - percent-character found?
604 - () for negative leading sign?
605 - exponetial-notation?
606 - shall thousand-separators be generated?
607 - is a percent-character being found? --> dNumber *= 100.0;
608 - are there thousand-separators in a row?
609 ,, or ,. --> dNumber /= 1000.0;
610 - other errors? multiple decimal points, E's, etc.
611 --> errors are simply ignored at the moment
613 AnalyseFormatString( sFormatStrg
, nNoOfDigitsLeft
, nNoOfDigitsRight
,
614 nNoOfOptionalDigitsLeft
, nNoOfExponentDigits
,
615 nNoOfOptionalExponentDigits
,
616 bPercent
, bCurrency
, bScientific
,
617 bGenerateThousandSeparator
, nMultipleThousandSeparators
);
618 // special handling for special characters
623 // TODO: this condition (,, or ,.) is NOT Visual-Basic compatible!
624 // Question: shall this stay here (requirements)?
625 if( nMultipleThousandSeparators
)
631 short nState
,nDigitPos
,nExponentPos
,nMaxDigit
,nMaxExponentDigit
;
632 bool bFirstDigit
,bFirstExponentDigit
,bFoundFirstDigit
,
633 bIsNegative
,bZeroSpaceOn
, bSignHappend
,bDigitPosNegative
;
635 bSignHappend
= false;
636 bFoundFirstDigit
= false;
637 bIsNegative
= dNumber
< 0.0;
638 nLen
= sFormatStrg
.getLength();
639 dExponent
= get_number_of_digits( dNumber
);
641 nMaxExponentDigit
= 0;
642 nMaxDigit
= (short)dExponent
;
643 bDigitPosNegative
= false;
646 dExponent
= dExponent
- (double)(nNoOfDigitsLeft
-1);
647 nDigitPos
= nMaxDigit
;
648 nMaxExponentDigit
= (short)get_number_of_digits( dExponent
);
649 nExponentPos
= nNoOfExponentDigits
- 1 - nNoOfOptionalExponentDigits
;
653 nDigitPos
= nNoOfDigitsLeft
- 1; // counting starts at 0, 10^0
654 // no exponent-data is needed here!
655 bDigitPosNegative
= (nDigitPos
< 0);
658 bFirstExponentDigit
= true;
659 nState
= 0; // 0 --> mantissa; 1 --> exponent
660 bZeroSpaceOn
= false;
666 // scanning the format-string:
667 sal_Unicode cForce
= 0;
668 for( i
= 0; i
< nLen
; i
++ )
678 c
= sFormatStrg
[ i
];
686 // handling of the mantissa
689 // remark: at bCurrency the negative
690 // leading sign shall be shown with ()
691 if( bIsNegative
&& !bCreateSign
&& !bSignHappend
)
694 sReturnStrg
.append('-');
696 // output redundant positions, i. e. those which
697 // are undocumented by the format-string
698 if( nMaxDigit
> nDigitPos
)
700 for( short j
= nMaxDigit
; j
> nDigitPos
; j
-- )
704 AppendDigit( sReturnStrg
, nTempDigit
= GetDigitAtPosScan( j
, bFoundFirstDigit
) );
706 AppendDigit( sReturnStrg
, nTempDigit
= GetDigitAtPos( dNumber
, j
, dNumber
, bFoundFirstDigit
) );
708 if( nTempDigit
!=_NO_DIGIT
)
712 if( bGenerateThousandSeparator
&& ( c
=='0' || nMaxDigit
>= nDigitPos
) && j
> 0 && (j
% 3 == 0) )
714 sReturnStrg
.append(cThousandSep
);
720 if( nMaxDigit
<nDigitPos
&& ( c
=='0' || bZeroSpaceOn
) )
722 AppendDigit( sReturnStrg
, 0 );
725 // Remark: in Visual-Basic the first 0 turns on the 0 for
726 // all the following # (up to the decimal point),
727 // this behaviour is simulated here with the flag.
728 if( bGenerateThousandSeparator
&& ( c
=='0' || nMaxDigit
>= nDigitPos
) && nDigitPos
> 0 && (nDigitPos
% 3 == 0) )
730 sReturnStrg
.append(cThousandSep
);
737 AppendDigit( sReturnStrg
, nTempDigit
= GetDigitAtPosScan( nDigitPos
, bFoundFirstDigit
) );
739 AppendDigit( sReturnStrg
, nTempDigit
= GetDigitAtPos( dNumber
, nDigitPos
, dNumber
, bFoundFirstDigit
) );
742 if( nTempDigit
!= _NO_DIGIT
)
746 if( bGenerateThousandSeparator
&& ( c
=='0' || nMaxDigit
>=nDigitPos
) && nDigitPos
>0 && (nDigitPos
% 3 == 0) )
748 sReturnStrg
.append(cThousandSep
);
755 // handling the exponent
756 if( bFirstExponentDigit
)
758 // leading sign has been given out at e/E already
759 bFirstExponentDigit
= false;
760 if( nMaxExponentDigit
> nExponentPos
)
761 // output redundant positions, i. e. those which
762 // are undocumented by the format-string
764 for( short j
= nMaxExponentDigit
; j
> nExponentPos
; j
-- )
767 AppendDigit( sReturnStrg
, GetDigitAtPosExpScan( dExponent
, j
, bFoundFirstDigit
) );
769 AppendDigit( sReturnStrg
,GetDigitAtPos( dExponent
, j
, dExponent
, bFoundFirstDigit
) );
775 if( nMaxExponentDigit
< nExponentPos
&& c
=='0' )
777 AppendDigit( sReturnStrg
, 0 );
782 AppendDigit( sReturnStrg
, GetDigitAtPosExpScan( dExponent
, nExponentPos
, bFoundFirstDigit
) );
784 AppendDigit( sReturnStrg
, GetDigitAtPos( dExponent
, nExponentPos
, dExponent
, bFoundFirstDigit
) );
791 if( bDigitPosNegative
) // #i13821: If no digits before .
793 bDigitPosNegative
= false;
799 sReturnStrg
.append(cDecPoint
);
802 // maybe remove redundant 0s, e. g. 4.500e4 in 0.0##e-00
803 ParseBack( sReturnStrg
, sFormatStrg
, i
-1 );
804 sReturnStrg
.append('%');
808 // does mantissa have to be rounded, before the exponent is displayed?
810 // is there a mantissa at all?
813 // apparently not, i. e. invalid format string, e. g. E000.00
814 // so ignore these e and E characters
815 // maybe output an error (like in Visual Basic)?
817 // #i13821: VB 6 behaviour
818 sReturnStrg
.append(c
);
822 bool bOverflow
= false;
824 short nNextDigit
= GetDigitAtPosScan( nDigitPos
, bFoundFirstDigit
);
826 short nNextDigit
= GetDigitAtPos( dNumber
, nDigitPos
, dNumber
, bFoundFirstDigit
);
830 StrRoundDigit( sReturnStrg
, sReturnStrg
.getLength() - 1, bOverflow
);
834 // a leading 9 has been rounded
835 LeftShiftDecimalPoint( sReturnStrg
);
836 sReturnStrg
[sReturnStrg
.getLength() - 1] = 0;
839 // maybe remove redundant 0s, e. g. 4.500e4 in 0.0##e-00
840 ParseBack( sReturnStrg
, sFormatStrg
, i
-1 );
842 // change the scanner's condition
844 // output exponent character
845 sReturnStrg
.append(c
);
846 // i++; // MANIPULATION of the loop-variable!
847 c
= sFormatStrg
[ ++i
];
848 // output leading sign / exponent
853 if( dExponent
< 0.0 )
855 sReturnStrg
.append('-');
860 if( dExponent
< 0.0 )
862 sReturnStrg
.append('-');
866 sReturnStrg
.append('+');
877 // maybe remove redundant 0s, e. g. 4.500e4 in 0.0##e-00
878 ParseBack( sReturnStrg
, sFormatStrg
, i
-1 );
881 sReturnStrg
.append(c
);
885 // append the string for the currency:
886 sReturnStrg
.append(sCurrencyStrg
);
891 ParseBack( sReturnStrg
, sFormatStrg
, i
-1 );
892 sReturnStrg
.append(c
);
895 ParseBack( sReturnStrg
, sFormatStrg
, i
-1 );
896 // special character found, output next
897 // character directly (if existing)
898 c
= sFormatStrg
[ ++i
];
901 sReturnStrg
.append(c
);
904 case CREATE_1000SEP_CHAR
:
905 // ignore here, action has already been
906 // executed in AnalyseFormatString
909 // output characters and digits, too (like in Visual-Basic)
910 if( ( c
>='a' && c
<='z' ) ||
911 ( c
>='A' && c
<='Z' ) ||
912 ( c
>='1' && c
<='9' ) )
914 sReturnStrg
.append(c
);
919 // scan completed - rounding necessary?
923 short nNextDigit
= GetDigitAtPosScan( nDigitPos
, bFoundFirstDigit
);
925 short nNextDigit
= GetDigitAtPos( dNumber
, nDigitPos
, dNumber
, bFoundFirstDigit
);
929 StrRoundDigit( sReturnStrg
, sReturnStrg
.getLength() - 1 );
933 if( nNoOfDigitsRight
>0 )
935 ParseBack( sReturnStrg
, sFormatStrg
, sFormatStrg
.getLength()-1 );
937 sReturnStrgFinal
= sReturnStrg
.makeStringAndClear();
940 OUString
SbxBasicFormater::BasicFormatNull( const OUString
& sFormatStrg
)
942 bool bNullFormatFound
;
943 OUString sNullFormatStrg
= GetNullFormatString( sFormatStrg
, bNullFormatFound
);
945 if( bNullFormatFound
)
947 return sNullFormatStrg
;
949 return OUString("null");
952 OUString
SbxBasicFormater::BasicFormat( double dNumber
, const OUString
& _sFormatStrg
)
954 bool bPosFormatFound
,bNegFormatFound
,b0FormatFound
;
955 OUString sFormatStrg
= _sFormatStrg
;
957 // analyse format-string concerning predefined formats:
958 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_GENERALNUMBER
) )
960 sFormatStrg
= GENERALNUMBER_FORMAT
;
962 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_CURRENCY
) )
964 sFormatStrg
= sCurrencyFormatStrg
;
966 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_FIXED
) )
968 sFormatStrg
= FIXED_FORMAT
;
970 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_STANDARD
) )
972 sFormatStrg
= STANDARD_FORMAT
;
974 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_PERCENT
) )
976 sFormatStrg
= PERCENT_FORMAT
;
978 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_SCIENTIFIC
) )
980 sFormatStrg
= SCIENTIFIC_FORMAT
;
982 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_YESNO
) )
984 return ( dNumber
==0.0 ) ? sNoStrg
: sYesStrg
;
986 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_TRUEFALSE
) )
988 return ( dNumber
==0.0 ) ? sFalseStrg
: sTrueStrg
;
990 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_ONOFF
) )
992 return ( dNumber
==0.0 ) ? sOffStrg
: sOnStrg
;
995 // analyse format-string concerning ';', i. e. format-strings for
996 // positive-, negative- and 0-values
997 OUString sPosFormatStrg
= GetPosFormatString( sFormatStrg
, bPosFormatFound
);
998 OUString sNegFormatStrg
= GetNegFormatString( sFormatStrg
, bNegFormatFound
);
999 OUString s0FormatStrg
= Get0FormatString( sFormatStrg
, b0FormatFound
);
1001 OUString sReturnStrg
;
1006 sTempStrg
= sFormatStrg
;
1009 if( s0FormatStrg
.isEmpty() && bPosFormatFound
)
1011 sTempStrg
= sPosFormatStrg
;
1015 sTempStrg
= s0FormatStrg
;
1018 else if( bPosFormatFound
)
1020 sTempStrg
= sPosFormatStrg
;
1022 ScanFormatString( dNumber
, sTempStrg
, sReturnStrg
,/*bCreateSign=*/false );
1028 if( bNegFormatFound
)
1030 if( sNegFormatStrg
.isEmpty() && bPosFormatFound
)
1033 sTempStrg
+= sPosFormatStrg
;
1037 sTempStrg
= sNegFormatStrg
;
1042 sTempStrg
= sFormatStrg
;
1044 // if NO format-string especially for negative
1045 // values is given, output the leading sign
1046 ScanFormatString( dNumber
, sTempStrg
, sReturnStrg
,/*bCreateSign=*/bNegFormatFound
/*sNegFormatStrg!=EMPTYFORMATSTRING*/ );
1048 else // if( dNumber>0.0 )
1050 ScanFormatString( dNumber
,
1051 (/*sPosFormatStrg!=EMPTYFORMATSTRING*/bPosFormatFound
? sPosFormatStrg
: sFormatStrg
),
1052 sReturnStrg
,/*bCreateSign=*/false );
1058 bool SbxBasicFormater::isBasicFormat( const OUString
& sFormatStrg
)
1060 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_GENERALNUMBER
) )
1064 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_CURRENCY
) )
1068 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_FIXED
) )
1072 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_STANDARD
) )
1076 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_PERCENT
) )
1080 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_SCIENTIFIC
) )
1084 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_YESNO
) )
1088 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_TRUEFALSE
) )
1092 if( sFormatStrg
.equalsIgnoreAsciiCase( BASICFORMAT_ONOFF
) )
1099 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */