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