summaryrefslogtreecommitdiff
path: root/basic/inc/basic/sbxform.hxx
blob: 46eb030eb8774d63626dd73b942b2a02932fc4c4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 * 
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _SBXFORM_HXX
#define _SBXFORM_HXX

//====================================================================
// Implementation class for Basic command: Format$( d,formatStr )
//====================================================================
/*
  Grammar of format string (a try):
  -----------------------------------------------

  format_string		:= {\special_char} general_format | scientific_format {\special_char} {;format_string}
  general_format	:= {#[,]}{0[,]}[.{0}{#}]
  scientific_format := {0}[.{0}{#}](e | E)(+ | -){#}{0}

  percent_char		:= '%'
  special_char		:= \char | + | - | ( | ) | $ | space_char
  char				:= all_ascii_chars
  space_char		:= ' '

  {}	repeated multiple times (incl. zero times)
  []	exactly one or zero times
  ()	parenthesis, e.g. (e | E) means e or E times

  Additional predefined formats for the format string:
    "General Number"
    "Currency"
    "Fixed"
    "Standard"
    "Percent"
    "Scientific"
    "Yes/No"
    "True/False"
    "On/Off"

 Note: invalid format string are ignored just as in VisualBasic, the output is 
       probably 'undefined'. ASCII letters are outputted directly.

 Constraints in VisualBasic:
    - the exponent (scientific syntax) has a maximum of three digits!

 Constraints of new implementation:
    - the '+' sign is not allowed as wildcard in the mantissa

 TODO:
    - Date formatting
        Wildcards are: 'h', 'm', 's', 'y'
        predefined String-Constants/Commands:
            "AMPM", "Long Date", "Long Time"
*/

/*
  There are two possibilities to get the number of digits of a number:

        a) use sprintf()
        b) use log10() and pow() digit
*/
#define _with_sprintf	// use a)

#include <tools/string.hxx>

class SbxBasicFormater {
  public:
    // Constructor takes signs for decimal point, thousand separation sign
    // and necessary resource strings.
    SbxBasicFormater( sal_Unicode _cDecPoint, sal_Unicode _cThousandSep,
                      String _sOnStrg,
                      String _sOffStrg,
                      String _sYesStrg,
                      String _sNoStrg,
                      String _sTrueStrg,
                      String _sFalseStrg,
                      String _sCurrencyStrg,
                      String _sCurrencyFormatStrg );

    /* Basic command: Format$( number,format-string )

       Parameter:
        dNumber		: number to be formated
        sFormatStrg	: the Format-String, e.g. ###0.0###

       Return value:
        String containing the formatted output
    */
    String	BasicFormat( double dNumber, String sFormatStrg );
    String  BasicFormatNull( String sFormatStrg );

    static  BOOL isBasicFormat( String sFormatStrg );

  private:
    //*** some helper methods ***
    //void	ShowError( char *sErrMsg );
    inline void	ShiftString( String& sStrg, USHORT nStartPos );
    inline void	StrAppendChar( String& sStrg, sal_Unicode ch );
    void	AppendDigit( String& sStrg, short nDigit );
    void	LeftShiftDecimalPoint( String& sStrg );
    void	StrRoundDigit( String& sStrg, short nPos, BOOL& bOverflow );
    void	StrRoundDigit( String& sStrg, short nPos );
    void	ParseBack( String& sStrg, const String& sFormatStrg,
                short nFormatPos );
#ifdef _with_sprintf
    // Methods for string conversion with sprintf():
    void	InitScan( double _dNum );
    void	InitExp( double _dNewExp );
    short	GetDigitAtPosScan( short nPos, BOOL& bFoundFirstDigit );
    short	GetDigitAtPosExpScan( double dNewExponent, short nPos,
                BOOL& bFoundFirstDigit );
    short	GetDigitAtPosExpScan( short nPos, BOOL& bFoundFirstDigit );
#else
    // Methods for direct 'calculation' with log10() and pow():
    short	GetDigitAtPos( double dNumber, short nPos, double& dNextNumber,
                BOOL& bFoundFirstDigit );
    short	RoundDigit( double dNumber );
#endif
    String	GetPosFormatString( const String& sFormatStrg, BOOL & bFound );
    String	GetNegFormatString( const String& sFormatStrg, BOOL & bFound );
    String	Get0FormatString( const String& sFormatStrg, BOOL & bFound );
    String	GetNullFormatString( const String& sFormatStrg, BOOL & bFound );
    short	AnalyseFormatString( const String& sFormatStrg,
                short& nNoOfDigitsLeft, short& nNoOfDigitsRight,
                short& nNoOfOptionalDigitsLeft,
                short& nNoOfExponentDigits,
                short& nNoOfOptionalExponentDigits,
                BOOL& bPercent, BOOL& bCurrency, BOOL& bScientific,
                BOOL& bGenerateThousandSeparator,
                short& nMultipleThousandSeparators );
    void	ScanFormatString( double dNumber, const String& sFormatStrg,
                String& sReturnStrg, BOOL bCreateSign );

    //*** Data ***
    sal_Unicode cDecPoint;		// sign for the decimal point
    sal_Unicode cThousandSep;	// sign for thousand delimiter
    // Text for output:
    String 	sOnStrg;
    String 	sOffStrg;
    String	sYesStrg;
    String 	sNoStrg;
    String 	sTrueStrg;
    String 	sFalseStrg;
    String  sCurrencyStrg;
    String  sCurrencyFormatStrg;

    //*** temporary data for scan loop ***
    //-----------------------------------------------
    // String containing the number in scientific format
    String	sSciNumStrg;
    // String containing the exponent of the number
    String  sNumExpStrg;
    double	dNum;			// the number that is scanned
    short	nNumExp;		// the exponent of the number
    short	nExpExp;		// the number of digits in the exponent
};

#endif