1*e1f63238SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3*e1f63238SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4*e1f63238SAndrew Rist * or more contributor license agreements. See the NOTICE file
5*e1f63238SAndrew Rist * distributed with this work for additional information
6*e1f63238SAndrew Rist * regarding copyright ownership. The ASF licenses this file
7*e1f63238SAndrew Rist * to you under the Apache License, Version 2.0 (the
8*e1f63238SAndrew Rist * "License"); you may not use this file except in compliance
9*e1f63238SAndrew Rist * with the License. You may obtain a copy of the License at
10*e1f63238SAndrew Rist *
11*e1f63238SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12*e1f63238SAndrew Rist *
13*e1f63238SAndrew Rist * Unless required by applicable law or agreed to in writing,
14*e1f63238SAndrew Rist * software distributed under the License is distributed on an
15*e1f63238SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*e1f63238SAndrew Rist * KIND, either express or implied. See the License for the
17*e1f63238SAndrew Rist * specific language governing permissions and limitations
18*e1f63238SAndrew Rist * under the License.
19*e1f63238SAndrew Rist *
20*e1f63238SAndrew Rist *************************************************************/
21*e1f63238SAndrew Rist
22*e1f63238SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_basic.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir #include <stdlib.h>
28cdf0e10cSrcweir
29cdf0e10cSrcweir #include <basic/sbxform.hxx>
30cdf0e10cSrcweir
31cdf0e10cSrcweir /*
32cdf0e10cSrcweir TODO: gibt es noch irgend welche Star-Basic Besonderheiten ?
33cdf0e10cSrcweir
34cdf0e10cSrcweir was bedeutet: * als Platzhalter
35cdf0e10cSrcweir
36cdf0e10cSrcweir BEMERKUNG: Visual-Basic behandelt folgende (ung"ultige) Format-Strings
37cdf0e10cSrcweir wie angezeigt:
38cdf0e10cSrcweir
39cdf0e10cSrcweir ##0##.##0## --> ##000.000##
40cdf0e10cSrcweir
41cdf0e10cSrcweir (diese Klasse verh"alt sich genau so).
42cdf0e10cSrcweir */
43cdf0e10cSrcweir
44cdf0e10cSrcweir #include <stdio.h> // f"ur: sprintf()
45cdf0e10cSrcweir #include <float.h> // f"ur: DBL_DIG, DBL_EPSILON
46cdf0e10cSrcweir #include <math.h> // f"ur: floor(), fabs(), log10(), pow()
47cdf0e10cSrcweir
48cdf0e10cSrcweir //=================================================================
49cdf0e10cSrcweir //=========================== DEFINES =============================
50cdf0e10cSrcweir //=================================================================
51cdf0e10cSrcweir
52cdf0e10cSrcweir #define _NO_DIGIT -1
53cdf0e10cSrcweir
54cdf0e10cSrcweir #define MAX_NO_OF_EXP_DIGITS 5
55cdf0e10cSrcweir // +4 wegen dem Wertebereich: zwischen -308 und +308
56cdf0e10cSrcweir // +1 f"ur abschliessende 0
57cdf0e10cSrcweir #define MAX_NO_OF_DIGITS DBL_DIG
58cdf0e10cSrcweir #define MAX_DOUBLE_BUFFER_LENGTH MAX_NO_OF_DIGITS + 9
59cdf0e10cSrcweir // +1 f"ur Vorzeichen
60cdf0e10cSrcweir // +1 f"ur Ziffer vor dem Dezimal-Punkt
61cdf0e10cSrcweir // +1 f"ur Dezimal-Punkt
62cdf0e10cSrcweir // +2 f"ur Exponent E und Exp. Vorzeichen
63cdf0e10cSrcweir // +3 f"ur den Wert des Exponenten
64cdf0e10cSrcweir // +1 f"ur abschliessende 0
65cdf0e10cSrcweir
66cdf0e10cSrcweir // Defines f"ur die Ziffern:
67cdf0e10cSrcweir #define ASCII_0 '0' // 48
68cdf0e10cSrcweir #define ASCII_9 '9' // 57
69cdf0e10cSrcweir
70cdf0e10cSrcweir #define CREATE_1000SEP_CHAR '@'
71cdf0e10cSrcweir
72cdf0e10cSrcweir #define FORMAT_SEPARATOR ';'
73cdf0e10cSrcweir
74cdf0e10cSrcweir // vordefinierte Formate f"ur den Format$()-Befehl:
75cdf0e10cSrcweir #define BASICFORMAT_GENERALNUMBER "General Number"
76cdf0e10cSrcweir #define BASICFORMAT_CURRENCY "Currency"
77cdf0e10cSrcweir #define BASICFORMAT_FIXED "Fixed"
78cdf0e10cSrcweir #define BASICFORMAT_STANDARD "Standard"
79cdf0e10cSrcweir #define BASICFORMAT_PERCENT "Percent"
80cdf0e10cSrcweir #define BASICFORMAT_SCIENTIFIC "Scientific"
81cdf0e10cSrcweir #define BASICFORMAT_YESNO "Yes/No"
82cdf0e10cSrcweir #define BASICFORMAT_TRUEFALSE "True/False"
83cdf0e10cSrcweir #define BASICFORMAT_ONOFF "On/Off"
84cdf0e10cSrcweir
85cdf0e10cSrcweir #define EMPTYFORMATSTRING ""
86cdf0e10cSrcweir
87cdf0e10cSrcweir // Bem.: Visual-Basic hat bei Floating-Point-Zahlen maximal 12 Stellen
88cdf0e10cSrcweir // nach dem Dezimal-Punkt.
89cdf0e10cSrcweir // Alle Format-Strings sind kompatibel zu Visual-Basic:
90cdf0e10cSrcweir #define GENERALNUMBER_FORMAT "0.############"
91cdf0e10cSrcweir // max. 12 Stellen in Visual-Basic !
92cdf0e10cSrcweir #define CURRENCY_FORMAT "@$0.00;@($0.00)"
93cdf0e10cSrcweir #define FIXED_FORMAT "0.00"
94cdf0e10cSrcweir #define STANDARD_FORMAT "@0.00"
95cdf0e10cSrcweir #define PERCENT_FORMAT "0.00%"
96cdf0e10cSrcweir #define SCIENTIFIC_FORMAT "#.00E+00"
97cdf0e10cSrcweir // BEMERKUNG: das Zeichen @ bedeutet, das Tausender-Separatoren erzeugt
98cdf0e10cSrcweir // weden sollen. Dies ist eine StarBasic 'Erweiterung'.
99cdf0e10cSrcweir
100cdf0e10cSrcweir //=================================================================
101cdf0e10cSrcweir
102cdf0e10cSrcweir // zur Bestimmung der Anzahl Stellen in dNumber
get_number_of_digits(double dNumber)103cdf0e10cSrcweir double get_number_of_digits( double dNumber )
104cdf0e10cSrcweir //double floor_log10_fabs( double dNumber )
105cdf0e10cSrcweir {
106cdf0e10cSrcweir if( dNumber==0.0 )
107cdf0e10cSrcweir // 0 hat zumindest auch eine Stelle !
108cdf0e10cSrcweir return 0.0; //ehemals 1.0, jetzt 0.0 wegen #40025;
109cdf0e10cSrcweir else
110cdf0e10cSrcweir return floor( log10( fabs( dNumber ) ) );
111cdf0e10cSrcweir }
112cdf0e10cSrcweir
113cdf0e10cSrcweir //=================================================================
114cdf0e10cSrcweir //======================= IMPLEMENTATION ==========================
115cdf0e10cSrcweir //=================================================================
116cdf0e10cSrcweir
SbxBasicFormater(sal_Unicode _cDecPoint,sal_Unicode _cThousandSep,String _sOnStrg,String _sOffStrg,String _sYesStrg,String _sNoStrg,String _sTrueStrg,String _sFalseStrg,String _sCurrencyStrg,String _sCurrencyFormatStrg)117cdf0e10cSrcweir SbxBasicFormater::SbxBasicFormater( sal_Unicode _cDecPoint, sal_Unicode _cThousandSep,
118cdf0e10cSrcweir String _sOnStrg,
119cdf0e10cSrcweir String _sOffStrg,
120cdf0e10cSrcweir String _sYesStrg,
121cdf0e10cSrcweir String _sNoStrg,
122cdf0e10cSrcweir String _sTrueStrg,
123cdf0e10cSrcweir String _sFalseStrg,
124cdf0e10cSrcweir String _sCurrencyStrg,
125cdf0e10cSrcweir String _sCurrencyFormatStrg )
126cdf0e10cSrcweir {
127cdf0e10cSrcweir cDecPoint = _cDecPoint;
128cdf0e10cSrcweir cThousandSep = _cThousandSep;
129cdf0e10cSrcweir sOnStrg = _sOnStrg;
130cdf0e10cSrcweir sOffStrg = _sOffStrg;
131cdf0e10cSrcweir sYesStrg = _sYesStrg;
132cdf0e10cSrcweir sNoStrg = _sNoStrg;
133cdf0e10cSrcweir sTrueStrg = _sTrueStrg;
134cdf0e10cSrcweir sFalseStrg = _sFalseStrg;
135cdf0e10cSrcweir sCurrencyStrg = _sCurrencyStrg;
136cdf0e10cSrcweir sCurrencyFormatStrg = _sCurrencyFormatStrg;
137cdf0e10cSrcweir }
138cdf0e10cSrcweir
139cdf0e10cSrcweir // Funktion zur Ausgabe eines Fehler-Textes (zum Debuggen)
140cdf0e10cSrcweir /*
141cdf0e10cSrcweir void SbxBasicFormater::ShowError( char * sErrMsg )
142cdf0e10cSrcweir {
143cdf0e10cSrcweir // cout << "ERROR in Format$(): " << sErrMsg << endl;
144cdf0e10cSrcweir }
145cdf0e10cSrcweir */
146cdf0e10cSrcweir // verschiebt alle Zeichen des Strings, angefangen von der nStartPos,
147cdf0e10cSrcweir // um eine Position zu gr"osseren Indizes, d.h. es wird Platz f"ur
148cdf0e10cSrcweir // ein neues (einzuf"ugendes) Zeichen geschafft.
149cdf0e10cSrcweir // ACHTUNG: der String MUSS gross genug sein !
ShiftString(String & sStrg,sal_uInt16 nStartPos)150cdf0e10cSrcweir inline void SbxBasicFormater::ShiftString( String& sStrg, sal_uInt16 nStartPos )
151cdf0e10cSrcweir {
152cdf0e10cSrcweir sStrg.Erase( nStartPos,1 );
153cdf0e10cSrcweir }
154cdf0e10cSrcweir
155cdf0e10cSrcweir // Funktion um ein Zeichen an einen String anzuh"angen
StrAppendChar(String & sStrg,sal_Unicode ch)156cdf0e10cSrcweir inline void SbxBasicFormater::StrAppendChar( String& sStrg, sal_Unicode ch )
157cdf0e10cSrcweir {
158cdf0e10cSrcweir sStrg.Insert( ch );
159cdf0e10cSrcweir }
160cdf0e10cSrcweir
161cdf0e10cSrcweir // h"angt die "ubergebene Ziffer nDigit an den "ubergebenen String sStrg
162cdf0e10cSrcweir // an, dabei wird "uberpr"uft ob nDigit eine g"ultige Ziffer ist,
163cdf0e10cSrcweir // falls dies nicht der Fall ist, wird nichts gemacht.
AppendDigit(String & sStrg,short nDigit)164cdf0e10cSrcweir void SbxBasicFormater::AppendDigit( String& sStrg, short nDigit )
165cdf0e10cSrcweir {
166cdf0e10cSrcweir if( nDigit>=0 && nDigit<=9 )
167cdf0e10cSrcweir StrAppendChar( sStrg, (sal_Unicode)(nDigit+ASCII_0) );
168cdf0e10cSrcweir }
169cdf0e10cSrcweir
170cdf0e10cSrcweir // verschiebt den Dezimal-Punkt um eine Stelle nach links
LeftShiftDecimalPoint(String & sStrg)171cdf0e10cSrcweir void SbxBasicFormater::LeftShiftDecimalPoint( String& sStrg )
172cdf0e10cSrcweir {
173cdf0e10cSrcweir sal_uInt16 nPos = sStrg.Search( cDecPoint );
174cdf0e10cSrcweir
175cdf0e10cSrcweir if( nPos!=STRING_NOTFOUND )
176cdf0e10cSrcweir {
177cdf0e10cSrcweir // vertausche Dezimal-Punkt
178cdf0e10cSrcweir sStrg.SetChar( nPos, sStrg.GetChar( nPos - 1 ) );
179cdf0e10cSrcweir sStrg.SetChar( nPos-1, cDecPoint );
180cdf0e10cSrcweir }
181cdf0e10cSrcweir }
182cdf0e10cSrcweir
183cdf0e10cSrcweir // rundet in einem String die Ziffer an der angegebenen Stelle,
184cdf0e10cSrcweir // es wird ein Flag zur"uckgeliefert, falls ein Overflow auftrat,
185cdf0e10cSrcweir // d.h. 99.99 --> 100.00, d.h. ein Gr"ossenordung ge"andert wurde
186cdf0e10cSrcweir // (geschieht beim Runden einer 9).
StrRoundDigit(String & sStrg,short nPos,sal_Bool & bOverflow)187cdf0e10cSrcweir void SbxBasicFormater::StrRoundDigit( String& sStrg, short nPos, sal_Bool& bOverflow )
188cdf0e10cSrcweir {
189cdf0e10cSrcweir // wurde ggf ein falscher Index uebergeben --> Aufruf ignorieren
190cdf0e10cSrcweir if( nPos<0 )
191cdf0e10cSrcweir return;
192cdf0e10cSrcweir
193cdf0e10cSrcweir bOverflow = sal_False;
194cdf0e10cSrcweir // "uberspringe den Dezimalpunkt und Tausender-Trennzeichen
195cdf0e10cSrcweir sal_Unicode c = sStrg.GetChar( nPos );
196cdf0e10cSrcweir if( nPos>0 && (c == cDecPoint || c == cThousandSep) )
197cdf0e10cSrcweir {
198cdf0e10cSrcweir StrRoundDigit( sStrg,nPos-1,bOverflow );
199cdf0e10cSrcweir // AENDERUNG ab 9.3.1997: nach rekursivem Call die Methode SOFORT beenden !
200cdf0e10cSrcweir return;
201cdf0e10cSrcweir }
202cdf0e10cSrcweir // "uberspringe alle nicht-Ziffern:
203cdf0e10cSrcweir // BEMERKUNG:
204cdf0e10cSrcweir // in einem g"ultigen Format-String sollte die Ausgabe
205cdf0e10cSrcweir // der Zahl an einem St"uck geschen, d.h. Sonderzeichen sollten
206cdf0e10cSrcweir // NUR vor ODER nach der Zahl stehen und nicht mitten in der
207cdf0e10cSrcweir // Format-Angabe f"ur die Zahl
208cdf0e10cSrcweir while( nPos>=0 && (sStrg.GetChar( nPos )<ASCII_0 || sStrg.GetChar( nPos )>ASCII_9) )
209cdf0e10cSrcweir nPos--;
210cdf0e10cSrcweir // muss ggf. noch Platz f"ur eine weitere (f"uhrende) Ziffer
211cdf0e10cSrcweir // geschaffen werden ?
212cdf0e10cSrcweir if( nPos==-1 )
213cdf0e10cSrcweir {
214cdf0e10cSrcweir ShiftString( sStrg,0 );
215cdf0e10cSrcweir // f"uhrende 1 einf"ugen: z.B. 99.99 f"ur 0.0
216cdf0e10cSrcweir sStrg.SetChar( 0, '1' );
217cdf0e10cSrcweir bOverflow = sal_True;
218cdf0e10cSrcweir }
219cdf0e10cSrcweir else
220cdf0e10cSrcweir {
221cdf0e10cSrcweir // ist die zu rundende Position eine Ziffer ?
222cdf0e10cSrcweir sal_Unicode c2 = sStrg.GetChar( nPos );
223cdf0e10cSrcweir if( c2 >= ASCII_0 && c2 <= ASCII_9 )
224cdf0e10cSrcweir {
225cdf0e10cSrcweir // muss eine 9 gerundet werden? Falls: Ja --> rekursiver Aufruf
226cdf0e10cSrcweir if( c2 == ASCII_9 )
227cdf0e10cSrcweir {
228cdf0e10cSrcweir sStrg.SetChar( nPos, '0' );
229cdf0e10cSrcweir StrRoundDigit( sStrg,nPos-1,bOverflow );
230cdf0e10cSrcweir }
231cdf0e10cSrcweir else
232cdf0e10cSrcweir sStrg.SetChar( nPos, c2+1 );
233cdf0e10cSrcweir }
234cdf0e10cSrcweir else
235cdf0e10cSrcweir {
236cdf0e10cSrcweir // --> Nein, d.h. Platz f"ur Ziffer schaffen: z.B. -99.99 f"ur #0.0
237cdf0e10cSrcweir // da gerundet wird MUSS es immer eine g"ultige Position
238cdf0e10cSrcweir // nPos+1 geben !
239cdf0e10cSrcweir ShiftString( sStrg,nPos+1 );
240cdf0e10cSrcweir // f"uhrende 1 einf"ugen
241cdf0e10cSrcweir sStrg.SetChar( nPos+1, '1' );
242cdf0e10cSrcweir bOverflow = sal_True;
243cdf0e10cSrcweir }
244cdf0e10cSrcweir }
245cdf0e10cSrcweir }
246cdf0e10cSrcweir
247cdf0e10cSrcweir // rundet in einem String die Ziffer an der angegebenen Stelle
StrRoundDigit(String & sStrg,short nPos)248cdf0e10cSrcweir void SbxBasicFormater::StrRoundDigit( String& sStrg, short nPos )
249cdf0e10cSrcweir {
250cdf0e10cSrcweir sal_Bool bOverflow;
251cdf0e10cSrcweir
252cdf0e10cSrcweir StrRoundDigit( sStrg,nPos,bOverflow );
253cdf0e10cSrcweir }
254cdf0e10cSrcweir
255cdf0e10cSrcweir // parse den Formatstring von der "ubergebenen Position zur"uck
256cdf0e10cSrcweir // und l"osche ggf. "uberf"ussige 0en, z.B. 4.50 in 0.0#
ParseBack(String & sStrg,const String & sFormatStrg,short nFormatPos)257cdf0e10cSrcweir void SbxBasicFormater::ParseBack( String& sStrg, const String& sFormatStrg,
258cdf0e10cSrcweir short nFormatPos )
259cdf0e10cSrcweir {
260cdf0e10cSrcweir // WICHTIG: nFormatPos kann auch negativ sein, in diesem Fall Aufruf ignorieren
261cdf0e10cSrcweir for( short i=nFormatPos;
262cdf0e10cSrcweir i>0 && sFormatStrg.GetChar( i ) == '#' && sStrg.GetChar( (sStrg.Len()-1) ) == '0';
263cdf0e10cSrcweir i-- )
264cdf0e10cSrcweir { sStrg.Erase( sStrg.Len()-1 ); }
265cdf0e10cSrcweir }
266cdf0e10cSrcweir
267cdf0e10cSrcweir #ifdef _with_sprintf
268cdf0e10cSrcweir
269cdf0e10cSrcweir /*
270cdf0e10cSrcweir Bemerkung:
271cdf0e10cSrcweir Zahl wird mit maximaler (sinnvollen) Genauigkeit in einen String
272cdf0e10cSrcweir umgewandelt (mit sprintf()), dieser String wird dann im Schleifen-
273cdf0e10cSrcweir Durchlauf nach der entsprechenden Ziffer durchsucht.
274cdf0e10cSrcweir */
275cdf0e10cSrcweir // initialisiert die Daten der Klasse um einen Scan-Durchlauf durchzuf"uhren
InitScan(double _dNum)276cdf0e10cSrcweir void SbxBasicFormater::InitScan( double _dNum )
277cdf0e10cSrcweir {
278cdf0e10cSrcweir char sBuffer[ MAX_DOUBLE_BUFFER_LENGTH ];
279cdf0e10cSrcweir
280cdf0e10cSrcweir dNum = _dNum;
281cdf0e10cSrcweir InitExp( get_number_of_digits( dNum ) );
282cdf0e10cSrcweir // maximal 15 Nachkomma-Stellen, Format-Beispiel: -1.234000000000000E-001
283cdf0e10cSrcweir /*int nCount =*/ sprintf( sBuffer,"%+22.15lE",dNum );
284cdf0e10cSrcweir sSciNumStrg.AssignAscii( sBuffer );
285cdf0e10cSrcweir }
286cdf0e10cSrcweir
InitExp(double _dNewExp)287cdf0e10cSrcweir void SbxBasicFormater::InitExp( double _dNewExp )
288cdf0e10cSrcweir {
289cdf0e10cSrcweir char sBuffer[ MAX_DOUBLE_BUFFER_LENGTH ];
290cdf0e10cSrcweir // bestimme den Exponenten (kann immer GENAU durch int dargestellt werden)
291cdf0e10cSrcweir nNumExp = (short)_dNewExp;
292cdf0e10cSrcweir // und dessen String
293cdf0e10cSrcweir /*int nCount =*/ sprintf( sBuffer,"%+i",nNumExp );
294cdf0e10cSrcweir sNumExpStrg.AssignAscii( sBuffer );
295cdf0e10cSrcweir // bestimme die Anzahl der Stellen im Exponenten
296cdf0e10cSrcweir nExpExp = (short)get_number_of_digits( (double)nNumExp );
297cdf0e10cSrcweir }
298cdf0e10cSrcweir
299cdf0e10cSrcweir // bestimmt die Ziffer an der angegebenen Stelle (gedacht zur Anwendung im
300cdf0e10cSrcweir // Scan-Durchlauf)
GetDigitAtPosScan(short nPos,sal_Bool & bFoundFirstDigit)301cdf0e10cSrcweir short SbxBasicFormater::GetDigitAtPosScan( short nPos, sal_Bool& bFoundFirstDigit )
302cdf0e10cSrcweir {
303cdf0e10cSrcweir // Versuch eine gr"ossere Ziffer zu lesen,
304cdf0e10cSrcweir // z.B. Stelle 4 in 1.234,
305cdf0e10cSrcweir // oder eine Ziffer ausserhalb der Aufl"osung der
306cdf0e10cSrcweir // Zahl (double) zu lesen (z.B. max. 15 Stellen).
307cdf0e10cSrcweir if( nPos>nNumExp || abs(nNumExp-nPos)>MAX_NO_OF_DIGITS )
308cdf0e10cSrcweir return _NO_DIGIT;
309cdf0e10cSrcweir // bestimme den Index der Stelle in dem Number-String:
310cdf0e10cSrcweir // "uberlese das Vorzeichen
311cdf0e10cSrcweir sal_uInt16 no = 1;
312cdf0e10cSrcweir // falls notwendig den Dezimal-Punkt "uberlesen:
313cdf0e10cSrcweir if( nPos<nNumExp )
314cdf0e10cSrcweir no++;
315cdf0e10cSrcweir no += nNumExp-nPos;
316cdf0e10cSrcweir // Abfrage der ersten (g"ultigen) Ziffer der Zahl --> Flag setzen
317cdf0e10cSrcweir if( nPos==nNumExp )
318cdf0e10cSrcweir bFoundFirstDigit = sal_True;
319cdf0e10cSrcweir return (short)(sSciNumStrg.GetChar( no ) - ASCII_0);
320cdf0e10cSrcweir }
321cdf0e10cSrcweir
GetDigitAtPosExpScan(short nPos,sal_Bool & bFoundFirstDigit)322cdf0e10cSrcweir short SbxBasicFormater::GetDigitAtPosExpScan( short nPos, sal_Bool& bFoundFirstDigit )
323cdf0e10cSrcweir {
324cdf0e10cSrcweir // ist die abgefragte Stelle zu gross f"ur den Exponenten ?
325cdf0e10cSrcweir if( nPos>nExpExp )
326cdf0e10cSrcweir return -1;
327cdf0e10cSrcweir
328cdf0e10cSrcweir // bestimme den Index der Stelle in dem Number-String:
329cdf0e10cSrcweir // "uberlese das Vorzeichen
330cdf0e10cSrcweir sal_uInt16 no = 1;
331cdf0e10cSrcweir no += nExpExp-nPos;
332cdf0e10cSrcweir // Abfrage der ersten (g"ultigen) Ziffer der Zahl --> Flag setzen
333cdf0e10cSrcweir if( nPos==nExpExp )
334cdf0e10cSrcweir bFoundFirstDigit = sal_True;
335cdf0e10cSrcweir return (short)(sNumExpStrg.GetChar( no ) - ASCII_0);
336cdf0e10cSrcweir }
337cdf0e10cSrcweir
338cdf0e10cSrcweir // es kann ein Wert f"ur den Exponent angegeben werden, da ggf. die
339cdf0e10cSrcweir // Zahl ggf. NICHT normiert (z.B. 1.2345e-03) dargestellt werden soll,
340cdf0e10cSrcweir // sondern eventuell 123.345e-3 !
GetDigitAtPosExpScan(double dNewExponent,short nPos,sal_Bool & bFoundFirstDigit)341cdf0e10cSrcweir short SbxBasicFormater::GetDigitAtPosExpScan( double dNewExponent, short nPos,
342cdf0e10cSrcweir sal_Bool& bFoundFirstDigit )
343cdf0e10cSrcweir {
344cdf0e10cSrcweir // neuer Exponent wurde "ubergeben, aktualisiere
345cdf0e10cSrcweir // die tempor"aren Klassen-Variablen
346cdf0e10cSrcweir InitExp( dNewExponent );
347cdf0e10cSrcweir // und jetzt die Stelle bestimmen
348cdf0e10cSrcweir return GetDigitAtPosExpScan( nPos,bFoundFirstDigit );
349cdf0e10cSrcweir }
350cdf0e10cSrcweir
351cdf0e10cSrcweir #else
352cdf0e10cSrcweir
353cdf0e10cSrcweir /* Probleme mit der folgenden Methode:
354cdf0e10cSrcweir
355cdf0e10cSrcweir TODO: ggf einen 'intelligenten' Peek-Parser um Rundungsfehler bei
356cdf0e10cSrcweir double-Zahlen herauszufinden ? z.B. f"ur 0.00115 #.#e-000
357cdf0e10cSrcweir
358cdf0e10cSrcweir Problem mit: format( 0.3345 , "0.000" )
359cdf0e10cSrcweir Problem mit: format( 0.00115 , "0.0000" )
360cdf0e10cSrcweir
361cdf0e10cSrcweir */
362cdf0e10cSrcweir // liefert die Ziffer an der angegebenen '10er System'-Position,
363cdf0e10cSrcweir // d.h. positive nPos f"ur Stellen vor dem Komma und negative
364cdf0e10cSrcweir // f"ur Stellen nach dem Komma.
365cdf0e10cSrcweir // nPos==0 bedeutet erste Stelle vor dem Komma, also 10^0.
366cdf0e10cSrcweir // liefert 0..9 f"ur g"ultige Ziffern und -1 f"ur nicht vorhanden,
367cdf0e10cSrcweir // d.h. falls die "ubergebene Zahl zu klein ist
368cdf0e10cSrcweir // (z.B. Stelle 5 bei dNumber=123).
369cdf0e10cSrcweir // Weiter wird in dNextNumber die um die f"uhrenden Stellen
370cdf0e10cSrcweir // (bis nPos) gek"urzte Zahl zur"uckgeliefert, z.B.
371cdf0e10cSrcweir // GetDigitAtPos( 3434.565 , 2 , dNewNumber ) --> dNewNumber = 434.565
372cdf0e10cSrcweir // dies kann f"ur Schleifenabarbeitung g"unstiger sein, d.h.
373cdf0e10cSrcweir // die Zahlen immer von der gr"ossten Stelle abarbeiten/scanen.
374cdf0e10cSrcweir // In bFoundFirstDigit wird ggf. ein Flag gesetzt wenn eine Ziffer
375cdf0e10cSrcweir // gefunden wurde, dies wird dazu verwendet um 'Fehler' beim Parsen 202
376cdf0e10cSrcweir // zu vermeiden, die
377cdf0e10cSrcweir //
378cdf0e10cSrcweir // ACHTUNG: anscheinend gibt es manchmal noch Probleme mit Rundungs-Fehlern!
GetDigitAtPos(double dNumber,short nPos,double & dNextNumber,sal_Bool & bFoundFirstDigit)379cdf0e10cSrcweir short SbxBasicFormater::GetDigitAtPos( double dNumber, short nPos,
380cdf0e10cSrcweir double& dNextNumber, sal_Bool& bFoundFirstDigit )
381cdf0e10cSrcweir // ACHTUNG: nPos kann auch negativ werden, f"ur Stellen nach dem Dezimal-Punkt
382cdf0e10cSrcweir {
383cdf0e10cSrcweir double dTemp = dNumber;
384cdf0e10cSrcweir double dDigit,dPos;
385cdf0e10cSrcweir short nMaxDigit;
386cdf0e10cSrcweir
387cdf0e10cSrcweir // erst mal aus der Zahl eine positive Zahl machen:
388cdf0e10cSrcweir dNumber = fabs( dNumber );
389cdf0e10cSrcweir dPos = (double)nPos;
390cdf0e10cSrcweir
391cdf0e10cSrcweir // "uberpr"ufe ob Zahl zu klein f"ur angegebene Stelle ist
392cdf0e10cSrcweir nMaxDigit = (short)get_number_of_digits( dNumber );
393cdf0e10cSrcweir // f"uhrende Ziffern 'l"oschen'
394cdf0e10cSrcweir // Bem.: Fehler nur bei Zahlen gr"osser 0, d.h. bei Ziffern vor dem
395cdf0e10cSrcweir // Dezimal-Punkt
396cdf0e10cSrcweir if( nMaxDigit<nPos && !bFoundFirstDigit && nPos>=0 )
397cdf0e10cSrcweir return _NO_DIGIT;
398cdf0e10cSrcweir // Ziffer gefunden, setze Flag:
399cdf0e10cSrcweir bFoundFirstDigit = sal_True;
400cdf0e10cSrcweir for( short i=nMaxDigit; i>=nPos; i-- )
401cdf0e10cSrcweir {
402cdf0e10cSrcweir double dI = (double)i;
403cdf0e10cSrcweir double dTemp1 = pow( 10.0,dI );
404cdf0e10cSrcweir // pr"apariere nun die gesuchte Ziffer:
405cdf0e10cSrcweir dDigit = floor( pow( 10.0,log10( fabs( dNumber ) )-dI ) );
406cdf0e10cSrcweir dNumber -= dTemp1 * dDigit;
407cdf0e10cSrcweir }
408cdf0e10cSrcweir // Zuweisung f"ur optimierte Schleifen-Durchl"aufe
409cdf0e10cSrcweir dNextNumber = dNumber;
410cdf0e10cSrcweir // und zum Schluss noch die float-Rundungsungenauigkeiten heraus filtern
411cdf0e10cSrcweir return RoundDigit( dDigit );
412cdf0e10cSrcweir }
413cdf0e10cSrcweir
414cdf0e10cSrcweir // rundet eine double-Zahl zwischen 0 und 9 auf die genaue
415cdf0e10cSrcweir // Integer-Zahl, z.B. 2.8 -> 3 und 2.2 -> 2
RoundDigit(double dNumber)416cdf0e10cSrcweir short SbxBasicFormater::RoundDigit( double dNumber )
417cdf0e10cSrcweir {
418cdf0e10cSrcweir // ist der Wertebereich g"ultig ?
419cdf0e10cSrcweir if( dNumber<0.0 || dNumber>10.0 )
420cdf0e10cSrcweir return -1;
421cdf0e10cSrcweir short nTempHigh = (short)(dNumber+0.5); // ggf. floor( )
422cdf0e10cSrcweir return nTempHigh;
423cdf0e10cSrcweir }
424cdf0e10cSrcweir
425cdf0e10cSrcweir #endif
426cdf0e10cSrcweir
427cdf0e10cSrcweir // kopiert den entsprechenden Teil des Format-Strings, falls vorhanden,
428cdf0e10cSrcweir // und liefert diesen zur"uck.
429cdf0e10cSrcweir // Somit wird ein neuer String erzeugt, der vom Aufrufer wieder freigegeben
430cdf0e10cSrcweir // werden muss
GetPosFormatString(const String & sFormatStrg,sal_Bool & bFound)431cdf0e10cSrcweir String SbxBasicFormater::GetPosFormatString( const String& sFormatStrg, sal_Bool & bFound )
432cdf0e10cSrcweir {
433cdf0e10cSrcweir bFound = sal_False; // default...
434cdf0e10cSrcweir sal_uInt16 nPos = sFormatStrg.Search( FORMAT_SEPARATOR );
435cdf0e10cSrcweir
436cdf0e10cSrcweir if( nPos!=STRING_NOTFOUND )
437cdf0e10cSrcweir {
438cdf0e10cSrcweir bFound = sal_True;
439cdf0e10cSrcweir // der Format-String f"ur die positiven Zahlen ist alles
440cdf0e10cSrcweir // vor dem ersten ';'
441cdf0e10cSrcweir return sFormatStrg.Copy( 0,nPos );
442cdf0e10cSrcweir }
443cdf0e10cSrcweir // kein ; gefunden, liefere Leerstring
444cdf0e10cSrcweir String aRetStr;
445cdf0e10cSrcweir aRetStr.AssignAscii( EMPTYFORMATSTRING );
446cdf0e10cSrcweir return aRetStr;
447cdf0e10cSrcweir }
448cdf0e10cSrcweir
449cdf0e10cSrcweir // siehe auch GetPosFormatString()
GetNegFormatString(const String & sFormatStrg,sal_Bool & bFound)450cdf0e10cSrcweir String SbxBasicFormater::GetNegFormatString( const String& sFormatStrg, sal_Bool & bFound )
451cdf0e10cSrcweir {
452cdf0e10cSrcweir bFound = sal_False; // default...
453cdf0e10cSrcweir sal_uInt16 nPos = sFormatStrg.Search( FORMAT_SEPARATOR );
454cdf0e10cSrcweir
455cdf0e10cSrcweir if( nPos!=STRING_NOTFOUND )
456cdf0e10cSrcweir {
457cdf0e10cSrcweir // der Format-String f"ur die negative Zahlen ist alles
458cdf0e10cSrcweir // zwischen dem ersten und dem zweiten ';'.
459cdf0e10cSrcweir // Daher: hole erst mal alles nach dem ersten ';'
460cdf0e10cSrcweir String sTempStrg = sFormatStrg.Copy( nPos+1 );
461cdf0e10cSrcweir // und suche darin ggf. ein weiteres ';'
462cdf0e10cSrcweir nPos = sTempStrg.Search( FORMAT_SEPARATOR );
463cdf0e10cSrcweir bFound = sal_True;
464cdf0e10cSrcweir if( nPos==STRING_NOTFOUND )
465cdf0e10cSrcweir // keins gefunden, liefere alles...
466cdf0e10cSrcweir return sTempStrg;
467cdf0e10cSrcweir else
468cdf0e10cSrcweir // ansonsten den String zwischen den beiden ';' liefern
469cdf0e10cSrcweir return sTempStrg.Copy( 0,nPos );
470cdf0e10cSrcweir }
471cdf0e10cSrcweir String aRetStr;
472cdf0e10cSrcweir aRetStr.AssignAscii( EMPTYFORMATSTRING );
473cdf0e10cSrcweir return aRetStr;
474cdf0e10cSrcweir }
475cdf0e10cSrcweir
476cdf0e10cSrcweir // siehe auch GetPosFormatString()
Get0FormatString(const String & sFormatStrg,sal_Bool & bFound)477cdf0e10cSrcweir String SbxBasicFormater::Get0FormatString( const String& sFormatStrg, sal_Bool & bFound )
478cdf0e10cSrcweir {
479cdf0e10cSrcweir bFound = sal_False; // default...
480cdf0e10cSrcweir sal_uInt16 nPos = sFormatStrg.Search( FORMAT_SEPARATOR );
481cdf0e10cSrcweir
482cdf0e10cSrcweir if( nPos!=STRING_NOTFOUND )
483cdf0e10cSrcweir {
484cdf0e10cSrcweir // der Format-String f"ur die Null ist alles
485cdf0e10cSrcweir // was nach dem zweiten ';' kommt.
486cdf0e10cSrcweir // Daher: hole erst mal alles nach dem ersten ';'
487cdf0e10cSrcweir String sTempStrg = sFormatStrg.Copy( nPos+1 );
488cdf0e10cSrcweir // und suche darin ggf. ein weiteres ';'
489cdf0e10cSrcweir nPos = sTempStrg.Search( FORMAT_SEPARATOR );
490cdf0e10cSrcweir if( nPos!=STRING_NOTFOUND )
491cdf0e10cSrcweir {
492cdf0e10cSrcweir bFound = sal_True;
493cdf0e10cSrcweir sTempStrg = sTempStrg.Copy( nPos+1 );
494cdf0e10cSrcweir nPos = sTempStrg.Search( FORMAT_SEPARATOR );
495cdf0e10cSrcweir if( nPos==STRING_NOTFOUND )
496cdf0e10cSrcweir // keins gefunden, liefere alles...
497cdf0e10cSrcweir return sTempStrg;
498cdf0e10cSrcweir else
499cdf0e10cSrcweir return sTempStrg.Copy( 0,nPos );
500cdf0e10cSrcweir }
501cdf0e10cSrcweir }
502cdf0e10cSrcweir // kein ; gefunden, liefere Leerstring
503cdf0e10cSrcweir String aRetStr;
504cdf0e10cSrcweir aRetStr.AssignAscii( EMPTYFORMATSTRING );
505cdf0e10cSrcweir return aRetStr;
506cdf0e10cSrcweir }
507cdf0e10cSrcweir
508cdf0e10cSrcweir // siehe auch GetPosFormatString()
GetNullFormatString(const String & sFormatStrg,sal_Bool & bFound)509cdf0e10cSrcweir String SbxBasicFormater::GetNullFormatString( const String& sFormatStrg, sal_Bool & bFound )
510cdf0e10cSrcweir {
511cdf0e10cSrcweir bFound = sal_False; // default...
512cdf0e10cSrcweir sal_uInt16 nPos = sFormatStrg.Search( FORMAT_SEPARATOR );
513cdf0e10cSrcweir
514cdf0e10cSrcweir if( nPos!=STRING_NOTFOUND )
515cdf0e10cSrcweir {
516cdf0e10cSrcweir // der Format-String f"ur die Null ist alles
517cdf0e10cSrcweir // was nach dem dritten ';' kommt.
518cdf0e10cSrcweir // Daher: hole erst mal alles nach dem ersten ';'
519cdf0e10cSrcweir String sTempStrg = sFormatStrg.Copy( nPos+1 );
520cdf0e10cSrcweir // und suche darin ggf. ein weiteres ';'
521cdf0e10cSrcweir nPos = sTempStrg.Search( FORMAT_SEPARATOR );
522cdf0e10cSrcweir if( nPos!=STRING_NOTFOUND )
523cdf0e10cSrcweir {
524cdf0e10cSrcweir // und suche nun nach dem dritten ';'
525cdf0e10cSrcweir sTempStrg = sTempStrg.Copy( nPos+1 );
526cdf0e10cSrcweir nPos = sTempStrg.Search( FORMAT_SEPARATOR );
527cdf0e10cSrcweir if( nPos!=STRING_NOTFOUND )
528cdf0e10cSrcweir {
529cdf0e10cSrcweir bFound = sal_True;
530cdf0e10cSrcweir return sTempStrg.Copy( nPos+1 );
531cdf0e10cSrcweir }
532cdf0e10cSrcweir }
533cdf0e10cSrcweir }
534cdf0e10cSrcweir // kein ; gefunden, liefere Leerstring
535cdf0e10cSrcweir String aRetStr;
536cdf0e10cSrcweir aRetStr.AssignAscii( EMPTYFORMATSTRING );
537cdf0e10cSrcweir return aRetStr;
538cdf0e10cSrcweir }
539cdf0e10cSrcweir
540cdf0e10cSrcweir // analysiert den Format-String, liefert Wert <> 0 falls ein Fehler
541cdf0e10cSrcweir // aufgetreten ist
AnalyseFormatString(const String & sFormatStrg,short & nNoOfDigitsLeft,short & nNoOfDigitsRight,short & nNoOfOptionalDigitsLeft,short & nNoOfExponentDigits,short & nNoOfOptionalExponentDigits,sal_Bool & bPercent,sal_Bool & bCurrency,sal_Bool & bScientific,sal_Bool & bGenerateThousandSeparator,short & nMultipleThousandSeparators)542cdf0e10cSrcweir short SbxBasicFormater::AnalyseFormatString( const String& sFormatStrg,
543cdf0e10cSrcweir short& nNoOfDigitsLeft, short& nNoOfDigitsRight,
544cdf0e10cSrcweir short& nNoOfOptionalDigitsLeft,
545cdf0e10cSrcweir short& nNoOfExponentDigits, short& nNoOfOptionalExponentDigits,
546cdf0e10cSrcweir sal_Bool& bPercent, sal_Bool& bCurrency, sal_Bool& bScientific,
547cdf0e10cSrcweir sal_Bool& bGenerateThousandSeparator,
548cdf0e10cSrcweir short& nMultipleThousandSeparators )
549cdf0e10cSrcweir {
550cdf0e10cSrcweir sal_uInt16 nLen;
551cdf0e10cSrcweir short nState = 0;
552cdf0e10cSrcweir
553cdf0e10cSrcweir nLen = sFormatStrg.Len();
554cdf0e10cSrcweir // initialisiere alle Z"ahler und Flags
555cdf0e10cSrcweir nNoOfDigitsLeft = 0;
556cdf0e10cSrcweir nNoOfDigitsRight = 0;
557cdf0e10cSrcweir nNoOfOptionalDigitsLeft = 0;
558cdf0e10cSrcweir nNoOfExponentDigits = 0;
559cdf0e10cSrcweir nNoOfOptionalExponentDigits = 0;
560cdf0e10cSrcweir bPercent = sal_False;
561cdf0e10cSrcweir bCurrency = sal_False;
562cdf0e10cSrcweir bScientific = sal_False;
563cdf0e10cSrcweir // ab 11.7.97: sobald ein Komma in dem Format String gefunden wird,
564cdf0e10cSrcweir // werden alle 3 Zehnerpotenzen markiert (d.h. tausender, milionen, ...)
565cdf0e10cSrcweir // bisher wurde nur an den gesetzten Position ein Tausender-Separator
566cdf0e10cSrcweir // ausgegeben oder wenn ein @ im Format-String stand.
567cdf0e10cSrcweir // Dies war ein Missverstaendnis der VB Kompatiblitaet.
568cdf0e10cSrcweir bGenerateThousandSeparator = sFormatStrg.Search( ',' ) != STRING_NOTFOUND;
569cdf0e10cSrcweir nMultipleThousandSeparators = 0;
570cdf0e10cSrcweir // und untersuche den Format-String nach den gew"unschten Informationen
571cdf0e10cSrcweir for( sal_uInt16 i=0; i<nLen; i++ )
572cdf0e10cSrcweir {
573cdf0e10cSrcweir sal_Unicode c = sFormatStrg.GetChar( i );
574cdf0e10cSrcweir switch( c ) {
575cdf0e10cSrcweir case '#':
576cdf0e10cSrcweir case '0':
577cdf0e10cSrcweir if( nState==0 )
578cdf0e10cSrcweir {
579cdf0e10cSrcweir nNoOfDigitsLeft++;
580cdf0e10cSrcweir // TODO hier ggf. bessere Fehler-"Uberpr"ufung der Mantisse auf g"ultige Syntax (siehe Grammatik)
581cdf0e10cSrcweir // ACHTUNG: 'undefiniertes' Verhalten falls # und 0
582cdf0e10cSrcweir // gemischt werden !!!
583cdf0e10cSrcweir // BEMERKUNG: eigentlich sind #-Platzhalter bei Scientific
584cdf0e10cSrcweir // Darstellung vor dem Dezimal-Punkt sinnlos !
585cdf0e10cSrcweir if( c=='#' )
586cdf0e10cSrcweir nNoOfOptionalDigitsLeft++;
587cdf0e10cSrcweir }
588cdf0e10cSrcweir else if( nState==1 )
589cdf0e10cSrcweir nNoOfDigitsRight++;
590cdf0e10cSrcweir else if( nState==-1 ) // suche 0 im Exponent
591cdf0e10cSrcweir {
592cdf0e10cSrcweir if( c=='#' ) // # schaltet den Zustand weiter
593cdf0e10cSrcweir {
594cdf0e10cSrcweir nNoOfOptionalExponentDigits++;
595cdf0e10cSrcweir nState = -2;
596cdf0e10cSrcweir }
597cdf0e10cSrcweir nNoOfExponentDigits++;
598cdf0e10cSrcweir }
599cdf0e10cSrcweir else if( nState==-2 ) // suche # im Exponent
600cdf0e10cSrcweir {
601cdf0e10cSrcweir if( c=='0' )
602cdf0e10cSrcweir // ERROR: 0 nach # im Exponent ist NICHT erlaubt !!
603cdf0e10cSrcweir return -4;
604cdf0e10cSrcweir nNoOfOptionalExponentDigits++;
605cdf0e10cSrcweir nNoOfExponentDigits++;
606cdf0e10cSrcweir }
607cdf0e10cSrcweir break;
608cdf0e10cSrcweir case '.':
609cdf0e10cSrcweir nState++;
610cdf0e10cSrcweir if( nState>1 )
611cdf0e10cSrcweir return -1; // ERROR: zu viele Dezimal-Punkte
612cdf0e10cSrcweir break;
613cdf0e10cSrcweir case '%':
614cdf0e10cSrcweir bPercent = sal_True;
615cdf0e10cSrcweir /* old:
616cdf0e10cSrcweir bPercent++;
617cdf0e10cSrcweir if( bPercent>1 )
618cdf0e10cSrcweir return -2; // ERROR: zu viele Prozent-Zeichen
619cdf0e10cSrcweir */
620cdf0e10cSrcweir break;
621cdf0e10cSrcweir case '(':
622cdf0e10cSrcweir bCurrency = sal_True;
623cdf0e10cSrcweir break;
624cdf0e10cSrcweir case ',':
625cdf0e10cSrcweir {
626cdf0e10cSrcweir sal_Unicode ch = sFormatStrg.GetChar( i+1 );
627cdf0e10cSrcweir // vorl"aufig wird NUR auf zwei aufeinanderfolgede
628cdf0e10cSrcweir // Zeichen gepr"uft
629cdf0e10cSrcweir if( ch!=0 && (ch==',' || ch=='.') )
630cdf0e10cSrcweir nMultipleThousandSeparators++;
631cdf0e10cSrcweir } break;
632cdf0e10cSrcweir case 'e':
633cdf0e10cSrcweir case 'E':
634cdf0e10cSrcweir // #i13821 not when no digits before
635cdf0e10cSrcweir if( nNoOfDigitsLeft > 0 || nNoOfDigitsRight > 0 )
636cdf0e10cSrcweir {
637cdf0e10cSrcweir nState = -1; // breche jetzt das Z"ahlen der Stellen ab
638cdf0e10cSrcweir bScientific = sal_True;
639cdf0e10cSrcweir }
640cdf0e10cSrcweir /* old:
641cdf0e10cSrcweir bScientific++;
642cdf0e10cSrcweir if( bScientific>1 )
643cdf0e10cSrcweir return -3; // ERROR: zu viele Exponent-Zeichen
644cdf0e10cSrcweir */
645cdf0e10cSrcweir break;
646cdf0e10cSrcweir // EIGENES Kommando-Zeichen, das die Erzeugung der
647cdf0e10cSrcweir // Tausender-Trennzeichen einschaltet
648cdf0e10cSrcweir case '\\':
649cdf0e10cSrcweir // Ignore next char
650cdf0e10cSrcweir i++;
651cdf0e10cSrcweir break;
652cdf0e10cSrcweir case CREATE_1000SEP_CHAR:
653cdf0e10cSrcweir bGenerateThousandSeparator = sal_True;
654cdf0e10cSrcweir break;
655cdf0e10cSrcweir }
656cdf0e10cSrcweir }
657cdf0e10cSrcweir return 0;
658cdf0e10cSrcweir }
659cdf0e10cSrcweir
660cdf0e10cSrcweir // das Flag bCreateSign zeigt an, dass bei der Mantisse ein Vorzeichen
661cdf0e10cSrcweir // erzeugt werden soll
ScanFormatString(double dNumber,const String & sFormatStrg,String & sReturnStrg,sal_Bool bCreateSign)662cdf0e10cSrcweir void SbxBasicFormater::ScanFormatString( double dNumber,
663cdf0e10cSrcweir const String& sFormatStrg, String& sReturnStrg,
664cdf0e10cSrcweir sal_Bool bCreateSign )
665cdf0e10cSrcweir {
666cdf0e10cSrcweir short /*nErr,*/nNoOfDigitsLeft,nNoOfDigitsRight,nNoOfOptionalDigitsLeft,
667cdf0e10cSrcweir nNoOfExponentDigits,nNoOfOptionalExponentDigits,
668cdf0e10cSrcweir nMultipleThousandSeparators;
669cdf0e10cSrcweir sal_Bool bPercent,bCurrency,bScientific,bGenerateThousandSeparator;
670cdf0e10cSrcweir
671cdf0e10cSrcweir // Initialisiere den Return-String
672cdf0e10cSrcweir sReturnStrg = String();
673cdf0e10cSrcweir
674cdf0e10cSrcweir // analysiere den Format-String, d.h. bestimme folgende Werte:
675cdf0e10cSrcweir /*
676cdf0e10cSrcweir - Anzahl der Ziffern vor dem Komma
677cdf0e10cSrcweir - Anzahl der Ziffern nach dem Komma
678cdf0e10cSrcweir - optionale Ziffern vor dem Komma
679cdf0e10cSrcweir - Anzahl der Ziffern im Exponent
680cdf0e10cSrcweir - optionale Ziffern im Exponent
681cdf0e10cSrcweir - Prozent-Zeichen gefunden ?
682cdf0e10cSrcweir - () f"ur negatives Vorzeichen ?
683cdf0e10cSrcweir - Exponetial-Schreibweise ?
684cdf0e10cSrcweir - sollen Tausender-Separatoren erzeugt werden ?
685cdf0e10cSrcweir - wird ein Prozent-Zeichen gefunden ? --> dNumber *= 100.0;
686cdf0e10cSrcweir - gibt es aufeinanderfolgende Tausender-Trennzeichen ?
687cdf0e10cSrcweir ,, oder ,. --> dNumber /= 1000.0;
688cdf0e10cSrcweir - sonstige Fehler ? mehrfache Dezimalpunkte, E's, etc.
689cdf0e10cSrcweir --> Fehler werden zur Zeit einfach ignoriert
690cdf0e10cSrcweir */
691cdf0e10cSrcweir /*nErr =*/ AnalyseFormatString( sFormatStrg,nNoOfDigitsLeft,nNoOfDigitsRight,
692cdf0e10cSrcweir nNoOfOptionalDigitsLeft,nNoOfExponentDigits,
693cdf0e10cSrcweir nNoOfOptionalExponentDigits,
694cdf0e10cSrcweir bPercent,bCurrency,bScientific,bGenerateThousandSeparator,
695cdf0e10cSrcweir nMultipleThousandSeparators );
696cdf0e10cSrcweir /* es werden alle Fehler ignoriert, wie in Visual-Basic
697cdf0e10cSrcweir if( nErr!=0 )
698cdf0e10cSrcweir {
699cdf0e10cSrcweir char sBuffer[512];
700cdf0e10cSrcweir
701cdf0e10cSrcweir //sprintf( sBuffer,"bad format-string >%s< err=%i",sFormatStrg,nErr );
702cdf0e10cSrcweir strcpy( sBuffer,"bad format-string" );
703cdf0e10cSrcweir ShowError( sBuffer );
704cdf0e10cSrcweir }
705cdf0e10cSrcweir else
706cdf0e10cSrcweir */
707cdf0e10cSrcweir {
708cdf0e10cSrcweir // Spezialbehandlung f"ur Spezialzeichen
709cdf0e10cSrcweir if( bPercent )
710cdf0e10cSrcweir dNumber *= 100.0;
711cdf0e10cSrcweir // TODO: diese Vorgabe (,, oder ,.) ist NICHT Visual-Basic kompatibel !
712cdf0e10cSrcweir // Frage: soll das hier stehen bleiben (Anforderungen) ?
713cdf0e10cSrcweir if( nMultipleThousandSeparators )
714cdf0e10cSrcweir dNumber /= 1000.0;
715cdf0e10cSrcweir
716cdf0e10cSrcweir // einige Arbeits-Variablen
717cdf0e10cSrcweir double dExponent;
718cdf0e10cSrcweir short i,nLen;
719cdf0e10cSrcweir short nState,nDigitPos,nExponentPos,nMaxDigit,nMaxExponentDigit;
720cdf0e10cSrcweir sal_Bool bFirstDigit,bFirstExponentDigit,bFoundFirstDigit,
721cdf0e10cSrcweir bIsNegative,bZeroSpaceOn, bSignHappend,bDigitPosNegative;
722cdf0e10cSrcweir
723cdf0e10cSrcweir // Initialisierung der Arbeits-Variablen
724cdf0e10cSrcweir bSignHappend = sal_False;
725cdf0e10cSrcweir bFoundFirstDigit = sal_False;
726cdf0e10cSrcweir bIsNegative = dNumber<0.0;
727cdf0e10cSrcweir nLen = sFormatStrg.Len();
728cdf0e10cSrcweir dExponent = get_number_of_digits( dNumber );
729cdf0e10cSrcweir nExponentPos = 0;
730cdf0e10cSrcweir nMaxExponentDigit = 0;
731cdf0e10cSrcweir nMaxDigit = (short)dExponent;
732cdf0e10cSrcweir bDigitPosNegative = false;
733cdf0e10cSrcweir if( bScientific )
734cdf0e10cSrcweir {
735cdf0e10cSrcweir //if( nNoOfOptionalDigitsLeft>0 )
736cdf0e10cSrcweir // ShowError( "# in scientific-format in front of the decimal-point has no effect" );
737cdf0e10cSrcweir // beim Exponent ggf. "uberz"ahlige Stellen vor dem Komma abziehen
738cdf0e10cSrcweir dExponent = dExponent - (double)(nNoOfDigitsLeft-1);
739cdf0e10cSrcweir nDigitPos = nMaxDigit;
740cdf0e10cSrcweir nMaxExponentDigit = (short)get_number_of_digits( dExponent );
741cdf0e10cSrcweir nExponentPos = nNoOfExponentDigits-1 - nNoOfOptionalExponentDigits;
742cdf0e10cSrcweir }
743cdf0e10cSrcweir else
744cdf0e10cSrcweir {
745cdf0e10cSrcweir nDigitPos = nNoOfDigitsLeft-1; // Z"ahlweise f"angt bei 0 an, 10^0
746cdf0e10cSrcweir // hier ben"otigt man keine Exponent-Daten !
747cdf0e10cSrcweir bDigitPosNegative = (nDigitPos < 0);
748cdf0e10cSrcweir }
749cdf0e10cSrcweir bFirstDigit = sal_True;
750cdf0e10cSrcweir bFirstExponentDigit = sal_True;
751cdf0e10cSrcweir nState = 0; // 0 --> Mantisse; 1 --> Exponent
752cdf0e10cSrcweir bZeroSpaceOn = 0;
753cdf0e10cSrcweir
754cdf0e10cSrcweir
755cdf0e10cSrcweir #ifdef _with_sprintf
756cdf0e10cSrcweir InitScan( dNumber );
757cdf0e10cSrcweir #endif
758cdf0e10cSrcweir // scanne jetzt den Format-String:
759cdf0e10cSrcweir sal_Unicode cForce = 0;
760cdf0e10cSrcweir for( i=0; i<nLen; i++ )
761cdf0e10cSrcweir {
762cdf0e10cSrcweir sal_Unicode c;
763cdf0e10cSrcweir if( cForce )
764cdf0e10cSrcweir {
765cdf0e10cSrcweir c = cForce;
766cdf0e10cSrcweir cForce = 0;
767cdf0e10cSrcweir }
768cdf0e10cSrcweir else
769cdf0e10cSrcweir {
770cdf0e10cSrcweir c = sFormatStrg.GetChar( i );
771cdf0e10cSrcweir }
772cdf0e10cSrcweir switch( c ) {
773cdf0e10cSrcweir case '0':
774cdf0e10cSrcweir case '#':
775cdf0e10cSrcweir if( nState==0 )
776cdf0e10cSrcweir {
777cdf0e10cSrcweir // Behandlung der Mantisse
778cdf0e10cSrcweir if( bFirstDigit )
779cdf0e10cSrcweir {
780cdf0e10cSrcweir //org:bFirstDigit = sal_False;
781cdf0e10cSrcweir // ggf. Vorzeichen erzeugen
782cdf0e10cSrcweir // Bem.: bei bCurrency soll das negative
783cdf0e10cSrcweir // Vorzeichen durch () angezeigt werden
784cdf0e10cSrcweir if( bIsNegative && !bCreateSign/*!bCurrency*/ && !bSignHappend )
785cdf0e10cSrcweir {
786cdf0e10cSrcweir // nur einmal ein Vorzeichen ausgeben
787cdf0e10cSrcweir bSignHappend = sal_True;
788cdf0e10cSrcweir StrAppendChar( sReturnStrg,'-' );
789cdf0e10cSrcweir }
790cdf0e10cSrcweir // hier jetzt "uberz"ahlige Stellen ausgeben,
791cdf0e10cSrcweir // d.h. vom Format-String nicht erfasste Stellen
792cdf0e10cSrcweir if( nMaxDigit>nDigitPos )
793cdf0e10cSrcweir {
794cdf0e10cSrcweir for( short j=nMaxDigit; j>nDigitPos; j-- )
795cdf0e10cSrcweir {
796cdf0e10cSrcweir short nTempDigit;
797cdf0e10cSrcweir #ifdef _with_sprintf
798cdf0e10cSrcweir AppendDigit( sReturnStrg,nTempDigit = GetDigitAtPosScan( j,bFoundFirstDigit ) );
799cdf0e10cSrcweir #else
800cdf0e10cSrcweir AppendDigit( sReturnStrg,nTempDigit = GetDigitAtPos( dNumber,j,dNumber,bFoundFirstDigit ) );
801cdf0e10cSrcweir #endif
802cdf0e10cSrcweir // wurde wirklich eine Ziffer eingefuegt ?
803cdf0e10cSrcweir if( nTempDigit!=_NO_DIGIT )
804cdf0e10cSrcweir // jetzt wurde wirklich eine Ziffer ausgegeben, Flag setzen
805cdf0e10cSrcweir bFirstDigit = sal_False;
806cdf0e10cSrcweir // muss ggf. ein Tausender-Trennzeichen erzeugt werden?
807cdf0e10cSrcweir if( bGenerateThousandSeparator && ( c=='0' || nMaxDigit>=nDigitPos ) && j>0 && (j % 3 == 0) )
808cdf0e10cSrcweir StrAppendChar( sReturnStrg,cThousandSep );
809cdf0e10cSrcweir }
810cdf0e10cSrcweir }
811cdf0e10cSrcweir }
812cdf0e10cSrcweir // muss f"ur eine leere Stelle eventuell eine 0 ausgegeben werden ?
813cdf0e10cSrcweir if( nMaxDigit<nDigitPos && ( c=='0' || bZeroSpaceOn ) )
814cdf0e10cSrcweir {
815cdf0e10cSrcweir AppendDigit( sReturnStrg,0 ); // Ja
816cdf0e10cSrcweir // jetzt wurde wirklich eine Ziffer ausgegeben, Flag setzen
817cdf0e10cSrcweir bFirstDigit = sal_False;
818cdf0e10cSrcweir bZeroSpaceOn = 1;
819cdf0e10cSrcweir // BEM.: bei Visual-Basic schaltet die erste 0 f"ur alle
820cdf0e10cSrcweir // nachfolgenden # (bis zum Dezimal-Punkt) die 0 ein,
821cdf0e10cSrcweir // dieses Verhalten wird hier mit dem Flag simmuliert.
822cdf0e10cSrcweir // muss ggf. ein Tausender-Trennzeichen erzeugt werden?
823cdf0e10cSrcweir if( bGenerateThousandSeparator && ( c=='0' || nMaxDigit>=nDigitPos ) && nDigitPos>0 && (nDigitPos % 3 == 0) )
824cdf0e10cSrcweir StrAppendChar( sReturnStrg,cThousandSep );
825cdf0e10cSrcweir }
826cdf0e10cSrcweir else
827cdf0e10cSrcweir {
828cdf0e10cSrcweir short nTempDigit;
829cdf0e10cSrcweir #ifdef _with_sprintf
830cdf0e10cSrcweir AppendDigit( sReturnStrg,nTempDigit = GetDigitAtPosScan( nDigitPos,bFoundFirstDigit ) );
831cdf0e10cSrcweir #else
832cdf0e10cSrcweir AppendDigit( sReturnStrg,nTempDigit = GetDigitAtPos( dNumber,nDigitPos,dNumber,bFoundFirstDigit ) );
833cdf0e10cSrcweir #endif
834cdf0e10cSrcweir // wurde wirklich eine Ziffer eingefuegt ?
835cdf0e10cSrcweir if( nTempDigit!=_NO_DIGIT )
836cdf0e10cSrcweir // jetzt wurde wirklich eine Ziffer ausgegeben, Flag setzen
837cdf0e10cSrcweir bFirstDigit = sal_False;
838cdf0e10cSrcweir // muss ggf. ein Tausender-Trennzeichen erzeugt werden?
839cdf0e10cSrcweir if( bGenerateThousandSeparator && ( c=='0' || nMaxDigit>=nDigitPos ) && nDigitPos>0 && (nDigitPos % 3 == 0) )
840cdf0e10cSrcweir StrAppendChar( sReturnStrg,cThousandSep );
841cdf0e10cSrcweir }
842cdf0e10cSrcweir // und Position aktualisieren
843cdf0e10cSrcweir nDigitPos--;
844cdf0e10cSrcweir }
845cdf0e10cSrcweir else
846cdf0e10cSrcweir {
847cdf0e10cSrcweir // Behandlung des Exponenten
848cdf0e10cSrcweir if( bFirstExponentDigit )
849cdf0e10cSrcweir {
850cdf0e10cSrcweir // Vorzeichen wurde schon bei e/E ausgegeben
851cdf0e10cSrcweir bFirstExponentDigit = sal_False;
852cdf0e10cSrcweir if( nMaxExponentDigit>nExponentPos )
853cdf0e10cSrcweir // hier jetzt "uberz"ahlige Stellen ausgeben,
854cdf0e10cSrcweir // d.h. vom Format-String nicht erfasste Stellen
855cdf0e10cSrcweir {
856cdf0e10cSrcweir for( short j=nMaxExponentDigit; j>nExponentPos; j-- )
857cdf0e10cSrcweir {
858cdf0e10cSrcweir #ifdef _with_sprintf
859cdf0e10cSrcweir AppendDigit( sReturnStrg,GetDigitAtPosExpScan( dExponent,j,bFoundFirstDigit ) );
860cdf0e10cSrcweir #else
861cdf0e10cSrcweir AppendDigit( sReturnStrg,GetDigitAtPos( dExponent,j,dExponent,bFoundFirstDigit ) );
862cdf0e10cSrcweir #endif
863cdf0e10cSrcweir }
864cdf0e10cSrcweir }
865cdf0e10cSrcweir }
866cdf0e10cSrcweir // muss f"ur eine leere Stelle eventuell eine 0 ausgegeben werden ?
867cdf0e10cSrcweir if( nMaxExponentDigit<nExponentPos && c=='0' )
868cdf0e10cSrcweir AppendDigit( sReturnStrg,0 ); // Ja
869cdf0e10cSrcweir else
870cdf0e10cSrcweir #ifdef _with_sprintf
871cdf0e10cSrcweir AppendDigit( sReturnStrg,GetDigitAtPosExpScan( dExponent,nExponentPos,bFoundFirstDigit ) );
872cdf0e10cSrcweir #else
873cdf0e10cSrcweir AppendDigit( sReturnStrg,GetDigitAtPos( dExponent,nExponentPos,dExponent,bFoundFirstDigit ) );
874cdf0e10cSrcweir #endif
875cdf0e10cSrcweir nExponentPos--;
876cdf0e10cSrcweir }
877cdf0e10cSrcweir break;
878cdf0e10cSrcweir case '.':
879cdf0e10cSrcweir if( bDigitPosNegative ) // #i13821: If no digits before .
880cdf0e10cSrcweir {
881cdf0e10cSrcweir bDigitPosNegative = false;
882cdf0e10cSrcweir nDigitPos = 0;
883cdf0e10cSrcweir cForce = '#';
884cdf0e10cSrcweir i-=2;
885cdf0e10cSrcweir break;
886cdf0e10cSrcweir }
887cdf0e10cSrcweir // gebe Komma aus
888cdf0e10cSrcweir StrAppendChar( sReturnStrg,cDecPoint );
889cdf0e10cSrcweir break;
890cdf0e10cSrcweir case '%':
891cdf0e10cSrcweir // ggf. "uberf"ussige 0en l"oschen, z.B. 4.500e4 in 0.0##e-00
892cdf0e10cSrcweir ParseBack( sReturnStrg,sFormatStrg,i-1 );
893cdf0e10cSrcweir // gebe Prozent-Zeichen aus
894cdf0e10cSrcweir sReturnStrg.Insert('%');
895cdf0e10cSrcweir break;
896cdf0e10cSrcweir case 'e':
897cdf0e10cSrcweir case 'E':
898cdf0e10cSrcweir // muss Mantisse noch gerundet werden, bevor der Exponent angezeigt wird ?
899cdf0e10cSrcweir {
900cdf0e10cSrcweir // gibt es ueberhaupt eine Mantisse ?
901cdf0e10cSrcweir if( bFirstDigit )
902cdf0e10cSrcweir {
903cdf0e10cSrcweir // anscheinend nicht, d.h. ungueltiger Format String, z.B. E000.00
904cdf0e10cSrcweir // d.h. ignoriere diese e bzw. E Zeichen
905cdf0e10cSrcweir // ggf. einen Fehler (wie Visual Basic) ausgeben ?
906cdf0e10cSrcweir
907cdf0e10cSrcweir // #i13821: VB 6 behaviour
908cdf0e10cSrcweir StrAppendChar( sReturnStrg,c );
909cdf0e10cSrcweir break;
910cdf0e10cSrcweir }
911cdf0e10cSrcweir
912cdf0e10cSrcweir sal_Bool bOverflow = sal_False;
913cdf0e10cSrcweir #ifdef _with_sprintf
914cdf0e10cSrcweir short nNextDigit = GetDigitAtPosScan( nDigitPos,bFoundFirstDigit );
915cdf0e10cSrcweir #else
916cdf0e10cSrcweir short nNextDigit = GetDigitAtPos( dNumber,nDigitPos,dNumber,bFoundFirstDigit );
917cdf0e10cSrcweir #endif
918cdf0e10cSrcweir if( nNextDigit>=5 )
919cdf0e10cSrcweir StrRoundDigit( sReturnStrg,sReturnStrg.Len()-1,bOverflow );
920cdf0e10cSrcweir if( bOverflow )
921cdf0e10cSrcweir {
922cdf0e10cSrcweir // es wurde eine f"uhrende 9 gerundet, d.h.
923cdf0e10cSrcweir // verschiebe den Dezimal-Punkt um eine Stelle nach links
924cdf0e10cSrcweir LeftShiftDecimalPoint( sReturnStrg );
925cdf0e10cSrcweir // und l"osche die letzte Ziffer, diese wird
926cdf0e10cSrcweir // duch die f"uhrende 1 ersetzt:
927cdf0e10cSrcweir sReturnStrg.SetChar( sReturnStrg.Len()-1 , 0 );
928cdf0e10cSrcweir // der Exponent muss um 1 erh"oht werden,
929cdf0e10cSrcweir // da der Dezimalpunkt verschoben wurde
930cdf0e10cSrcweir dExponent += 1.0;
931cdf0e10cSrcweir }
932cdf0e10cSrcweir // ggf. "uberf"ussige 0en l"oschen, z.B. 4.500e4 in 0.0##e-00
933cdf0e10cSrcweir ParseBack( sReturnStrg,sFormatStrg,i-1 );
934cdf0e10cSrcweir }
935cdf0e10cSrcweir // "andere Zustand des Scanners
936cdf0e10cSrcweir nState++;
937cdf0e10cSrcweir // gebe Exponent-Zeichen aus
938cdf0e10cSrcweir StrAppendChar( sReturnStrg,c );
939cdf0e10cSrcweir // i++; // MANIPULATION der Schleifen-Variable !
940cdf0e10cSrcweir c = sFormatStrg.GetChar( ++i );
941cdf0e10cSrcweir // und gebe Vorzeichen / Exponent aus
942cdf0e10cSrcweir if( c!=0 )
943cdf0e10cSrcweir {
944cdf0e10cSrcweir if( c=='-' )
945cdf0e10cSrcweir {
946cdf0e10cSrcweir // falls Exponent < 0 gebe - aus
947cdf0e10cSrcweir if( dExponent<0.0 )
948cdf0e10cSrcweir StrAppendChar( sReturnStrg,'-' );
949cdf0e10cSrcweir }
950cdf0e10cSrcweir else if( c=='+' )
951cdf0e10cSrcweir {
952cdf0e10cSrcweir // gebe auf jeden Fall das Vorzeichen des Exponenten aus !
953cdf0e10cSrcweir if( dExponent<0.0 )
954cdf0e10cSrcweir StrAppendChar( sReturnStrg,'-' );
955cdf0e10cSrcweir else
956cdf0e10cSrcweir StrAppendChar( sReturnStrg,'+' );
957cdf0e10cSrcweir }
958cdf0e10cSrcweir //else
959cdf0e10cSrcweir // ShowError( "operator e/E did not find + or -" );
960cdf0e10cSrcweir }
961cdf0e10cSrcweir //else
962cdf0e10cSrcweir // ShowError( "operator e/E ended with 0" );
963cdf0e10cSrcweir break;
964cdf0e10cSrcweir case ',':
965cdf0e10cSrcweir // ACHTUNG: nur falls Zahl bisher ausgegeben wurde
966cdf0e10cSrcweir // das Zeichen ausgeben
967cdf0e10cSrcweir ////--> Siehe Kommentar vom 11.7. in AnalyseFormatString()
968cdf0e10cSrcweir ////if( !bFirstDigit )
969cdf0e10cSrcweir //// // gebe Tausender-Trennzeichen aus
970cdf0e10cSrcweir //// StrAppendChar( sReturnStrg,cThousandSep );
971cdf0e10cSrcweir break;
972cdf0e10cSrcweir case ';':
973cdf0e10cSrcweir break;
974cdf0e10cSrcweir case '(':
975cdf0e10cSrcweir case ')':
976cdf0e10cSrcweir // ggf. "uberf"ussige 0en l"oschen, z.B. 4.500e4 in 0.0##e-00
977cdf0e10cSrcweir ParseBack( sReturnStrg,sFormatStrg,i-1 );
978cdf0e10cSrcweir if( bIsNegative )
979cdf0e10cSrcweir StrAppendChar( sReturnStrg,c );
980cdf0e10cSrcweir break;
981cdf0e10cSrcweir case '$':
982cdf0e10cSrcweir // den String fuer die Waehrung dranhengen:
983cdf0e10cSrcweir sReturnStrg += sCurrencyStrg;
984cdf0e10cSrcweir break;
985cdf0e10cSrcweir case ' ':
986cdf0e10cSrcweir case '-':
987cdf0e10cSrcweir case '+':
988cdf0e10cSrcweir // ggf. "uberf"ussige 0en l"oschen, z.B. 4.500e4 in 0.0##e-00
989cdf0e10cSrcweir ParseBack( sReturnStrg,sFormatStrg,i-1 );
990cdf0e10cSrcweir // gebe das jeweilige Zeichen direkt aus
991cdf0e10cSrcweir StrAppendChar( sReturnStrg,c );
992cdf0e10cSrcweir break;
993cdf0e10cSrcweir case '\\':
994cdf0e10cSrcweir // ggf. "uberf"ussige 0en l"oschen, z.B. 4.500e4 in 0.0##e-00
995cdf0e10cSrcweir // falls Sonderzeichen am Ende oder mitten in
996cdf0e10cSrcweir // Format-String vorkommen
997cdf0e10cSrcweir ParseBack( sReturnStrg,sFormatStrg,i-1 );
998cdf0e10cSrcweir // Sonderzeichen gefunden, gebe N"ACHSTES
999cdf0e10cSrcweir // Zeichen direkt aus (falls es existiert)
1000cdf0e10cSrcweir // i++;
1001cdf0e10cSrcweir c = sFormatStrg.GetChar( ++i );
1002cdf0e10cSrcweir if( c!=0 )
1003cdf0e10cSrcweir StrAppendChar( sReturnStrg,c );
1004cdf0e10cSrcweir //else
1005cdf0e10cSrcweir // ShowError( "operator \\ ended with 0" );
1006cdf0e10cSrcweir break;
1007cdf0e10cSrcweir case CREATE_1000SEP_CHAR:
1008cdf0e10cSrcweir // hier ignorieren, Aktion wurde schon in
1009cdf0e10cSrcweir // AnalyseFormatString durchgef"uhrt
1010cdf0e10cSrcweir break;
1011cdf0e10cSrcweir default:
1012cdf0e10cSrcweir // auch die Zeichen und Ziffern ausgeben (wie in Visual-Basic)
1013cdf0e10cSrcweir if( ( c>='a' && c<='z' ) ||
1014cdf0e10cSrcweir ( c>='A' && c<='Z' ) ||
1015cdf0e10cSrcweir ( c>='1' && c<='9' ) )
1016cdf0e10cSrcweir StrAppendChar( sReturnStrg,c );
1017cdf0e10cSrcweir // else
1018cdf0e10cSrcweir // ignorieren !
1019cdf0e10cSrcweir // ehemals: ShowError( "bad character in format-string" );
1020cdf0e10cSrcweir }
1021cdf0e10cSrcweir }
1022cdf0e10cSrcweir // Format-String wurde vollst"andig gescanned,
1023cdf0e10cSrcweir // muss die letzte Stelle nun gerundet werden ?
1024cdf0e10cSrcweir // Dies hier ist jedoch NUR notwendig, falls das
1025cdf0e10cSrcweir // Zahlenformat NICHT Scientific-Format ist !
1026cdf0e10cSrcweir if( !bScientific )
1027cdf0e10cSrcweir {
1028cdf0e10cSrcweir #ifdef _with_sprintf
1029cdf0e10cSrcweir short nNextDigit = GetDigitAtPosScan( nDigitPos,bFoundFirstDigit );
1030cdf0e10cSrcweir #else
1031cdf0e10cSrcweir short nNextDigit = GetDigitAtPos( dNumber,nDigitPos,dNumber,bFoundFirstDigit );
1032cdf0e10cSrcweir #endif
1033cdf0e10cSrcweir if( nNextDigit>=5 )
1034cdf0e10cSrcweir StrRoundDigit( sReturnStrg,sReturnStrg.Len()-1 );
1035cdf0e10cSrcweir }
1036cdf0e10cSrcweir // und ganz zum Schluss:
1037cdf0e10cSrcweir // ggf. "uberf"ussige 0en l"oschen, z.B. 4.500e4 in 0.0##e-00#,
1038cdf0e10cSrcweir // ABER nur Stellen nach dem Dezimal-Punkt k"onnen gel"oscht werden
1039cdf0e10cSrcweir if( nNoOfDigitsRight>0 )
1040cdf0e10cSrcweir ParseBack( sReturnStrg,sFormatStrg,sFormatStrg.Len()-1 );
1041cdf0e10cSrcweir }
1042cdf0e10cSrcweir }
1043cdf0e10cSrcweir
BasicFormatNull(String sFormatStrg)1044cdf0e10cSrcweir String SbxBasicFormater::BasicFormatNull( String sFormatStrg )
1045cdf0e10cSrcweir {
1046cdf0e10cSrcweir sal_Bool bNullFormatFound;
1047cdf0e10cSrcweir String sNullFormatStrg = GetNullFormatString( sFormatStrg,bNullFormatFound );
1048cdf0e10cSrcweir
1049cdf0e10cSrcweir if( bNullFormatFound )
1050cdf0e10cSrcweir return sNullFormatStrg;
1051cdf0e10cSrcweir String aRetStr;
1052cdf0e10cSrcweir aRetStr.AssignAscii( "null" );
1053cdf0e10cSrcweir return aRetStr;
1054cdf0e10cSrcweir }
1055cdf0e10cSrcweir
BasicFormat(double dNumber,String sFormatStrg)1056cdf0e10cSrcweir String SbxBasicFormater::BasicFormat( double dNumber, String sFormatStrg )
1057cdf0e10cSrcweir {
1058cdf0e10cSrcweir sal_Bool bPosFormatFound,bNegFormatFound,b0FormatFound;
1059cdf0e10cSrcweir
1060cdf0e10cSrcweir // analysiere Format-String auf vordefinierte Formate:
1061cdf0e10cSrcweir if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_GENERALNUMBER ) )
1062cdf0e10cSrcweir sFormatStrg.AssignAscii( GENERALNUMBER_FORMAT );
1063cdf0e10cSrcweir if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_CURRENCY ) )
1064cdf0e10cSrcweir sFormatStrg = sCurrencyFormatStrg; // old: CURRENCY_FORMAT;
1065cdf0e10cSrcweir if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_FIXED ) )
1066cdf0e10cSrcweir sFormatStrg.AssignAscii( FIXED_FORMAT );
1067cdf0e10cSrcweir if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_STANDARD ) )
1068cdf0e10cSrcweir sFormatStrg.AssignAscii( STANDARD_FORMAT );
1069cdf0e10cSrcweir if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_PERCENT ) )
1070cdf0e10cSrcweir sFormatStrg.AssignAscii( PERCENT_FORMAT );
1071cdf0e10cSrcweir if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_SCIENTIFIC ) )
1072cdf0e10cSrcweir sFormatStrg.AssignAscii( SCIENTIFIC_FORMAT );
1073cdf0e10cSrcweir if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_YESNO ) )
1074cdf0e10cSrcweir return ( dNumber==0.0 ) ? sNoStrg : sYesStrg ;
1075cdf0e10cSrcweir if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_TRUEFALSE ) )
1076cdf0e10cSrcweir return ( dNumber==0.0 ) ? sFalseStrg : sTrueStrg ;
1077cdf0e10cSrcweir if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_ONOFF ) )
1078cdf0e10cSrcweir return ( dNumber==0.0 ) ? sOffStrg : sOnStrg ;
1079cdf0e10cSrcweir
1080cdf0e10cSrcweir // analysiere Format-String auf ';', d.h. Format-Strings f"ur
1081cdf0e10cSrcweir // positive-, negative- und 0-Werte
1082cdf0e10cSrcweir String sPosFormatStrg = GetPosFormatString( sFormatStrg, bPosFormatFound );
1083cdf0e10cSrcweir String sNegFormatStrg = GetNegFormatString( sFormatStrg, bNegFormatFound );
1084cdf0e10cSrcweir String s0FormatStrg = Get0FormatString( sFormatStrg, b0FormatFound );
1085cdf0e10cSrcweir //String sNullFormatStrg = GetNullFormatString( sFormatStrg, bNullFormatFound );
1086cdf0e10cSrcweir
1087cdf0e10cSrcweir String sReturnStrg;
1088cdf0e10cSrcweir String sTempStrg;
1089cdf0e10cSrcweir
1090cdf0e10cSrcweir if( dNumber==0.0 )
1091cdf0e10cSrcweir {
1092cdf0e10cSrcweir sTempStrg = sFormatStrg;
1093cdf0e10cSrcweir if( b0FormatFound )
1094cdf0e10cSrcweir {
1095cdf0e10cSrcweir // wurde ggf. Leer-String uebergeben ?
1096cdf0e10cSrcweir if( s0FormatStrg.Len() == 0 && bPosFormatFound )
1097cdf0e10cSrcweir // --> Ja, dann verwende String fuer positive Werte
1098cdf0e10cSrcweir sTempStrg = sPosFormatStrg;
1099cdf0e10cSrcweir else
1100cdf0e10cSrcweir sTempStrg = s0FormatStrg;
1101cdf0e10cSrcweir }
1102cdf0e10cSrcweir else if( bPosFormatFound )
1103cdf0e10cSrcweir {
1104cdf0e10cSrcweir // verwende String fuer positive Werte
1105cdf0e10cSrcweir sTempStrg = sPosFormatStrg;
1106cdf0e10cSrcweir }
1107cdf0e10cSrcweir ScanFormatString( dNumber, sTempStrg, sReturnStrg,/*bCreateSign=*/sal_False );
1108cdf0e10cSrcweir }
1109cdf0e10cSrcweir else
1110cdf0e10cSrcweir {
1111cdf0e10cSrcweir if( dNumber<0.0 )
1112cdf0e10cSrcweir {
1113cdf0e10cSrcweir if( bNegFormatFound )
1114cdf0e10cSrcweir {
1115cdf0e10cSrcweir // wurde ggf. Leer-String uebergeben ?
1116cdf0e10cSrcweir if( sNegFormatStrg.Len() == 0 && bPosFormatFound )
1117cdf0e10cSrcweir {
1118cdf0e10cSrcweir // --> Ja, dann verwende String fuer positive Werte
1119cdf0e10cSrcweir // und setzte Minus-Zeichen davor !
1120cdf0e10cSrcweir sTempStrg = String::CreateFromAscii("-");
1121cdf0e10cSrcweir sTempStrg += sPosFormatStrg;
1122cdf0e10cSrcweir }
1123cdf0e10cSrcweir else
1124cdf0e10cSrcweir sTempStrg = sNegFormatStrg;
1125cdf0e10cSrcweir }
1126cdf0e10cSrcweir else
1127cdf0e10cSrcweir sTempStrg = sFormatStrg;
1128cdf0e10cSrcweir // falls KEIN Format-String speziell f"ur negative Werte angegeben
1129cdf0e10cSrcweir // wurde, so soll das Vorzeichen ausgegeben werden
1130cdf0e10cSrcweir ScanFormatString( dNumber, sTempStrg, sReturnStrg,/*bCreateSign=*/bNegFormatFound/*sNegFormatStrg!=EMPTYFORMATSTRING*/ );
1131cdf0e10cSrcweir }
1132cdf0e10cSrcweir else // if( dNumber>0.0 )
1133cdf0e10cSrcweir {
1134cdf0e10cSrcweir ScanFormatString( dNumber,
1135cdf0e10cSrcweir (/*sPosFormatStrg!=EMPTYFORMATSTRING*/bPosFormatFound ? sPosFormatStrg : sFormatStrg),
1136cdf0e10cSrcweir sReturnStrg,/*bCreateSign=*/sal_False );
1137cdf0e10cSrcweir }
1138cdf0e10cSrcweir }
1139cdf0e10cSrcweir return sReturnStrg;
1140cdf0e10cSrcweir }
1141cdf0e10cSrcweir
isBasicFormat(String sFormatStrg)1142cdf0e10cSrcweir sal_Bool SbxBasicFormater::isBasicFormat( String sFormatStrg )
1143cdf0e10cSrcweir {
1144cdf0e10cSrcweir if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_GENERALNUMBER ) )
1145cdf0e10cSrcweir return sal_True;
1146cdf0e10cSrcweir if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_CURRENCY ) )
1147cdf0e10cSrcweir return sal_True;
1148cdf0e10cSrcweir if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_FIXED ) )
1149cdf0e10cSrcweir return sal_True;
1150cdf0e10cSrcweir if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_STANDARD ) )
1151cdf0e10cSrcweir return sal_True;
1152cdf0e10cSrcweir if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_PERCENT ) )
1153cdf0e10cSrcweir return sal_True;
1154cdf0e10cSrcweir if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_SCIENTIFIC ) )
1155cdf0e10cSrcweir return sal_True;
1156cdf0e10cSrcweir if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_YESNO ) )
1157cdf0e10cSrcweir return sal_True;
1158cdf0e10cSrcweir if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_TRUEFALSE ) )
1159cdf0e10cSrcweir return sal_True;
1160cdf0e10cSrcweir if( sFormatStrg.EqualsIgnoreCaseAscii( BASICFORMAT_ONOFF ) )
1161cdf0e10cSrcweir return sal_True;
1162cdf0e10cSrcweir return sal_False;
1163cdf0e10cSrcweir }
1164cdf0e10cSrcweir
1165