xref: /trunk/main/basic/source/sbx/sbxform.cxx (revision cdf0e10c)
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