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