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