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