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