1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_svtools.hxx"
26*b1cdbd2cSJim Jagielski 
27*b1cdbd2cSJim Jagielski #include <stdio.h>
28*b1cdbd2cSJim Jagielski #include <tools/debug.hxx>
29*b1cdbd2cSJim Jagielski #include <comphelper/processfactory.hxx>
30*b1cdbd2cSJim Jagielski #include <unotools/localedatawrapper.hxx>
31*b1cdbd2cSJim Jagielski #include <vcl/svapp.hxx>
32*b1cdbd2cSJim Jagielski #include <svl/zformat.hxx>
33*b1cdbd2cSJim Jagielski #include <svtools/fmtfield.hxx>
34*b1cdbd2cSJim Jagielski #include <i18npool/mslangid.hxx>
35*b1cdbd2cSJim Jagielski #include <com/sun/star/lang/Locale.hpp>
36*b1cdbd2cSJim Jagielski #include <com/sun/star/util/SearchOptions.hpp>
37*b1cdbd2cSJim Jagielski #include <com/sun/star/util/SearchAlgorithms.hpp>
38*b1cdbd2cSJim Jagielski #include <com/sun/star/util/SearchResult.hpp>
39*b1cdbd2cSJim Jagielski #include <com/sun/star/util/SearchFlags.hpp>
40*b1cdbd2cSJim Jagielski #include <com/sun/star/lang/Locale.hpp>
41*b1cdbd2cSJim Jagielski #include <unotools/syslocale.hxx>
42*b1cdbd2cSJim Jagielski 
43*b1cdbd2cSJim Jagielski #ifndef REGEXP_SUPPORT
44*b1cdbd2cSJim Jagielski #include <map>
45*b1cdbd2cSJim Jagielski #endif
46*b1cdbd2cSJim Jagielski 
47*b1cdbd2cSJim Jagielski #if !defined INCLUDED_RTL_MATH_HXX
48*b1cdbd2cSJim Jagielski #include <rtl/math.hxx>
49*b1cdbd2cSJim Jagielski #endif
50*b1cdbd2cSJim Jagielski 
51*b1cdbd2cSJim Jagielski using namespace ::com::sun::star::lang;
52*b1cdbd2cSJim Jagielski using namespace ::com::sun::star::util;
53*b1cdbd2cSJim Jagielski 
54*b1cdbd2cSJim Jagielski 
55*b1cdbd2cSJim Jagielski #ifdef REGEXP_SUPPORT
56*b1cdbd2cSJim Jagielski 
57*b1cdbd2cSJim Jagielski //==============================================================================
58*b1cdbd2cSJim Jagielski // regular expression to validate complete numbers, plus every fragment which can occur during the input
59*b1cdbd2cSJim Jagielski // of a complete number
60*b1cdbd2cSJim Jagielski // [+/-][{digit}*.]*{digit}*[,{digit}*][e[+/-]{digit}*]
61*b1cdbd2cSJim Jagielski const char __FAR_DATA szNumericInput[] = "_[-+]?([0-9]*\\,)*[0-9]*(\\.[0-9]*)?(e[-+]?[0-9]*)?_";
62*b1cdbd2cSJim Jagielski 	// (the two _ are for normalizing it: With this, we can ensure that a to-be-checked text is always
63*b1cdbd2cSJim Jagielski 	// matched as a _whole_)
64*b1cdbd2cSJim Jagielski #else
65*b1cdbd2cSJim Jagielski 
66*b1cdbd2cSJim Jagielski // hmm. No support for regular expression. Well, I always (not really :) wanted to write a finite automat
67*b1cdbd2cSJim Jagielski // so here comes a finite automat ...
68*b1cdbd2cSJim Jagielski 
69*b1cdbd2cSJim Jagielski namespace validation
70*b1cdbd2cSJim Jagielski {
71*b1cdbd2cSJim Jagielski 	// the states of our automat.
72*b1cdbd2cSJim Jagielski 	enum State
73*b1cdbd2cSJim Jagielski 	{
74*b1cdbd2cSJim Jagielski 		START,				// at the very start of the string
75*b1cdbd2cSJim Jagielski 		NUM_START,			// the very start of the number
76*b1cdbd2cSJim Jagielski 
77*b1cdbd2cSJim Jagielski 		DIGIT_PRE_COMMA,	// some pre-comma digits are read, perhaps including some thousand separators
78*b1cdbd2cSJim Jagielski 
79*b1cdbd2cSJim Jagielski 		DIGIT_POST_COMMA,	// reading digits after the comma
80*b1cdbd2cSJim Jagielski 		EXPONENT_START,		// at the very start of the exponent value
81*b1cdbd2cSJim Jagielski 							//    (means: not including the "e" which denotes the exponent)
82*b1cdbd2cSJim Jagielski 		EXPONENT_DIGIT,		// currently reading the digits of the exponent
83*b1cdbd2cSJim Jagielski 
84*b1cdbd2cSJim Jagielski 		END					// reached the end of the string
85*b1cdbd2cSJim Jagielski 	};
86*b1cdbd2cSJim Jagielski 
87*b1cdbd2cSJim Jagielski 	// a row in the transition table (means the set of states to be reached from a given state)
88*b1cdbd2cSJim Jagielski 	typedef ::std::map< sal_Unicode, State >		StateTransitions;
89*b1cdbd2cSJim Jagielski 
90*b1cdbd2cSJim Jagielski 	// a single transition
91*b1cdbd2cSJim Jagielski 	typedef StateTransitions::value_type			Transition;
92*b1cdbd2cSJim Jagielski 
93*b1cdbd2cSJim Jagielski 	// the complete transition table
94*b1cdbd2cSJim Jagielski 	typedef	::std::map< State, StateTransitions >	TransitionTable;
95*b1cdbd2cSJim Jagielski 
96*b1cdbd2cSJim Jagielski 	// the validator class
97*b1cdbd2cSJim Jagielski 	class NumberValidator
98*b1cdbd2cSJim Jagielski 	{
99*b1cdbd2cSJim Jagielski 	private:
100*b1cdbd2cSJim Jagielski 		TransitionTable		m_aTransitions;
101*b1cdbd2cSJim Jagielski 		const sal_Unicode	m_cThSep;
102*b1cdbd2cSJim Jagielski 		const sal_Unicode	m_cDecSep;
103*b1cdbd2cSJim Jagielski 
104*b1cdbd2cSJim Jagielski 	public:
105*b1cdbd2cSJim Jagielski 		NumberValidator( const sal_Unicode _cThSep, const sal_Unicode _cDecSep );
106*b1cdbd2cSJim Jagielski 
107*b1cdbd2cSJim Jagielski 		sal_Bool isValidNumericFragment( const String& _rText );
108*b1cdbd2cSJim Jagielski 
109*b1cdbd2cSJim Jagielski 	private:
110*b1cdbd2cSJim Jagielski 		sal_Bool implValidateNormalized( const String& _rText );
111*b1cdbd2cSJim Jagielski 	};
112*b1cdbd2cSJim Jagielski 
113*b1cdbd2cSJim Jagielski 	//--------------------------------------------------------------------------
114*b1cdbd2cSJim Jagielski 	//..........................................................................
lcl_insertStopTransition(StateTransitions & _rRow)115*b1cdbd2cSJim Jagielski 	static void lcl_insertStopTransition( StateTransitions& _rRow )
116*b1cdbd2cSJim Jagielski 	{
117*b1cdbd2cSJim Jagielski 		_rRow.insert( Transition( '_', END ) );
118*b1cdbd2cSJim Jagielski 	}
119*b1cdbd2cSJim Jagielski 
120*b1cdbd2cSJim Jagielski 	//..........................................................................
lcl_insertStartExponentTransition(StateTransitions & _rRow)121*b1cdbd2cSJim Jagielski 	static void lcl_insertStartExponentTransition( StateTransitions& _rRow )
122*b1cdbd2cSJim Jagielski 	{
123*b1cdbd2cSJim Jagielski 		_rRow.insert( Transition( 'e', EXPONENT_START ) );
124*b1cdbd2cSJim Jagielski 	}
125*b1cdbd2cSJim Jagielski 
126*b1cdbd2cSJim Jagielski 	//..........................................................................
lcl_insertSignTransitions(StateTransitions & _rRow,const State eNextState)127*b1cdbd2cSJim Jagielski 	static void lcl_insertSignTransitions( StateTransitions& _rRow, const State eNextState )
128*b1cdbd2cSJim Jagielski 	{
129*b1cdbd2cSJim Jagielski 		_rRow.insert( Transition( '-', eNextState ) );
130*b1cdbd2cSJim Jagielski 		_rRow.insert( Transition( '+', eNextState ) );
131*b1cdbd2cSJim Jagielski 	}
132*b1cdbd2cSJim Jagielski 
133*b1cdbd2cSJim Jagielski 	//..........................................................................
lcl_insertDigitTransitions(StateTransitions & _rRow,const State eNextState)134*b1cdbd2cSJim Jagielski 	static void lcl_insertDigitTransitions( StateTransitions& _rRow, const State eNextState )
135*b1cdbd2cSJim Jagielski 	{
136*b1cdbd2cSJim Jagielski 		for ( sal_Unicode aChar = '0'; aChar <= '9'; ++aChar )
137*b1cdbd2cSJim Jagielski 			_rRow.insert( Transition( aChar, eNextState ) );
138*b1cdbd2cSJim Jagielski 	}
139*b1cdbd2cSJim Jagielski 
140*b1cdbd2cSJim Jagielski 	//..........................................................................
lcl_insertCommonPreCommaTransitions(StateTransitions & _rRow,const sal_Unicode _cThSep,const sal_Unicode _cDecSep)141*b1cdbd2cSJim Jagielski 	static void lcl_insertCommonPreCommaTransitions( StateTransitions& _rRow, const sal_Unicode _cThSep, const sal_Unicode _cDecSep )
142*b1cdbd2cSJim Jagielski 	{
143*b1cdbd2cSJim Jagielski 		// digits are allowed
144*b1cdbd2cSJim Jagielski 		lcl_insertDigitTransitions( _rRow, DIGIT_PRE_COMMA );
145*b1cdbd2cSJim Jagielski 
146*b1cdbd2cSJim Jagielski 		// the thousand separator is allowed
147*b1cdbd2cSJim Jagielski 		_rRow.insert( Transition( _cThSep, DIGIT_PRE_COMMA ) );
148*b1cdbd2cSJim Jagielski 
149*b1cdbd2cSJim Jagielski 		// a comma is allowed
150*b1cdbd2cSJim Jagielski 		_rRow.insert( Transition( _cDecSep, DIGIT_POST_COMMA ) );
151*b1cdbd2cSJim Jagielski 	}
152*b1cdbd2cSJim Jagielski 
153*b1cdbd2cSJim Jagielski 	//--------------------------------------------------------------------------
NumberValidator(const sal_Unicode _cThSep,const sal_Unicode _cDecSep)154*b1cdbd2cSJim Jagielski 	NumberValidator::NumberValidator( const sal_Unicode _cThSep, const sal_Unicode _cDecSep )
155*b1cdbd2cSJim Jagielski 		:m_cThSep( _cThSep )
156*b1cdbd2cSJim Jagielski 		,m_cDecSep( _cDecSep )
157*b1cdbd2cSJim Jagielski 	{
158*b1cdbd2cSJim Jagielski 		// build up our transition table
159*b1cdbd2cSJim Jagielski 
160*b1cdbd2cSJim Jagielski 		// how to procede from START
161*b1cdbd2cSJim Jagielski 		{
162*b1cdbd2cSJim Jagielski 			StateTransitions& rRow = m_aTransitions[ START ];
163*b1cdbd2cSJim Jagielski 			rRow.insert( Transition( '_', NUM_START ) );
164*b1cdbd2cSJim Jagielski 				// if we encounter the normalizing character, we want to procede with the number
165*b1cdbd2cSJim Jagielski 		}
166*b1cdbd2cSJim Jagielski 
167*b1cdbd2cSJim Jagielski 		// how to procede from NUM_START
168*b1cdbd2cSJim Jagielski 		{
169*b1cdbd2cSJim Jagielski 			StateTransitions& rRow = m_aTransitions[ NUM_START ];
170*b1cdbd2cSJim Jagielski 
171*b1cdbd2cSJim Jagielski 			// a sign is allowed
172*b1cdbd2cSJim Jagielski 			lcl_insertSignTransitions( rRow, DIGIT_PRE_COMMA );
173*b1cdbd2cSJim Jagielski 
174*b1cdbd2cSJim Jagielski 			// common transitions for the two pre-comma states
175*b1cdbd2cSJim Jagielski 			lcl_insertCommonPreCommaTransitions( rRow, m_cThSep, m_cDecSep );
176*b1cdbd2cSJim Jagielski 
177*b1cdbd2cSJim Jagielski 			// the exponent may start here
178*b1cdbd2cSJim Jagielski 			// (this would mean string like "_+e10_", but this is a valid fragment, though no valid number)
179*b1cdbd2cSJim Jagielski 			lcl_insertStartExponentTransition( rRow );
180*b1cdbd2cSJim Jagielski 		}
181*b1cdbd2cSJim Jagielski 
182*b1cdbd2cSJim Jagielski 		// how to procede from DIGIT_PRE_COMMA
183*b1cdbd2cSJim Jagielski 		{
184*b1cdbd2cSJim Jagielski 			StateTransitions& rRow = m_aTransitions[ DIGIT_PRE_COMMA ];
185*b1cdbd2cSJim Jagielski 
186*b1cdbd2cSJim Jagielski 			// common transitions for the two pre-comma states
187*b1cdbd2cSJim Jagielski 			lcl_insertCommonPreCommaTransitions( rRow, m_cThSep, m_cDecSep );
188*b1cdbd2cSJim Jagielski 
189*b1cdbd2cSJim Jagielski 			// the exponent may start here
190*b1cdbd2cSJim Jagielski 			lcl_insertStartExponentTransition( rRow );
191*b1cdbd2cSJim Jagielski 
192*b1cdbd2cSJim Jagielski 			// the final transition indicating the end of the string
193*b1cdbd2cSJim Jagielski 			// (if there is no comma and no post-comma, then the string may end here)
194*b1cdbd2cSJim Jagielski 			lcl_insertStopTransition( rRow );
195*b1cdbd2cSJim Jagielski 		}
196*b1cdbd2cSJim Jagielski 
197*b1cdbd2cSJim Jagielski 		// how to procede from DIGIT_POST_COMMA
198*b1cdbd2cSJim Jagielski 		{
199*b1cdbd2cSJim Jagielski 			StateTransitions& rRow = m_aTransitions[ DIGIT_POST_COMMA ];
200*b1cdbd2cSJim Jagielski 
201*b1cdbd2cSJim Jagielski 			// there might be digits, which would keep the state at DIGIT_POST_COMMA
202*b1cdbd2cSJim Jagielski 			lcl_insertDigitTransitions( rRow, DIGIT_POST_COMMA );
203*b1cdbd2cSJim Jagielski 
204*b1cdbd2cSJim Jagielski 			// the exponent may start here
205*b1cdbd2cSJim Jagielski 			lcl_insertStartExponentTransition( rRow );
206*b1cdbd2cSJim Jagielski 
207*b1cdbd2cSJim Jagielski 			// the string may end here
208*b1cdbd2cSJim Jagielski 			lcl_insertStopTransition( rRow );
209*b1cdbd2cSJim Jagielski 		}
210*b1cdbd2cSJim Jagielski 
211*b1cdbd2cSJim Jagielski 		// how to procede from EXPONENT_START
212*b1cdbd2cSJim Jagielski 		{
213*b1cdbd2cSJim Jagielski 			StateTransitions& rRow = m_aTransitions[ EXPONENT_START ];
214*b1cdbd2cSJim Jagielski 
215*b1cdbd2cSJim Jagielski 			// there may be a sign
216*b1cdbd2cSJim Jagielski 			lcl_insertSignTransitions( rRow, EXPONENT_DIGIT );
217*b1cdbd2cSJim Jagielski 
218*b1cdbd2cSJim Jagielski 			// there may be digits
219*b1cdbd2cSJim Jagielski 			lcl_insertDigitTransitions( rRow, EXPONENT_DIGIT );
220*b1cdbd2cSJim Jagielski 
221*b1cdbd2cSJim Jagielski 			// the string may end here
222*b1cdbd2cSJim Jagielski 			lcl_insertStopTransition( rRow );
223*b1cdbd2cSJim Jagielski 		}
224*b1cdbd2cSJim Jagielski 
225*b1cdbd2cSJim Jagielski 		// how to procede from EXPONENT_DIGIT
226*b1cdbd2cSJim Jagielski 		{
227*b1cdbd2cSJim Jagielski 			StateTransitions& rRow = m_aTransitions[ EXPONENT_DIGIT ];
228*b1cdbd2cSJim Jagielski 
229*b1cdbd2cSJim Jagielski 			// there may be digits
230*b1cdbd2cSJim Jagielski 			lcl_insertDigitTransitions( rRow, EXPONENT_DIGIT );
231*b1cdbd2cSJim Jagielski 
232*b1cdbd2cSJim Jagielski 			// the string may end here
233*b1cdbd2cSJim Jagielski 			lcl_insertStopTransition( rRow );
234*b1cdbd2cSJim Jagielski 		}
235*b1cdbd2cSJim Jagielski 
236*b1cdbd2cSJim Jagielski 		// how to procede from END
237*b1cdbd2cSJim Jagielski 		{
238*b1cdbd2cSJim Jagielski 			/*StateTransitions& rRow =*/ m_aTransitions[ EXPONENT_DIGIT ];
239*b1cdbd2cSJim Jagielski 			// no valid transition to leave this state
240*b1cdbd2cSJim Jagielski 			// (note that we, for consistency, nevertheless want to have a row in the table)
241*b1cdbd2cSJim Jagielski 		}
242*b1cdbd2cSJim Jagielski 	}
243*b1cdbd2cSJim Jagielski 
244*b1cdbd2cSJim Jagielski 	//--------------------------------------------------------------------------
implValidateNormalized(const String & _rText)245*b1cdbd2cSJim Jagielski 	sal_Bool NumberValidator::implValidateNormalized( const String& _rText )
246*b1cdbd2cSJim Jagielski 	{
247*b1cdbd2cSJim Jagielski 		const sal_Unicode* pCheckPos = _rText.GetBuffer();
248*b1cdbd2cSJim Jagielski 		State eCurrentState = START;
249*b1cdbd2cSJim Jagielski 
250*b1cdbd2cSJim Jagielski 		while ( END != eCurrentState )
251*b1cdbd2cSJim Jagielski 		{
252*b1cdbd2cSJim Jagielski 			// look up the transition row for the current state
253*b1cdbd2cSJim Jagielski 			TransitionTable::const_iterator aRow = m_aTransitions.find( eCurrentState );
254*b1cdbd2cSJim Jagielski 			DBG_ASSERT( m_aTransitions.end() != aRow,
255*b1cdbd2cSJim Jagielski 				"NumberValidator::implValidateNormalized: invalid transition table (row not found)!" );
256*b1cdbd2cSJim Jagielski 
257*b1cdbd2cSJim Jagielski 			if ( m_aTransitions.end() != aRow )
258*b1cdbd2cSJim Jagielski 			{
259*b1cdbd2cSJim Jagielski 				// look up the current character in this row
260*b1cdbd2cSJim Jagielski 				StateTransitions::const_iterator aTransition = aRow->second.find( *pCheckPos );
261*b1cdbd2cSJim Jagielski 				if ( aRow->second.end() != aTransition )
262*b1cdbd2cSJim Jagielski 				{
263*b1cdbd2cSJim Jagielski 					// there is a valid transition for this character
264*b1cdbd2cSJim Jagielski 					eCurrentState = aTransition->second;
265*b1cdbd2cSJim Jagielski 					++pCheckPos;
266*b1cdbd2cSJim Jagielski 					continue;
267*b1cdbd2cSJim Jagielski 				}
268*b1cdbd2cSJim Jagielski 			}
269*b1cdbd2cSJim Jagielski 
270*b1cdbd2cSJim Jagielski 			// if we're here, there is no valid transition
271*b1cdbd2cSJim Jagielski 			break;
272*b1cdbd2cSJim Jagielski 		}
273*b1cdbd2cSJim Jagielski 
274*b1cdbd2cSJim Jagielski 		DBG_ASSERT( ( END != eCurrentState ) || ( 0 == *pCheckPos ),
275*b1cdbd2cSJim Jagielski 			"NumberValidator::implValidateNormalized: inconsistency!" );
276*b1cdbd2cSJim Jagielski 			// if we're at END, then the string should be done, too - the string should be normalized, means ending
277*b1cdbd2cSJim Jagielski 			// a "_" and not containing any other "_" (except at the start), and "_" is the only possibility
278*b1cdbd2cSJim Jagielski 			// to reach the END state
279*b1cdbd2cSJim Jagielski 
280*b1cdbd2cSJim Jagielski 		// the string is valid if and only if we reached the final state
281*b1cdbd2cSJim Jagielski 		return ( END == eCurrentState );
282*b1cdbd2cSJim Jagielski 	}
283*b1cdbd2cSJim Jagielski 
284*b1cdbd2cSJim Jagielski 	//--------------------------------------------------------------------------
isValidNumericFragment(const String & _rText)285*b1cdbd2cSJim Jagielski 	sal_Bool NumberValidator::isValidNumericFragment( const String& _rText )
286*b1cdbd2cSJim Jagielski 	{
287*b1cdbd2cSJim Jagielski 		if ( !_rText.Len() )
288*b1cdbd2cSJim Jagielski 			// empty strings are always allowed
289*b1cdbd2cSJim Jagielski 			return sal_True;
290*b1cdbd2cSJim Jagielski 
291*b1cdbd2cSJim Jagielski 		// normalize the string
292*b1cdbd2cSJim Jagielski 		String sNormalized( RTL_CONSTASCII_STRINGPARAM( "_") );
293*b1cdbd2cSJim Jagielski 		sNormalized.Append( _rText );
294*b1cdbd2cSJim Jagielski 		sNormalized.AppendAscii( "_" );
295*b1cdbd2cSJim Jagielski 
296*b1cdbd2cSJim Jagielski 		return implValidateNormalized( sNormalized );
297*b1cdbd2cSJim Jagielski 	}
298*b1cdbd2cSJim Jagielski }
299*b1cdbd2cSJim Jagielski 
300*b1cdbd2cSJim Jagielski #endif
301*b1cdbd2cSJim Jagielski 
302*b1cdbd2cSJim Jagielski //==============================================================================
303*b1cdbd2cSJim Jagielski SvNumberFormatter* FormattedField::StaticFormatter::s_cFormatter = NULL;
304*b1cdbd2cSJim Jagielski sal_uLong FormattedField::StaticFormatter::s_nReferences = 0;
305*b1cdbd2cSJim Jagielski 
306*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
GetFormatter()307*b1cdbd2cSJim Jagielski SvNumberFormatter* FormattedField::StaticFormatter::GetFormatter()
308*b1cdbd2cSJim Jagielski {
309*b1cdbd2cSJim Jagielski 	if (!s_cFormatter)
310*b1cdbd2cSJim Jagielski 	{
311*b1cdbd2cSJim Jagielski 		// get the Office's locale and translate
312*b1cdbd2cSJim Jagielski         LanguageType eSysLanguage = MsLangId::convertLocaleToLanguage(
313*b1cdbd2cSJim Jagielski                 SvtSysLocale().GetLocaleData().getLocale() );
314*b1cdbd2cSJim Jagielski 		s_cFormatter = new SvNumberFormatter(
315*b1cdbd2cSJim Jagielski 			::comphelper::getProcessServiceFactory(),
316*b1cdbd2cSJim Jagielski 			eSysLanguage);
317*b1cdbd2cSJim Jagielski 	}
318*b1cdbd2cSJim Jagielski 	return s_cFormatter;
319*b1cdbd2cSJim Jagielski }
320*b1cdbd2cSJim Jagielski 
321*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
StaticFormatter()322*b1cdbd2cSJim Jagielski FormattedField::StaticFormatter::StaticFormatter()
323*b1cdbd2cSJim Jagielski {
324*b1cdbd2cSJim Jagielski 	++s_nReferences;
325*b1cdbd2cSJim Jagielski }
326*b1cdbd2cSJim Jagielski 
327*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
~StaticFormatter()328*b1cdbd2cSJim Jagielski FormattedField::StaticFormatter::~StaticFormatter()
329*b1cdbd2cSJim Jagielski {
330*b1cdbd2cSJim Jagielski 	if (--s_nReferences == 0)
331*b1cdbd2cSJim Jagielski 	{
332*b1cdbd2cSJim Jagielski 		delete s_cFormatter;
333*b1cdbd2cSJim Jagielski 		s_cFormatter = NULL;
334*b1cdbd2cSJim Jagielski 	}
335*b1cdbd2cSJim Jagielski }
336*b1cdbd2cSJim Jagielski 
337*b1cdbd2cSJim Jagielski //==============================================================================
338*b1cdbd2cSJim Jagielski DBG_NAME(FormattedField);
339*b1cdbd2cSJim Jagielski 
340*b1cdbd2cSJim Jagielski #define INIT_MEMBERS()				\
341*b1cdbd2cSJim Jagielski 	 m_aLastSelection(0,0)			\
342*b1cdbd2cSJim Jagielski 	,m_dMinValue(0)					\
343*b1cdbd2cSJim Jagielski 	,m_dMaxValue(0)					\
344*b1cdbd2cSJim Jagielski 	,m_bHasMin(sal_False)				\
345*b1cdbd2cSJim Jagielski 	,m_bHasMax(sal_False)				\
346*b1cdbd2cSJim Jagielski 	,m_bStrictFormat(sal_True)			\
347*b1cdbd2cSJim Jagielski 	,m_bValueDirty(sal_True)			\
348*b1cdbd2cSJim Jagielski 	,m_bEnableEmptyField(sal_True)		\
349*b1cdbd2cSJim Jagielski 	,m_bAutoColor(sal_False)			\
350*b1cdbd2cSJim Jagielski     ,m_bEnableNaN(sal_False)            \
351*b1cdbd2cSJim Jagielski 	,m_dCurrentValue(0)				\
352*b1cdbd2cSJim Jagielski 	,m_dDefaultValue(0)				\
353*b1cdbd2cSJim Jagielski 	,m_nFormatKey(0)				\
354*b1cdbd2cSJim Jagielski 	,m_pFormatter(NULL)				\
355*b1cdbd2cSJim Jagielski 	,m_dSpinSize(1)					\
356*b1cdbd2cSJim Jagielski 	,m_dSpinFirst(-1000000)			\
357*b1cdbd2cSJim Jagielski 	,m_dSpinLast(1000000)			\
358*b1cdbd2cSJim Jagielski 	,m_bTreatAsNumber(sal_True)			\
359*b1cdbd2cSJim Jagielski 	,m_pLastOutputColor(NULL)       \
360*b1cdbd2cSJim Jagielski     ,m_bUseInputStringForFormatting(false)
361*b1cdbd2cSJim Jagielski 
362*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
FormattedField(Window * pParent,WinBits nStyle,SvNumberFormatter * pInitialFormatter,sal_Int32 nFormatKey)363*b1cdbd2cSJim Jagielski FormattedField::FormattedField(Window* pParent, WinBits nStyle, SvNumberFormatter* pInitialFormatter, sal_Int32 nFormatKey)
364*b1cdbd2cSJim Jagielski 	:SpinField(pParent, nStyle)
365*b1cdbd2cSJim Jagielski 	,INIT_MEMBERS()
366*b1cdbd2cSJim Jagielski {
367*b1cdbd2cSJim Jagielski 	DBG_CTOR(FormattedField, NULL);
368*b1cdbd2cSJim Jagielski 
369*b1cdbd2cSJim Jagielski 	if (pInitialFormatter)
370*b1cdbd2cSJim Jagielski 	{
371*b1cdbd2cSJim Jagielski 		m_pFormatter = pInitialFormatter;
372*b1cdbd2cSJim Jagielski 		m_nFormatKey = nFormatKey;
373*b1cdbd2cSJim Jagielski 	}
374*b1cdbd2cSJim Jagielski }
375*b1cdbd2cSJim Jagielski 
376*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
FormattedField(Window * pParent,const ResId & rResId,SvNumberFormatter * pInitialFormatter,sal_Int32 nFormatKey)377*b1cdbd2cSJim Jagielski FormattedField::FormattedField(Window* pParent, const ResId& rResId, SvNumberFormatter* pInitialFormatter, sal_Int32 nFormatKey)
378*b1cdbd2cSJim Jagielski 	:SpinField(pParent, rResId)
379*b1cdbd2cSJim Jagielski 	,INIT_MEMBERS()
380*b1cdbd2cSJim Jagielski {
381*b1cdbd2cSJim Jagielski 	DBG_CTOR(FormattedField, NULL);
382*b1cdbd2cSJim Jagielski 
383*b1cdbd2cSJim Jagielski 	if (pInitialFormatter)
384*b1cdbd2cSJim Jagielski 	{
385*b1cdbd2cSJim Jagielski 		m_pFormatter = pInitialFormatter;
386*b1cdbd2cSJim Jagielski 		m_nFormatKey = nFormatKey;
387*b1cdbd2cSJim Jagielski 	}
388*b1cdbd2cSJim Jagielski }
389*b1cdbd2cSJim Jagielski 
390*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
~FormattedField()391*b1cdbd2cSJim Jagielski FormattedField::~FormattedField()
392*b1cdbd2cSJim Jagielski {
393*b1cdbd2cSJim Jagielski 	DBG_DTOR(FormattedField, NULL);
394*b1cdbd2cSJim Jagielski }
395*b1cdbd2cSJim Jagielski 
396*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
SetValidateText(const XubString & rText,const String * pErrorText)397*b1cdbd2cSJim Jagielski void FormattedField::SetValidateText(const XubString& rText, const String* pErrorText)
398*b1cdbd2cSJim Jagielski {
399*b1cdbd2cSJim Jagielski 	DBG_CHKTHIS(FormattedField, NULL);
400*b1cdbd2cSJim Jagielski 
401*b1cdbd2cSJim Jagielski 	if (CheckText(rText))
402*b1cdbd2cSJim Jagielski 		SetText(rText);
403*b1cdbd2cSJim Jagielski 	else
404*b1cdbd2cSJim Jagielski 		if (pErrorText)
405*b1cdbd2cSJim Jagielski 			ImplSetTextImpl(*pErrorText, NULL);
406*b1cdbd2cSJim Jagielski 		else
407*b1cdbd2cSJim Jagielski 			ImplSetValue(m_dDefaultValue, sal_True);
408*b1cdbd2cSJim Jagielski }
409*b1cdbd2cSJim Jagielski 
410*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
SetText(const XubString & rStr)411*b1cdbd2cSJim Jagielski void FormattedField::SetText(const XubString& rStr)
412*b1cdbd2cSJim Jagielski {
413*b1cdbd2cSJim Jagielski 	DBG_CHKTHIS(FormattedField, NULL);
414*b1cdbd2cSJim Jagielski 
415*b1cdbd2cSJim Jagielski 	SpinField::SetText(rStr);
416*b1cdbd2cSJim Jagielski 	m_bValueDirty = sal_True;
417*b1cdbd2cSJim Jagielski }
418*b1cdbd2cSJim Jagielski 
419*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
SetText(const XubString & rStr,const Selection & rNewSelection)420*b1cdbd2cSJim Jagielski void FormattedField::SetText( const XubString& rStr, const Selection& rNewSelection )
421*b1cdbd2cSJim Jagielski {
422*b1cdbd2cSJim Jagielski 	DBG_CHKTHIS(FormattedField, NULL);
423*b1cdbd2cSJim Jagielski 
424*b1cdbd2cSJim Jagielski 	SpinField::SetText( rStr, rNewSelection );
425*b1cdbd2cSJim Jagielski 	m_bValueDirty = sal_True;
426*b1cdbd2cSJim Jagielski }
427*b1cdbd2cSJim Jagielski 
428*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
SetTextFormatted(const XubString & rStr)429*b1cdbd2cSJim Jagielski void FormattedField::SetTextFormatted(const XubString& rStr)
430*b1cdbd2cSJim Jagielski {
431*b1cdbd2cSJim Jagielski 	DBG_CHKTHIS(FormattedField, NULL);
432*b1cdbd2cSJim Jagielski 
433*b1cdbd2cSJim Jagielski #if defined DBG_UTIL
434*b1cdbd2cSJim Jagielski 	if (ImplGetFormatter()->IsTextFormat(m_nFormatKey))
435*b1cdbd2cSJim Jagielski 		 DBG_WARNING("FormattedField::SetTextFormatted : valid only with text formats !");
436*b1cdbd2cSJim Jagielski #endif
437*b1cdbd2cSJim Jagielski 
438*b1cdbd2cSJim Jagielski 	m_sCurrentTextValue = rStr;
439*b1cdbd2cSJim Jagielski 
440*b1cdbd2cSJim Jagielski 	String sFormatted;
441*b1cdbd2cSJim Jagielski     double dNumber = 0.0;
442*b1cdbd2cSJim Jagielski     // IsNumberFormat changes the format key parameter
443*b1cdbd2cSJim Jagielski     sal_uInt32 nTempFormatKey = static_cast< sal_uInt32 >( m_nFormatKey );
444*b1cdbd2cSJim Jagielski     if( IsUsingInputStringForFormatting() &&
445*b1cdbd2cSJim Jagielski         ImplGetFormatter()->IsNumberFormat(m_sCurrentTextValue, nTempFormatKey, dNumber) )
446*b1cdbd2cSJim Jagielski         ImplGetFormatter()->GetInputLineString(dNumber, m_nFormatKey, sFormatted);
447*b1cdbd2cSJim Jagielski     else
448*b1cdbd2cSJim Jagielski         ImplGetFormatter()->GetOutputString(m_sCurrentTextValue, m_nFormatKey, sFormatted, &m_pLastOutputColor);
449*b1cdbd2cSJim Jagielski 
450*b1cdbd2cSJim Jagielski 	// calculate the new selection
451*b1cdbd2cSJim Jagielski 	Selection aSel(GetSelection());
452*b1cdbd2cSJim Jagielski 	Selection aNewSel(aSel);
453*b1cdbd2cSJim Jagielski 	aNewSel.Justify();
454*b1cdbd2cSJim Jagielski 	sal_uInt16 nNewLen = sFormatted.Len();
455*b1cdbd2cSJim Jagielski 	sal_uInt16 nCurrentLen = GetText().Len();
456*b1cdbd2cSJim Jagielski 	if ((nNewLen > nCurrentLen) && (aNewSel.Max() == nCurrentLen))
457*b1cdbd2cSJim Jagielski 	{	// the new text is longer and the cursor was behind the last char (of the old text)
458*b1cdbd2cSJim Jagielski 		if (aNewSel.Min() == 0)
459*b1cdbd2cSJim Jagielski 		{	// the whole text was selected -> select the new text on the whole, too
460*b1cdbd2cSJim Jagielski 			aNewSel.Max() = nNewLen;
461*b1cdbd2cSJim Jagielski 			if (!nCurrentLen)
462*b1cdbd2cSJim Jagielski 			{	// there wasn't really a previous selection (as there was no previous text), we're setting a new one -> check the selection options
463*b1cdbd2cSJim Jagielski 				sal_uLong nSelOptions = GetSettings().GetStyleSettings().GetSelectionOptions();
464*b1cdbd2cSJim Jagielski 				if (nSelOptions & SELECTION_OPTION_SHOWFIRST)
465*b1cdbd2cSJim Jagielski 				{	// selection should be from right to left -> swap min and max
466*b1cdbd2cSJim Jagielski 					aNewSel.Min() = aNewSel.Max();
467*b1cdbd2cSJim Jagielski 					aNewSel.Max() = 0;
468*b1cdbd2cSJim Jagielski 				}
469*b1cdbd2cSJim Jagielski 			}
470*b1cdbd2cSJim Jagielski 		}
471*b1cdbd2cSJim Jagielski 		else if (aNewSel.Max() == aNewSel.Min())
472*b1cdbd2cSJim Jagielski 		{	// there was no selection -> set the cursor behind the new last char
473*b1cdbd2cSJim Jagielski 			aNewSel.Max() = nNewLen;
474*b1cdbd2cSJim Jagielski 			aNewSel.Min() = nNewLen;
475*b1cdbd2cSJim Jagielski 		}
476*b1cdbd2cSJim Jagielski 	}
477*b1cdbd2cSJim Jagielski 	else if (aNewSel.Max() > nNewLen)
478*b1cdbd2cSJim Jagielski 		aNewSel.Max() = nNewLen;
479*b1cdbd2cSJim Jagielski 	else
480*b1cdbd2cSJim Jagielski 		aNewSel = aSel;	// don't use the justified version
481*b1cdbd2cSJim Jagielski 	SpinField::SetText(sFormatted, aNewSel);
482*b1cdbd2cSJim Jagielski 	m_bValueDirty = sal_False;
483*b1cdbd2cSJim Jagielski }
484*b1cdbd2cSJim Jagielski 
485*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
GetTextValue() const486*b1cdbd2cSJim Jagielski String FormattedField::GetTextValue() const
487*b1cdbd2cSJim Jagielski {
488*b1cdbd2cSJim Jagielski 	if (m_bValueDirty)
489*b1cdbd2cSJim Jagielski 	{
490*b1cdbd2cSJim Jagielski 		((FormattedField*)this)->m_sCurrentTextValue = GetText();
491*b1cdbd2cSJim Jagielski 		((FormattedField*)this)->m_bValueDirty = sal_False;
492*b1cdbd2cSJim Jagielski 	}
493*b1cdbd2cSJim Jagielski 	return m_sCurrentTextValue;
494*b1cdbd2cSJim Jagielski }
495*b1cdbd2cSJim Jagielski 
496*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
EnableNotANumber(sal_Bool _bEnable)497*b1cdbd2cSJim Jagielski void FormattedField::EnableNotANumber( sal_Bool _bEnable )
498*b1cdbd2cSJim Jagielski {
499*b1cdbd2cSJim Jagielski     if ( m_bEnableNaN == _bEnable )
500*b1cdbd2cSJim Jagielski         return;
501*b1cdbd2cSJim Jagielski 
502*b1cdbd2cSJim Jagielski     m_bEnableNaN = _bEnable;
503*b1cdbd2cSJim Jagielski }
504*b1cdbd2cSJim Jagielski 
505*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
SetAutoColor(sal_Bool _bAutomatic)506*b1cdbd2cSJim Jagielski void FormattedField::SetAutoColor(sal_Bool _bAutomatic)
507*b1cdbd2cSJim Jagielski {
508*b1cdbd2cSJim Jagielski 	if (_bAutomatic == m_bAutoColor)
509*b1cdbd2cSJim Jagielski 		return;
510*b1cdbd2cSJim Jagielski 
511*b1cdbd2cSJim Jagielski 	m_bAutoColor = _bAutomatic;
512*b1cdbd2cSJim Jagielski 	if (m_bAutoColor)
513*b1cdbd2cSJim Jagielski 	{	// if auto color is switched on, adjust the current text color, too
514*b1cdbd2cSJim Jagielski 		if (m_pLastOutputColor)
515*b1cdbd2cSJim Jagielski 			SetControlForeground(*m_pLastOutputColor);
516*b1cdbd2cSJim Jagielski 		else
517*b1cdbd2cSJim Jagielski 			SetControlForeground();
518*b1cdbd2cSJim Jagielski 	}
519*b1cdbd2cSJim Jagielski }
520*b1cdbd2cSJim Jagielski 
521*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
Modify()522*b1cdbd2cSJim Jagielski void FormattedField::Modify()
523*b1cdbd2cSJim Jagielski {
524*b1cdbd2cSJim Jagielski 	DBG_CHKTHIS(FormattedField, NULL);
525*b1cdbd2cSJim Jagielski 
526*b1cdbd2cSJim Jagielski 	if (!IsStrictFormat())
527*b1cdbd2cSJim Jagielski 	{
528*b1cdbd2cSJim Jagielski 		m_bValueDirty = sal_True;
529*b1cdbd2cSJim Jagielski 		SpinField::Modify();
530*b1cdbd2cSJim Jagielski 		return;
531*b1cdbd2cSJim Jagielski 	}
532*b1cdbd2cSJim Jagielski 
533*b1cdbd2cSJim Jagielski 	String sCheck = GetText();
534*b1cdbd2cSJim Jagielski 	if (CheckText(sCheck))
535*b1cdbd2cSJim Jagielski 	{
536*b1cdbd2cSJim Jagielski 		m_sLastValidText = sCheck;
537*b1cdbd2cSJim Jagielski 		m_aLastSelection = GetSelection();
538*b1cdbd2cSJim Jagielski 		m_bValueDirty = sal_True;
539*b1cdbd2cSJim Jagielski 	}
540*b1cdbd2cSJim Jagielski 	else
541*b1cdbd2cSJim Jagielski 	{
542*b1cdbd2cSJim Jagielski 		ImplSetTextImpl(m_sLastValidText, &m_aLastSelection);
543*b1cdbd2cSJim Jagielski 	}
544*b1cdbd2cSJim Jagielski 
545*b1cdbd2cSJim Jagielski 	SpinField::Modify();
546*b1cdbd2cSJim Jagielski }
547*b1cdbd2cSJim Jagielski 
548*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
ImplSetTextImpl(const XubString & rNew,Selection * pNewSel)549*b1cdbd2cSJim Jagielski void FormattedField::ImplSetTextImpl(const XubString& rNew, Selection* pNewSel)
550*b1cdbd2cSJim Jagielski {
551*b1cdbd2cSJim Jagielski 	DBG_CHKTHIS(FormattedField, NULL);
552*b1cdbd2cSJim Jagielski 
553*b1cdbd2cSJim Jagielski 	if (m_bAutoColor)
554*b1cdbd2cSJim Jagielski 	{
555*b1cdbd2cSJim Jagielski 		if (m_pLastOutputColor)
556*b1cdbd2cSJim Jagielski 			SetControlForeground(*m_pLastOutputColor);
557*b1cdbd2cSJim Jagielski 		else
558*b1cdbd2cSJim Jagielski 			SetControlForeground();
559*b1cdbd2cSJim Jagielski 	}
560*b1cdbd2cSJim Jagielski 
561*b1cdbd2cSJim Jagielski 	if (pNewSel)
562*b1cdbd2cSJim Jagielski 		SpinField::SetText(rNew, *pNewSel);
563*b1cdbd2cSJim Jagielski 	else
564*b1cdbd2cSJim Jagielski 	{
565*b1cdbd2cSJim Jagielski 		Selection aSel(GetSelection());
566*b1cdbd2cSJim Jagielski 		aSel.Justify();
567*b1cdbd2cSJim Jagielski 
568*b1cdbd2cSJim Jagielski 		sal_uInt16 nNewLen = rNew.Len();
569*b1cdbd2cSJim Jagielski 		sal_uInt16 nCurrentLen = GetText().Len();
570*b1cdbd2cSJim Jagielski 
571*b1cdbd2cSJim Jagielski 		if ((nNewLen > nCurrentLen) && (aSel.Max() == nCurrentLen))
572*b1cdbd2cSJim Jagielski 		{	// new new text is longer and the cursor is behind the last char
573*b1cdbd2cSJim Jagielski 			if (aSel.Min() == 0)
574*b1cdbd2cSJim Jagielski 			{	// the whole text was selected -> select the new text on the whole, too
575*b1cdbd2cSJim Jagielski 				aSel.Max() = nNewLen;
576*b1cdbd2cSJim Jagielski 				if (!nCurrentLen)
577*b1cdbd2cSJim Jagielski 				{	// there wasn't really a previous selection (as there was no previous text), we're setting a new one -> check the selection options
578*b1cdbd2cSJim Jagielski 					sal_uLong nSelOptions = GetSettings().GetStyleSettings().GetSelectionOptions();
579*b1cdbd2cSJim Jagielski 					if (nSelOptions & SELECTION_OPTION_SHOWFIRST)
580*b1cdbd2cSJim Jagielski 					{	// selection should be from right to left -> swap min and max
581*b1cdbd2cSJim Jagielski 						aSel.Min() = aSel.Max();
582*b1cdbd2cSJim Jagielski 						aSel.Max() = 0;
583*b1cdbd2cSJim Jagielski 					}
584*b1cdbd2cSJim Jagielski 				}
585*b1cdbd2cSJim Jagielski 			}
586*b1cdbd2cSJim Jagielski 			else if (aSel.Max() == aSel.Min())
587*b1cdbd2cSJim Jagielski 			{	// there was no selection -> set the cursor behind the new last char
588*b1cdbd2cSJim Jagielski 				aSel.Max() = nNewLen;
589*b1cdbd2cSJim Jagielski 				aSel.Min() = nNewLen;
590*b1cdbd2cSJim Jagielski 			}
591*b1cdbd2cSJim Jagielski 		}
592*b1cdbd2cSJim Jagielski 		else if (aSel.Max() > nNewLen)
593*b1cdbd2cSJim Jagielski 			aSel.Max() = nNewLen;
594*b1cdbd2cSJim Jagielski 		SpinField::SetText(rNew, aSel);
595*b1cdbd2cSJim Jagielski 	}
596*b1cdbd2cSJim Jagielski 
597*b1cdbd2cSJim Jagielski 	m_bValueDirty = sal_True;
598*b1cdbd2cSJim Jagielski 		// muss nicht stimmen, aber sicherheitshalber ...
599*b1cdbd2cSJim Jagielski }
600*b1cdbd2cSJim Jagielski 
601*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
PreNotify(NotifyEvent & rNEvt)602*b1cdbd2cSJim Jagielski long FormattedField::PreNotify(NotifyEvent& rNEvt)
603*b1cdbd2cSJim Jagielski {
604*b1cdbd2cSJim Jagielski 	DBG_CHKTHIS(FormattedField, NULL);
605*b1cdbd2cSJim Jagielski 	if (rNEvt.GetType() == EVENT_KEYINPUT)
606*b1cdbd2cSJim Jagielski 		m_aLastSelection = GetSelection();
607*b1cdbd2cSJim Jagielski 	return SpinField::PreNotify(rNEvt);
608*b1cdbd2cSJim Jagielski }
609*b1cdbd2cSJim Jagielski 
610*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
ImplSetFormatKey(sal_uLong nFormatKey)611*b1cdbd2cSJim Jagielski void FormattedField::ImplSetFormatKey(sal_uLong nFormatKey)
612*b1cdbd2cSJim Jagielski {
613*b1cdbd2cSJim Jagielski 	DBG_CHKTHIS(FormattedField, NULL);
614*b1cdbd2cSJim Jagielski 
615*b1cdbd2cSJim Jagielski 	m_nFormatKey = nFormatKey;
616*b1cdbd2cSJim Jagielski 	sal_Bool bNeedFormatter = (m_pFormatter == NULL) && (nFormatKey != 0);
617*b1cdbd2cSJim Jagielski 	if (bNeedFormatter)
618*b1cdbd2cSJim Jagielski 	{
619*b1cdbd2cSJim Jagielski 		ImplGetFormatter();		// damit wird ein Standard-Formatter angelegt
620*b1cdbd2cSJim Jagielski 
621*b1cdbd2cSJim Jagielski 		m_nFormatKey = nFormatKey;
622*b1cdbd2cSJim Jagielski 			// kann sein, dass das in dem Standard-Formatter keinen Sinn macht, aber der nimmt dann ein Default-Format an.
623*b1cdbd2cSJim Jagielski 			// Auf diese Weise kann ich einfach einen der - formatteruebergreifended gleichen - Standard-Keys setzen.
624*b1cdbd2cSJim Jagielski 		DBG_ASSERT(m_pFormatter->GetEntry(nFormatKey) != NULL, "FormattedField::ImplSetFormatKey : invalid format key !");
625*b1cdbd2cSJim Jagielski 			// Wenn SetFormatKey aufgerufen wird, ohne dass ein Formatter existiert, muss der Key einer der Standard-Werte
626*b1cdbd2cSJim Jagielski 			// sein, der in allen Formattern (also auch in meinem neu angelegten) vorhanden ist.
627*b1cdbd2cSJim Jagielski 	}
628*b1cdbd2cSJim Jagielski }
629*b1cdbd2cSJim Jagielski 
630*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
SetFormatKey(sal_uLong nFormatKey)631*b1cdbd2cSJim Jagielski void FormattedField::SetFormatKey(sal_uLong nFormatKey)
632*b1cdbd2cSJim Jagielski {
633*b1cdbd2cSJim Jagielski 	DBG_CHKTHIS(FormattedField, NULL);
634*b1cdbd2cSJim Jagielski 	sal_Bool bNoFormatter = (m_pFormatter == NULL);
635*b1cdbd2cSJim Jagielski 	ImplSetFormatKey(nFormatKey);
636*b1cdbd2cSJim Jagielski 	FormatChanged((bNoFormatter && (m_pFormatter != NULL)) ? FCT_FORMATTER : FCT_KEYONLY);
637*b1cdbd2cSJim Jagielski }
638*b1cdbd2cSJim Jagielski 
639*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
SetFormatter(SvNumberFormatter * pFormatter,sal_Bool bResetFormat)640*b1cdbd2cSJim Jagielski void FormattedField::SetFormatter(SvNumberFormatter* pFormatter, sal_Bool bResetFormat)
641*b1cdbd2cSJim Jagielski {
642*b1cdbd2cSJim Jagielski 	DBG_CHKTHIS(FormattedField, NULL);
643*b1cdbd2cSJim Jagielski 
644*b1cdbd2cSJim Jagielski 	if (bResetFormat)
645*b1cdbd2cSJim Jagielski 	{
646*b1cdbd2cSJim Jagielski 		m_pFormatter = pFormatter;
647*b1cdbd2cSJim Jagielski 
648*b1cdbd2cSJim Jagielski 		// calc the default format key from the Office's UI locale
649*b1cdbd2cSJim Jagielski 		if ( m_pFormatter )
650*b1cdbd2cSJim Jagielski 		{
651*b1cdbd2cSJim Jagielski 			// get the Office's locale and translate
652*b1cdbd2cSJim Jagielski             LanguageType eSysLanguage = MsLangId::convertLocaleToLanguage(
653*b1cdbd2cSJim Jagielski                     SvtSysLocale().GetLocaleData().getLocale() );
654*b1cdbd2cSJim Jagielski 			// get the standard numeric format for this language
655*b1cdbd2cSJim Jagielski 			m_nFormatKey = m_pFormatter->GetStandardFormat( NUMBERFORMAT_NUMBER, eSysLanguage );
656*b1cdbd2cSJim Jagielski 		}
657*b1cdbd2cSJim Jagielski 		else
658*b1cdbd2cSJim Jagielski 			m_nFormatKey = 0;
659*b1cdbd2cSJim Jagielski 	}
660*b1cdbd2cSJim Jagielski 	else
661*b1cdbd2cSJim Jagielski 	{
662*b1cdbd2cSJim Jagielski 		XubString sOldFormat;
663*b1cdbd2cSJim Jagielski 		LanguageType aOldLang;
664*b1cdbd2cSJim Jagielski 		GetFormat(sOldFormat, aOldLang);
665*b1cdbd2cSJim Jagielski 
666*b1cdbd2cSJim Jagielski 		sal_uInt32 nDestKey = pFormatter->TestNewString(sOldFormat);
667*b1cdbd2cSJim Jagielski 		if (nDestKey == NUMBERFORMAT_ENTRY_NOT_FOUND)
668*b1cdbd2cSJim Jagielski 		{
669*b1cdbd2cSJim Jagielski 			// die Sprache des neuen Formatters
670*b1cdbd2cSJim Jagielski 			const SvNumberformat* pDefaultEntry = pFormatter->GetEntry(0);
671*b1cdbd2cSJim Jagielski 			LanguageType aNewLang = pDefaultEntry ? pDefaultEntry->GetLanguage() : LANGUAGE_DONTKNOW;
672*b1cdbd2cSJim Jagielski 
673*b1cdbd2cSJim Jagielski 			// den alten Format-String in die neue Sprache konvertieren
674*b1cdbd2cSJim Jagielski 			sal_uInt16 nCheckPos;
675*b1cdbd2cSJim Jagielski 			short nType;
676*b1cdbd2cSJim Jagielski 			pFormatter->PutandConvertEntry(sOldFormat, nCheckPos, nType, nDestKey, aOldLang, aNewLang);
677*b1cdbd2cSJim Jagielski 			m_nFormatKey = nDestKey;
678*b1cdbd2cSJim Jagielski 		}
679*b1cdbd2cSJim Jagielski 		m_pFormatter = pFormatter;
680*b1cdbd2cSJim Jagielski 	}
681*b1cdbd2cSJim Jagielski 
682*b1cdbd2cSJim Jagielski 	FormatChanged(FCT_FORMATTER);
683*b1cdbd2cSJim Jagielski }
684*b1cdbd2cSJim Jagielski 
685*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
GetFormat(XubString & rFormatString,LanguageType & eLang) const686*b1cdbd2cSJim Jagielski void FormattedField::GetFormat(XubString& rFormatString, LanguageType& eLang) const
687*b1cdbd2cSJim Jagielski {
688*b1cdbd2cSJim Jagielski 	DBG_CHKTHIS(FormattedField, NULL);
689*b1cdbd2cSJim Jagielski 	const SvNumberformat* pFormatEntry = ImplGetFormatter()->GetEntry(m_nFormatKey);
690*b1cdbd2cSJim Jagielski 	DBG_ASSERT(pFormatEntry != NULL, "FormattedField::GetFormat: no number format for the given format key.");
691*b1cdbd2cSJim Jagielski 	rFormatString = pFormatEntry ? pFormatEntry->GetFormatstring() : XubString();
692*b1cdbd2cSJim Jagielski 	eLang = pFormatEntry ? pFormatEntry->GetLanguage() : LANGUAGE_DONTKNOW;
693*b1cdbd2cSJim Jagielski }
694*b1cdbd2cSJim Jagielski 
695*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
SetFormat(const XubString & rFormatString,LanguageType eLang)696*b1cdbd2cSJim Jagielski sal_Bool FormattedField::SetFormat(const XubString& rFormatString, LanguageType eLang)
697*b1cdbd2cSJim Jagielski {
698*b1cdbd2cSJim Jagielski 	DBG_CHKTHIS(FormattedField, NULL);
699*b1cdbd2cSJim Jagielski 	sal_uInt32 nNewKey = ImplGetFormatter()->TestNewString(rFormatString, eLang);
700*b1cdbd2cSJim Jagielski 	if (nNewKey == NUMBERFORMAT_ENTRY_NOT_FOUND)
701*b1cdbd2cSJim Jagielski 	{
702*b1cdbd2cSJim Jagielski 		sal_uInt16 nCheckPos;
703*b1cdbd2cSJim Jagielski 		short nType;
704*b1cdbd2cSJim Jagielski 		XubString rFormat(rFormatString);
705*b1cdbd2cSJim Jagielski 		if (!ImplGetFormatter()->PutEntry(rFormat, nCheckPos, nType, nNewKey, eLang))
706*b1cdbd2cSJim Jagielski 			return sal_False;
707*b1cdbd2cSJim Jagielski 		DBG_ASSERT(nNewKey != NUMBERFORMAT_ENTRY_NOT_FOUND, "FormattedField::SetFormatString : PutEntry returned an invalid key !");
708*b1cdbd2cSJim Jagielski 	}
709*b1cdbd2cSJim Jagielski 
710*b1cdbd2cSJim Jagielski 	if (nNewKey != m_nFormatKey)
711*b1cdbd2cSJim Jagielski 		SetFormatKey(nNewKey);
712*b1cdbd2cSJim Jagielski 	return sal_True;
713*b1cdbd2cSJim Jagielski }
714*b1cdbd2cSJim Jagielski 
715*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
GetThousandsSep() const716*b1cdbd2cSJim Jagielski sal_Bool FormattedField::GetThousandsSep() const
717*b1cdbd2cSJim Jagielski {
718*b1cdbd2cSJim Jagielski 	DBG_ASSERT(!ImplGetFormatter()->IsTextFormat(m_nFormatKey),
719*b1cdbd2cSJim Jagielski 		"FormattedField::GetThousandsSep : your'e sure what your'e doing when setting the precision of a text format ?");
720*b1cdbd2cSJim Jagielski 
721*b1cdbd2cSJim Jagielski 	sal_Bool bThousand, IsRed;
722*b1cdbd2cSJim Jagielski 	sal_uInt16 nPrecision, nAnzLeading;
723*b1cdbd2cSJim Jagielski 	ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nAnzLeading);
724*b1cdbd2cSJim Jagielski 
725*b1cdbd2cSJim Jagielski 	return bThousand;
726*b1cdbd2cSJim Jagielski }
727*b1cdbd2cSJim Jagielski 
728*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
SetThousandsSep(sal_Bool _bUseSeparator)729*b1cdbd2cSJim Jagielski void FormattedField::SetThousandsSep(sal_Bool _bUseSeparator)
730*b1cdbd2cSJim Jagielski {
731*b1cdbd2cSJim Jagielski 	DBG_ASSERT(!ImplGetFormatter()->IsTextFormat(m_nFormatKey),
732*b1cdbd2cSJim Jagielski 		"FormattedField::SetThousandsSep : your'e sure what your'e doing when setting the precision of a text format ?");
733*b1cdbd2cSJim Jagielski 
734*b1cdbd2cSJim Jagielski 	// get the current settings
735*b1cdbd2cSJim Jagielski 	sal_Bool bThousand, IsRed;
736*b1cdbd2cSJim Jagielski 	sal_uInt16 nPrecision, nAnzLeading;
737*b1cdbd2cSJim Jagielski 	ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nAnzLeading);
738*b1cdbd2cSJim Jagielski 	if (bThousand == _bUseSeparator)
739*b1cdbd2cSJim Jagielski 		return;
740*b1cdbd2cSJim Jagielski 
741*b1cdbd2cSJim Jagielski 	// we need the language for the following
742*b1cdbd2cSJim Jagielski 	LanguageType eLang;
743*b1cdbd2cSJim Jagielski 	String sFmtDescription;
744*b1cdbd2cSJim Jagielski 	GetFormat(sFmtDescription, eLang);
745*b1cdbd2cSJim Jagielski 
746*b1cdbd2cSJim Jagielski 	// generate a new format ...
747*b1cdbd2cSJim Jagielski 	ImplGetFormatter()->GenerateFormat(sFmtDescription, m_nFormatKey, eLang, _bUseSeparator, IsRed, nPrecision, nAnzLeading);
748*b1cdbd2cSJim Jagielski 	// ... and introduce it to the formatter
749*b1cdbd2cSJim Jagielski 	sal_uInt16 nCheckPos;
750*b1cdbd2cSJim Jagielski 	sal_uInt32  nNewKey;
751*b1cdbd2cSJim Jagielski 	short nType;
752*b1cdbd2cSJim Jagielski 	ImplGetFormatter()->PutEntry(sFmtDescription, nCheckPos, nType, nNewKey, eLang);
753*b1cdbd2cSJim Jagielski 
754*b1cdbd2cSJim Jagielski 	// set the new key
755*b1cdbd2cSJim Jagielski 	ImplSetFormatKey(nNewKey);
756*b1cdbd2cSJim Jagielski 	FormatChanged(FCT_THOUSANDSSEP);
757*b1cdbd2cSJim Jagielski }
758*b1cdbd2cSJim Jagielski 
759*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
GetDecimalDigits() const760*b1cdbd2cSJim Jagielski sal_uInt16 FormattedField::GetDecimalDigits() const
761*b1cdbd2cSJim Jagielski {
762*b1cdbd2cSJim Jagielski 	DBG_ASSERT(!ImplGetFormatter()->IsTextFormat(m_nFormatKey),
763*b1cdbd2cSJim Jagielski 		"FormattedField::GetDecimalDigits : your'e sure what your'e doing when setting the precision of a text format ?");
764*b1cdbd2cSJim Jagielski 
765*b1cdbd2cSJim Jagielski 	sal_Bool bThousand, IsRed;
766*b1cdbd2cSJim Jagielski 	sal_uInt16 nPrecision, nAnzLeading;
767*b1cdbd2cSJim Jagielski 	ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nAnzLeading);
768*b1cdbd2cSJim Jagielski 
769*b1cdbd2cSJim Jagielski 	return nPrecision;
770*b1cdbd2cSJim Jagielski }
771*b1cdbd2cSJim Jagielski 
772*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
SetDecimalDigits(sal_uInt16 _nPrecision)773*b1cdbd2cSJim Jagielski void FormattedField::SetDecimalDigits(sal_uInt16 _nPrecision)
774*b1cdbd2cSJim Jagielski {
775*b1cdbd2cSJim Jagielski 	DBG_ASSERT(!ImplGetFormatter()->IsTextFormat(m_nFormatKey),
776*b1cdbd2cSJim Jagielski 		"FormattedField::SetDecimalDigits : your'e sure what your'e doing when setting the precision of a text format ?");
777*b1cdbd2cSJim Jagielski 
778*b1cdbd2cSJim Jagielski 	// get the current settings
779*b1cdbd2cSJim Jagielski 	sal_Bool bThousand, IsRed;
780*b1cdbd2cSJim Jagielski 	sal_uInt16 nPrecision, nAnzLeading;
781*b1cdbd2cSJim Jagielski 	ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nAnzLeading);
782*b1cdbd2cSJim Jagielski 	if (nPrecision == _nPrecision)
783*b1cdbd2cSJim Jagielski 		return;
784*b1cdbd2cSJim Jagielski 
785*b1cdbd2cSJim Jagielski 	// we need the language for the following
786*b1cdbd2cSJim Jagielski 	LanguageType eLang;
787*b1cdbd2cSJim Jagielski 	String sFmtDescription;
788*b1cdbd2cSJim Jagielski 	GetFormat(sFmtDescription, eLang);
789*b1cdbd2cSJim Jagielski 
790*b1cdbd2cSJim Jagielski 	// generate a new format ...
791*b1cdbd2cSJim Jagielski 	ImplGetFormatter()->GenerateFormat(sFmtDescription, m_nFormatKey, eLang, bThousand, IsRed, _nPrecision, nAnzLeading);
792*b1cdbd2cSJim Jagielski 	// ... and introduce it to the formatter
793*b1cdbd2cSJim Jagielski 	sal_uInt16 nCheckPos;
794*b1cdbd2cSJim Jagielski 	sal_uInt32 nNewKey;
795*b1cdbd2cSJim Jagielski 	short nType;
796*b1cdbd2cSJim Jagielski 	ImplGetFormatter()->PutEntry(sFmtDescription, nCheckPos, nType, nNewKey, eLang);
797*b1cdbd2cSJim Jagielski 
798*b1cdbd2cSJim Jagielski 	// set the new key
799*b1cdbd2cSJim Jagielski 	ImplSetFormatKey(nNewKey);
800*b1cdbd2cSJim Jagielski 	FormatChanged(FCT_PRECISION);
801*b1cdbd2cSJim Jagielski }
802*b1cdbd2cSJim Jagielski 
803*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
FormatChanged(FORMAT_CHANGE_TYPE _nWhat)804*b1cdbd2cSJim Jagielski void FormattedField::FormatChanged( FORMAT_CHANGE_TYPE _nWhat )
805*b1cdbd2cSJim Jagielski {
806*b1cdbd2cSJim Jagielski 	DBG_CHKTHIS(FormattedField, NULL);
807*b1cdbd2cSJim Jagielski 	m_pLastOutputColor = NULL;
808*b1cdbd2cSJim Jagielski 
809*b1cdbd2cSJim Jagielski 	if ( ( 0 != ( _nWhat & FCT_FORMATTER ) ) && m_pFormatter )
810*b1cdbd2cSJim Jagielski 		m_pFormatter->SetEvalDateFormat( NF_EVALDATEFORMAT_INTL_FORMAT );
811*b1cdbd2cSJim Jagielski 		// 95845 - 03.04.2002 - fs@openoffice.org
812*b1cdbd2cSJim Jagielski 
813*b1cdbd2cSJim Jagielski 	ReFormat();
814*b1cdbd2cSJim Jagielski }
815*b1cdbd2cSJim Jagielski 
816*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
Commit()817*b1cdbd2cSJim Jagielski void FormattedField::Commit()
818*b1cdbd2cSJim Jagielski {
819*b1cdbd2cSJim Jagielski 	// remember the old text
820*b1cdbd2cSJim Jagielski 	String sOld( GetText() );
821*b1cdbd2cSJim Jagielski 
822*b1cdbd2cSJim Jagielski 	// do the reformat
823*b1cdbd2cSJim Jagielski 	ReFormat();
824*b1cdbd2cSJim Jagielski 
825*b1cdbd2cSJim Jagielski 	// did the text change?
826*b1cdbd2cSJim Jagielski 	if ( GetText() != sOld )
827*b1cdbd2cSJim Jagielski 	{	// consider the field as modified
828*b1cdbd2cSJim Jagielski 		Modify();
829*b1cdbd2cSJim Jagielski 		// but we have the most recent value now
830*b1cdbd2cSJim Jagielski 		m_bValueDirty = sal_False;
831*b1cdbd2cSJim Jagielski 	}
832*b1cdbd2cSJim Jagielski }
833*b1cdbd2cSJim Jagielski 
834*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
ReFormat()835*b1cdbd2cSJim Jagielski void FormattedField::ReFormat()
836*b1cdbd2cSJim Jagielski {
837*b1cdbd2cSJim Jagielski 	if (!IsEmptyFieldEnabled() || GetText().Len())
838*b1cdbd2cSJim Jagielski 	{
839*b1cdbd2cSJim Jagielski 		if (TreatingAsNumber())
840*b1cdbd2cSJim Jagielski         {
841*b1cdbd2cSJim Jagielski             double dValue = GetValue();
842*b1cdbd2cSJim Jagielski             if ( m_bEnableNaN && ::rtl::math::isNan( dValue ) )
843*b1cdbd2cSJim Jagielski                 return;
844*b1cdbd2cSJim Jagielski 			ImplSetValue( dValue, sal_True );
845*b1cdbd2cSJim Jagielski         }
846*b1cdbd2cSJim Jagielski 		else
847*b1cdbd2cSJim Jagielski 			SetTextFormatted(GetTextValue());
848*b1cdbd2cSJim Jagielski 	}
849*b1cdbd2cSJim Jagielski }
850*b1cdbd2cSJim Jagielski 
851*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
Notify(NotifyEvent & rNEvt)852*b1cdbd2cSJim Jagielski long FormattedField::Notify(NotifyEvent& rNEvt)
853*b1cdbd2cSJim Jagielski {
854*b1cdbd2cSJim Jagielski 	DBG_CHKTHIS(FormattedField, NULL);
855*b1cdbd2cSJim Jagielski 
856*b1cdbd2cSJim Jagielski 	if ((rNEvt.GetType() == EVENT_KEYINPUT) && !IsReadOnly())
857*b1cdbd2cSJim Jagielski 	{
858*b1cdbd2cSJim Jagielski 		const KeyEvent& rKEvt = *rNEvt.GetKeyEvent();
859*b1cdbd2cSJim Jagielski 		sal_uInt16 nMod = rKEvt.GetKeyCode().GetModifier();
860*b1cdbd2cSJim Jagielski 		switch ( rKEvt.GetKeyCode().GetCode() )
861*b1cdbd2cSJim Jagielski 		{
862*b1cdbd2cSJim Jagielski 			case KEY_UP:
863*b1cdbd2cSJim Jagielski 			case KEY_DOWN:
864*b1cdbd2cSJim Jagielski 			case KEY_PAGEUP:
865*b1cdbd2cSJim Jagielski 			case KEY_PAGEDOWN:
866*b1cdbd2cSJim Jagielski 				if (!nMod && ImplGetFormatter()->IsTextFormat(m_nFormatKey))
867*b1cdbd2cSJim Jagielski 				{
868*b1cdbd2cSJim Jagielski 					// the base class would translate this into calls to Up/Down/First/Last,
869*b1cdbd2cSJim Jagielski 					// but we don't want this if we are text-formatted
870*b1cdbd2cSJim Jagielski 					return 1;
871*b1cdbd2cSJim Jagielski 				}
872*b1cdbd2cSJim Jagielski 		}
873*b1cdbd2cSJim Jagielski 	}
874*b1cdbd2cSJim Jagielski 
875*b1cdbd2cSJim Jagielski 	if ((rNEvt.GetType() == EVENT_COMMAND) && !IsReadOnly())
876*b1cdbd2cSJim Jagielski 	{
877*b1cdbd2cSJim Jagielski 		const CommandEvent* pCommand = rNEvt.GetCommandEvent();
878*b1cdbd2cSJim Jagielski 		if (pCommand->GetCommand() == COMMAND_WHEEL)
879*b1cdbd2cSJim Jagielski 		{
880*b1cdbd2cSJim Jagielski 			const CommandWheelData* pData = rNEvt.GetCommandEvent()->GetWheelData();
881*b1cdbd2cSJim Jagielski 			if ((pData->GetMode() == COMMAND_WHEEL_SCROLL) && ImplGetFormatter()->IsTextFormat(m_nFormatKey))
882*b1cdbd2cSJim Jagielski 			{
883*b1cdbd2cSJim Jagielski 				// same as above : prevent the base class from doing Up/Down-calls
884*b1cdbd2cSJim Jagielski 				// (normally I should put this test into the Up/Down methods itself, shouldn't I ?)
885*b1cdbd2cSJim Jagielski 				// FS - 71553 - 19.01.00
886*b1cdbd2cSJim Jagielski 				return 1;
887*b1cdbd2cSJim Jagielski 			}
888*b1cdbd2cSJim Jagielski 		}
889*b1cdbd2cSJim Jagielski 	}
890*b1cdbd2cSJim Jagielski 
891*b1cdbd2cSJim Jagielski 	if (rNEvt.GetType() == EVENT_LOSEFOCUS)
892*b1cdbd2cSJim Jagielski 	{
893*b1cdbd2cSJim Jagielski 		// Sonderbehandlung fuer leere Texte
894*b1cdbd2cSJim Jagielski 		if (GetText().Len() == 0)
895*b1cdbd2cSJim Jagielski 		{
896*b1cdbd2cSJim Jagielski 			if (!IsEmptyFieldEnabled())
897*b1cdbd2cSJim Jagielski 			{
898*b1cdbd2cSJim Jagielski 				if (TreatingAsNumber())
899*b1cdbd2cSJim Jagielski 				{
900*b1cdbd2cSJim Jagielski 					ImplSetValue(m_dCurrentValue, sal_True);
901*b1cdbd2cSJim Jagielski 					Modify();
902*b1cdbd2cSJim Jagielski 				}
903*b1cdbd2cSJim Jagielski 				else
904*b1cdbd2cSJim Jagielski 				{
905*b1cdbd2cSJim Jagielski 					String sNew = GetTextValue();
906*b1cdbd2cSJim Jagielski 					if (sNew.Len())
907*b1cdbd2cSJim Jagielski 						SetTextFormatted(sNew);
908*b1cdbd2cSJim Jagielski 					else
909*b1cdbd2cSJim Jagielski 						SetTextFormatted(m_sDefaultText);
910*b1cdbd2cSJim Jagielski 				}
911*b1cdbd2cSJim Jagielski 				m_bValueDirty = sal_False;
912*b1cdbd2cSJim Jagielski 			}
913*b1cdbd2cSJim Jagielski 		}
914*b1cdbd2cSJim Jagielski 		else
915*b1cdbd2cSJim Jagielski 		{
916*b1cdbd2cSJim Jagielski 			Commit();
917*b1cdbd2cSJim Jagielski 		}
918*b1cdbd2cSJim Jagielski 	}
919*b1cdbd2cSJim Jagielski 
920*b1cdbd2cSJim Jagielski 	return SpinField::Notify( rNEvt );
921*b1cdbd2cSJim Jagielski }
922*b1cdbd2cSJim Jagielski 
923*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
SetMinValue(double dMin)924*b1cdbd2cSJim Jagielski void FormattedField::SetMinValue(double dMin)
925*b1cdbd2cSJim Jagielski {
926*b1cdbd2cSJim Jagielski 	DBG_CHKTHIS(FormattedField, NULL);
927*b1cdbd2cSJim Jagielski 	DBG_ASSERT(m_bTreatAsNumber, "FormattedField::SetMinValue : only to be used in numeric mode !");
928*b1cdbd2cSJim Jagielski 
929*b1cdbd2cSJim Jagielski 	m_dMinValue = dMin;
930*b1cdbd2cSJim Jagielski 	m_bHasMin = sal_True;
931*b1cdbd2cSJim Jagielski 	// fuer die Ueberpruefung des aktuellen Wertes an der neuen Grenze -> ImplSetValue
932*b1cdbd2cSJim Jagielski 	ReFormat();
933*b1cdbd2cSJim Jagielski }
934*b1cdbd2cSJim Jagielski 
935*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
SetMaxValue(double dMax)936*b1cdbd2cSJim Jagielski void FormattedField::SetMaxValue(double dMax)
937*b1cdbd2cSJim Jagielski {
938*b1cdbd2cSJim Jagielski 	DBG_CHKTHIS(FormattedField, NULL);
939*b1cdbd2cSJim Jagielski 	DBG_ASSERT(m_bTreatAsNumber, "FormattedField::SetMaxValue : only to be used in numeric mode !");
940*b1cdbd2cSJim Jagielski 
941*b1cdbd2cSJim Jagielski 	m_dMaxValue = dMax;
942*b1cdbd2cSJim Jagielski 	m_bHasMax = sal_True;
943*b1cdbd2cSJim Jagielski 	// fuer die Ueberpruefung des aktuellen Wertes an der neuen Grenze -> ImplSetValue
944*b1cdbd2cSJim Jagielski 	ReFormat();
945*b1cdbd2cSJim Jagielski }
946*b1cdbd2cSJim Jagielski 
947*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
SetTextValue(const XubString & rText)948*b1cdbd2cSJim Jagielski void FormattedField::SetTextValue(const XubString& rText)
949*b1cdbd2cSJim Jagielski {
950*b1cdbd2cSJim Jagielski 	DBG_CHKTHIS(FormattedField, NULL);
951*b1cdbd2cSJim Jagielski 	SetText(rText);
952*b1cdbd2cSJim Jagielski 	ReFormat();
953*b1cdbd2cSJim Jagielski }
954*b1cdbd2cSJim Jagielski 
955*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
EnableEmptyField(sal_Bool bEnable)956*b1cdbd2cSJim Jagielski void FormattedField::EnableEmptyField(sal_Bool bEnable)
957*b1cdbd2cSJim Jagielski {
958*b1cdbd2cSJim Jagielski 	DBG_CHKTHIS(FormattedField, NULL);
959*b1cdbd2cSJim Jagielski 	if (bEnable == m_bEnableEmptyField)
960*b1cdbd2cSJim Jagielski 		return;
961*b1cdbd2cSJim Jagielski 
962*b1cdbd2cSJim Jagielski 	m_bEnableEmptyField = bEnable;
963*b1cdbd2cSJim Jagielski 	if (!m_bEnableEmptyField && GetText().Len()==0)
964*b1cdbd2cSJim Jagielski 		ImplSetValue(m_dCurrentValue, sal_True);
965*b1cdbd2cSJim Jagielski }
966*b1cdbd2cSJim Jagielski 
967*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
ImplSetValue(double dVal,sal_Bool bForce)968*b1cdbd2cSJim Jagielski void FormattedField::ImplSetValue(double dVal, sal_Bool bForce)
969*b1cdbd2cSJim Jagielski {
970*b1cdbd2cSJim Jagielski 	DBG_CHKTHIS(FormattedField, NULL);
971*b1cdbd2cSJim Jagielski 
972*b1cdbd2cSJim Jagielski 	if (m_bHasMin && (dVal<m_dMinValue))
973*b1cdbd2cSJim Jagielski 		dVal = m_dMinValue;
974*b1cdbd2cSJim Jagielski 	if (m_bHasMax && (dVal>m_dMaxValue))
975*b1cdbd2cSJim Jagielski 		dVal = m_dMaxValue;
976*b1cdbd2cSJim Jagielski 	if (!bForce && (dVal == GetValue()))
977*b1cdbd2cSJim Jagielski 		return;
978*b1cdbd2cSJim Jagielski 
979*b1cdbd2cSJim Jagielski 	DBG_ASSERT(ImplGetFormatter() != NULL, "FormattedField::ImplSetValue : can't set a value without a formatter !");
980*b1cdbd2cSJim Jagielski 
981*b1cdbd2cSJim Jagielski 	m_bValueDirty = sal_False;
982*b1cdbd2cSJim Jagielski 	m_dCurrentValue = dVal;
983*b1cdbd2cSJim Jagielski 
984*b1cdbd2cSJim Jagielski 	String sNewText;
985*b1cdbd2cSJim Jagielski 	if (ImplGetFormatter()->IsTextFormat(m_nFormatKey))
986*b1cdbd2cSJim Jagielski 	{
987*b1cdbd2cSJim Jagielski 		// zuerst die Zahl als String im Standard-Format
988*b1cdbd2cSJim Jagielski 		String sTemp;
989*b1cdbd2cSJim Jagielski 		ImplGetFormatter()->GetOutputString(dVal, 0, sTemp, &m_pLastOutputColor);
990*b1cdbd2cSJim Jagielski 		// dann den String entsprechend dem Text-Format
991*b1cdbd2cSJim Jagielski 		ImplGetFormatter()->GetOutputString(sTemp, m_nFormatKey, sNewText, &m_pLastOutputColor);
992*b1cdbd2cSJim Jagielski 	}
993*b1cdbd2cSJim Jagielski 	else
994*b1cdbd2cSJim Jagielski 	{
995*b1cdbd2cSJim Jagielski         if( IsUsingInputStringForFormatting())
996*b1cdbd2cSJim Jagielski             ImplGetFormatter()->GetInputLineString(dVal, m_nFormatKey, sNewText);
997*b1cdbd2cSJim Jagielski         else
998*b1cdbd2cSJim Jagielski             ImplGetFormatter()->GetOutputString(dVal, m_nFormatKey, sNewText, &m_pLastOutputColor);
999*b1cdbd2cSJim Jagielski 	}
1000*b1cdbd2cSJim Jagielski 
1001*b1cdbd2cSJim Jagielski 	ImplSetTextImpl(sNewText, NULL);
1002*b1cdbd2cSJim Jagielski 	m_bValueDirty = sal_False;
1003*b1cdbd2cSJim Jagielski 	DBG_ASSERT(CheckText(sNewText), "FormattedField::ImplSetValue : formatted string doesn't match the criteria !");
1004*b1cdbd2cSJim Jagielski }
1005*b1cdbd2cSJim Jagielski 
1006*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
ImplGetValue(double & dNewVal)1007*b1cdbd2cSJim Jagielski sal_Bool FormattedField::ImplGetValue(double& dNewVal)
1008*b1cdbd2cSJim Jagielski {
1009*b1cdbd2cSJim Jagielski 	DBG_CHKTHIS(FormattedField, NULL);
1010*b1cdbd2cSJim Jagielski 
1011*b1cdbd2cSJim Jagielski 	dNewVal = m_dCurrentValue;
1012*b1cdbd2cSJim Jagielski 	if (!m_bValueDirty)
1013*b1cdbd2cSJim Jagielski 		return sal_True;
1014*b1cdbd2cSJim Jagielski 
1015*b1cdbd2cSJim Jagielski 	dNewVal = m_dDefaultValue;
1016*b1cdbd2cSJim Jagielski 	String sText(GetText());
1017*b1cdbd2cSJim Jagielski 	if (!sText.Len())
1018*b1cdbd2cSJim Jagielski 		return sal_True;
1019*b1cdbd2cSJim Jagielski 
1020*b1cdbd2cSJim Jagielski 	DBG_ASSERT(ImplGetFormatter() != NULL, "FormattedField::ImplGetValue : can't give you a current value without a formatter !");
1021*b1cdbd2cSJim Jagielski 
1022*b1cdbd2cSJim Jagielski 	sal_uInt32 nFormatKey = m_nFormatKey;	// IsNumberFormat veraendert den FormatKey ...
1023*b1cdbd2cSJim Jagielski 
1024*b1cdbd2cSJim Jagielski 	if (ImplGetFormatter()->IsTextFormat(nFormatKey) && m_bTreatAsNumber)
1025*b1cdbd2cSJim Jagielski 		// damit wir in einem als Text formatierten Feld trotzdem eine Eingabe wie '1,1' erkennen ...
1026*b1cdbd2cSJim Jagielski 		nFormatKey = 0;
1027*b1cdbd2cSJim Jagielski 
1028*b1cdbd2cSJim Jagielski 	// Sonderbehandlung fuer %-Formatierung
1029*b1cdbd2cSJim Jagielski 	if (ImplGetFormatter()->GetType(m_nFormatKey) == NUMBERFORMAT_PERCENT)
1030*b1cdbd2cSJim Jagielski 	{
1031*b1cdbd2cSJim Jagielski 		// the language of our format
1032*b1cdbd2cSJim Jagielski 		LanguageType eLanguage = m_pFormatter->GetEntry(m_nFormatKey)->GetLanguage();
1033*b1cdbd2cSJim Jagielski 		// the default number format for this language
1034*b1cdbd2cSJim Jagielski 		sal_uLong nStandardNumericFormat = m_pFormatter->GetStandardFormat(NUMBERFORMAT_NUMBER, eLanguage);
1035*b1cdbd2cSJim Jagielski 
1036*b1cdbd2cSJim Jagielski 		sal_uInt32 nTempFormat = nStandardNumericFormat;
1037*b1cdbd2cSJim Jagielski 		double dTemp;
1038*b1cdbd2cSJim Jagielski 		if (m_pFormatter->IsNumberFormat(sText, nTempFormat, dTemp) &&
1039*b1cdbd2cSJim Jagielski 			NUMBERFORMAT_NUMBER == m_pFormatter->GetType(nTempFormat))
1040*b1cdbd2cSJim Jagielski 			// der String entspricht einer Number-Formatierung, hat also nur kein %
1041*b1cdbd2cSJim Jagielski 			// -> append it
1042*b1cdbd2cSJim Jagielski 			sText += '%';
1043*b1cdbd2cSJim Jagielski 		// (with this, a input of '3' becomes '3%', which then by the formatter is translated
1044*b1cdbd2cSJim Jagielski 		// into 0.03. Without this, the formatter would give us the double 3 for an input '3',
1045*b1cdbd2cSJim Jagielski 		// which equals 300 percent.
1046*b1cdbd2cSJim Jagielski 	}
1047*b1cdbd2cSJim Jagielski 	if (!ImplGetFormatter()->IsNumberFormat(sText, nFormatKey, dNewVal))
1048*b1cdbd2cSJim Jagielski 		return sal_False;
1049*b1cdbd2cSJim Jagielski 
1050*b1cdbd2cSJim Jagielski 
1051*b1cdbd2cSJim Jagielski 	if (m_bHasMin && (dNewVal<m_dMinValue))
1052*b1cdbd2cSJim Jagielski 		dNewVal = m_dMinValue;
1053*b1cdbd2cSJim Jagielski 	if (m_bHasMax && (dNewVal>m_dMaxValue))
1054*b1cdbd2cSJim Jagielski 		dNewVal = m_dMaxValue;
1055*b1cdbd2cSJim Jagielski 	return sal_True;
1056*b1cdbd2cSJim Jagielski }
1057*b1cdbd2cSJim Jagielski 
1058*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
SetValue(double dVal)1059*b1cdbd2cSJim Jagielski void FormattedField::SetValue(double dVal)
1060*b1cdbd2cSJim Jagielski {
1061*b1cdbd2cSJim Jagielski 	DBG_CHKTHIS(FormattedField, NULL);
1062*b1cdbd2cSJim Jagielski 	ImplSetValue(dVal, m_bValueDirty);
1063*b1cdbd2cSJim Jagielski }
1064*b1cdbd2cSJim Jagielski 
1065*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
GetValue()1066*b1cdbd2cSJim Jagielski double FormattedField::GetValue()
1067*b1cdbd2cSJim Jagielski {
1068*b1cdbd2cSJim Jagielski 	DBG_CHKTHIS(FormattedField, NULL);
1069*b1cdbd2cSJim Jagielski 
1070*b1cdbd2cSJim Jagielski 	if ( !ImplGetValue( m_dCurrentValue ) )
1071*b1cdbd2cSJim Jagielski 	{
1072*b1cdbd2cSJim Jagielski         if ( m_bEnableNaN )
1073*b1cdbd2cSJim Jagielski             ::rtl::math::setNan( &m_dCurrentValue );
1074*b1cdbd2cSJim Jagielski         else
1075*b1cdbd2cSJim Jagielski 		    m_dCurrentValue = m_dDefaultValue;
1076*b1cdbd2cSJim Jagielski 	}
1077*b1cdbd2cSJim Jagielski 
1078*b1cdbd2cSJim Jagielski 	m_bValueDirty = sal_False;
1079*b1cdbd2cSJim Jagielski 	return m_dCurrentValue;
1080*b1cdbd2cSJim Jagielski }
1081*b1cdbd2cSJim Jagielski 
1082*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
Up()1083*b1cdbd2cSJim Jagielski void FormattedField::Up()
1084*b1cdbd2cSJim Jagielski {
1085*b1cdbd2cSJim Jagielski 	DBG_CHKTHIS(FormattedField, NULL);
1086*b1cdbd2cSJim Jagielski 	SetValue(GetValue() + m_dSpinSize);
1087*b1cdbd2cSJim Jagielski 		// das setValue handelt Bereichsueberschreitungen (min/max) automatisch
1088*b1cdbd2cSJim Jagielski 	SetModifyFlag();
1089*b1cdbd2cSJim Jagielski 	Modify();
1090*b1cdbd2cSJim Jagielski 
1091*b1cdbd2cSJim Jagielski 	SpinField::Up();
1092*b1cdbd2cSJim Jagielski }
1093*b1cdbd2cSJim Jagielski 
1094*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
Down()1095*b1cdbd2cSJim Jagielski void FormattedField::Down()
1096*b1cdbd2cSJim Jagielski {
1097*b1cdbd2cSJim Jagielski 	DBG_CHKTHIS(FormattedField, NULL);
1098*b1cdbd2cSJim Jagielski 	SetValue(GetValue() - m_dSpinSize);
1099*b1cdbd2cSJim Jagielski 	SetModifyFlag();
1100*b1cdbd2cSJim Jagielski 	Modify();
1101*b1cdbd2cSJim Jagielski 
1102*b1cdbd2cSJim Jagielski 	SpinField::Down();
1103*b1cdbd2cSJim Jagielski }
1104*b1cdbd2cSJim Jagielski 
1105*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
First()1106*b1cdbd2cSJim Jagielski void FormattedField::First()
1107*b1cdbd2cSJim Jagielski {
1108*b1cdbd2cSJim Jagielski 	DBG_CHKTHIS(FormattedField, NULL);
1109*b1cdbd2cSJim Jagielski 	if (m_bHasMin)
1110*b1cdbd2cSJim Jagielski 	{
1111*b1cdbd2cSJim Jagielski 		SetValue(m_dMinValue);
1112*b1cdbd2cSJim Jagielski 		SetModifyFlag();
1113*b1cdbd2cSJim Jagielski 		Modify();
1114*b1cdbd2cSJim Jagielski 	}
1115*b1cdbd2cSJim Jagielski 
1116*b1cdbd2cSJim Jagielski 	SpinField::First();
1117*b1cdbd2cSJim Jagielski }
1118*b1cdbd2cSJim Jagielski 
1119*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
Last()1120*b1cdbd2cSJim Jagielski void FormattedField::Last()
1121*b1cdbd2cSJim Jagielski {
1122*b1cdbd2cSJim Jagielski 	DBG_CHKTHIS(FormattedField, NULL);
1123*b1cdbd2cSJim Jagielski 	if (m_bHasMax)
1124*b1cdbd2cSJim Jagielski 	{
1125*b1cdbd2cSJim Jagielski 		SetValue(m_dMaxValue);
1126*b1cdbd2cSJim Jagielski 		SetModifyFlag();
1127*b1cdbd2cSJim Jagielski 		Modify();
1128*b1cdbd2cSJim Jagielski 	}
1129*b1cdbd2cSJim Jagielski 
1130*b1cdbd2cSJim Jagielski 	SpinField::Last();
1131*b1cdbd2cSJim Jagielski }
1132*b1cdbd2cSJim Jagielski 
1133*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
UseInputStringForFormatting(bool bUseInputStr)1134*b1cdbd2cSJim Jagielski void FormattedField::UseInputStringForFormatting( bool bUseInputStr /* = true */ )
1135*b1cdbd2cSJim Jagielski {
1136*b1cdbd2cSJim Jagielski     m_bUseInputStringForFormatting = bUseInputStr;
1137*b1cdbd2cSJim Jagielski }
1138*b1cdbd2cSJim Jagielski 
1139*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
IsUsingInputStringForFormatting() const1140*b1cdbd2cSJim Jagielski bool FormattedField::IsUsingInputStringForFormatting() const
1141*b1cdbd2cSJim Jagielski {
1142*b1cdbd2cSJim Jagielski     return m_bUseInputStringForFormatting;
1143*b1cdbd2cSJim Jagielski }
1144*b1cdbd2cSJim Jagielski 
1145*b1cdbd2cSJim Jagielski 
1146*b1cdbd2cSJim Jagielski //==============================================================================
1147*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
~DoubleNumericField()1148*b1cdbd2cSJim Jagielski DoubleNumericField::~DoubleNumericField()
1149*b1cdbd2cSJim Jagielski {
1150*b1cdbd2cSJim Jagielski #ifdef REGEXP_SUPPORT
1151*b1cdbd2cSJim Jagielski 	delete m_pConformanceTester;
1152*b1cdbd2cSJim Jagielski #else
1153*b1cdbd2cSJim Jagielski 	delete m_pNumberValidator;
1154*b1cdbd2cSJim Jagielski #endif
1155*b1cdbd2cSJim Jagielski }
1156*b1cdbd2cSJim Jagielski 
1157*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
FormatChanged(FORMAT_CHANGE_TYPE nWhat)1158*b1cdbd2cSJim Jagielski void DoubleNumericField::FormatChanged(FORMAT_CHANGE_TYPE nWhat)
1159*b1cdbd2cSJim Jagielski {
1160*b1cdbd2cSJim Jagielski 	ResetConformanceTester();
1161*b1cdbd2cSJim Jagielski 	FormattedField::FormatChanged(nWhat);
1162*b1cdbd2cSJim Jagielski }
1163*b1cdbd2cSJim Jagielski 
1164*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
CheckText(const XubString & sText) const1165*b1cdbd2cSJim Jagielski sal_Bool DoubleNumericField::CheckText(const XubString& sText) const
1166*b1cdbd2cSJim Jagielski {
1167*b1cdbd2cSJim Jagielski 	// We'd like to implement this using the NumberFormatter::IsNumberFormat, but unfortunately, this doesn't
1168*b1cdbd2cSJim Jagielski 	// recognize fragments of numbers (like, for instance "1e", which happens during entering e.g. "1e10")
1169*b1cdbd2cSJim Jagielski 	// Thus, the roundabout way via a regular expression
1170*b1cdbd2cSJim Jagielski 
1171*b1cdbd2cSJim Jagielski #ifdef REGEXP_SUPPORT
1172*b1cdbd2cSJim Jagielski 	if (!sText.Len())
1173*b1cdbd2cSJim Jagielski 		return sal_True;
1174*b1cdbd2cSJim Jagielski 
1175*b1cdbd2cSJim Jagielski 	String sForceComplete = '_';
1176*b1cdbd2cSJim Jagielski 	sForceComplete += sText;
1177*b1cdbd2cSJim Jagielski 	sForceComplete += '_';
1178*b1cdbd2cSJim Jagielski 
1179*b1cdbd2cSJim Jagielski 	sal_uInt16 nStart = 0, nEnd = sForceComplete.Len();
1180*b1cdbd2cSJim Jagielski 	sal_Bool bFound = m_pConformanceTester->SearchFrwrd(sForceComplete, &nStart, &nEnd);
1181*b1cdbd2cSJim Jagielski 
1182*b1cdbd2cSJim Jagielski 	if (bFound && (nStart == 0) && (nEnd == sForceComplete.Len()))
1183*b1cdbd2cSJim Jagielski 		return sal_True;
1184*b1cdbd2cSJim Jagielski 
1185*b1cdbd2cSJim Jagielski 	return sal_False;
1186*b1cdbd2cSJim Jagielski #else
1187*b1cdbd2cSJim Jagielski 	return m_pNumberValidator->isValidNumericFragment( sText );
1188*b1cdbd2cSJim Jagielski #endif
1189*b1cdbd2cSJim Jagielski }
1190*b1cdbd2cSJim Jagielski 
1191*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
ResetConformanceTester()1192*b1cdbd2cSJim Jagielski void DoubleNumericField::ResetConformanceTester()
1193*b1cdbd2cSJim Jagielski {
1194*b1cdbd2cSJim Jagielski 	// the thousands and the decimal separator are language dependent
1195*b1cdbd2cSJim Jagielski 	const SvNumberformat* pFormatEntry = ImplGetFormatter()->GetEntry(m_nFormatKey);
1196*b1cdbd2cSJim Jagielski 
1197*b1cdbd2cSJim Jagielski 	sal_Unicode cSeparatorThousand = ',';
1198*b1cdbd2cSJim Jagielski 	sal_Unicode cSeparatorDecimal = '.';
1199*b1cdbd2cSJim Jagielski 	if (pFormatEntry)
1200*b1cdbd2cSJim Jagielski 	{
1201*b1cdbd2cSJim Jagielski         Locale aLocale;
1202*b1cdbd2cSJim Jagielski         MsLangId::convertLanguageToLocale( pFormatEntry->GetLanguage(), aLocale );
1203*b1cdbd2cSJim Jagielski 		LocaleDataWrapper aLocaleInfo(::comphelper::getProcessServiceFactory(), aLocale);
1204*b1cdbd2cSJim Jagielski 
1205*b1cdbd2cSJim Jagielski 		String sSeparator = aLocaleInfo.getNumThousandSep();
1206*b1cdbd2cSJim Jagielski 		if (sSeparator.Len())
1207*b1cdbd2cSJim Jagielski 			cSeparatorThousand = sSeparator.GetBuffer()[0];
1208*b1cdbd2cSJim Jagielski 
1209*b1cdbd2cSJim Jagielski 		sSeparator = aLocaleInfo.getNumDecimalSep();
1210*b1cdbd2cSJim Jagielski 		if (sSeparator.Len())
1211*b1cdbd2cSJim Jagielski 			cSeparatorDecimal = sSeparator.GetBuffer()[0];
1212*b1cdbd2cSJim Jagielski 	}
1213*b1cdbd2cSJim Jagielski 
1214*b1cdbd2cSJim Jagielski #ifdef REGEXP_SUPPORT
1215*b1cdbd2cSJim Jagielski 	String sDescription = String::CreateFromAscii(szNumericInput);
1216*b1cdbd2cSJim Jagielski 
1217*b1cdbd2cSJim Jagielski 	String sReplaceWith((sal_Unicode)'\\');
1218*b1cdbd2cSJim Jagielski 	sReplaceWith += cSeparatorThousand;
1219*b1cdbd2cSJim Jagielski 	sDescription.SearchAndReplaceAscii("\\,", sReplaceWith);
1220*b1cdbd2cSJim Jagielski 
1221*b1cdbd2cSJim Jagielski 	sReplaceWith = (sal_Unicode)'\\';
1222*b1cdbd2cSJim Jagielski 	sReplaceWith += cSeparatorDecimal;
1223*b1cdbd2cSJim Jagielski 	sDescription.SearchAndReplaceAscii("\\.", sReplaceWith);
1224*b1cdbd2cSJim Jagielski 
1225*b1cdbd2cSJim Jagielski 	delete m_pConformanceTester;
1226*b1cdbd2cSJim Jagielski 
1227*b1cdbd2cSJim Jagielski 	SearchOptions aParam;
1228*b1cdbd2cSJim Jagielski 	aParam.algorithmType = SearchAlgorithms_REGEXP;
1229*b1cdbd2cSJim Jagielski 	aParam.searchFlag = SearchFlags::ALL_IGNORE_CASE;
1230*b1cdbd2cSJim Jagielski 	aParam.searchString = sDescription;
1231*b1cdbd2cSJim Jagielski 	aParam.transliterateFlags = 0;
1232*b1cdbd2cSJim Jagielski 
1233*b1cdbd2cSJim Jagielski 	String sLanguage, sCountry;
1234*b1cdbd2cSJim Jagielski 	ConvertLanguageToIsoNames( pFormatEntry ? pFormatEntry->GetLanguage() : LANGUAGE_ENGLISH_US, sLanguage, sCountry );
1235*b1cdbd2cSJim Jagielski 	aParam.Locale.Language = sLanguage;
1236*b1cdbd2cSJim Jagielski 	aParam.Locale.Country = sCountry;
1237*b1cdbd2cSJim Jagielski 
1238*b1cdbd2cSJim Jagielski 	m_pConformanceTester = new ::utl::TextSearch(aParam);
1239*b1cdbd2cSJim Jagielski #else
1240*b1cdbd2cSJim Jagielski 	delete m_pNumberValidator;
1241*b1cdbd2cSJim Jagielski 	m_pNumberValidator = new validation::NumberValidator( cSeparatorThousand, cSeparatorDecimal );
1242*b1cdbd2cSJim Jagielski #endif
1243*b1cdbd2cSJim Jagielski }
1244*b1cdbd2cSJim Jagielski 
1245*b1cdbd2cSJim Jagielski 
1246*b1cdbd2cSJim Jagielski //==============================================================================
1247*b1cdbd2cSJim Jagielski 
1248*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
DoubleCurrencyField(Window * pParent,WinBits nStyle)1249*b1cdbd2cSJim Jagielski DoubleCurrencyField::DoubleCurrencyField(Window* pParent, WinBits nStyle)
1250*b1cdbd2cSJim Jagielski 	:FormattedField(pParent, nStyle)
1251*b1cdbd2cSJim Jagielski 	,m_bChangingFormat(sal_False)
1252*b1cdbd2cSJim Jagielski {
1253*b1cdbd2cSJim Jagielski 	m_bPrependCurrSym = sal_False;
1254*b1cdbd2cSJim Jagielski 
1255*b1cdbd2cSJim Jagielski 	// initialize with a system currency format
1256*b1cdbd2cSJim Jagielski     m_sCurrencySymbol = SvtSysLocale().GetLocaleData().getCurrSymbol();
1257*b1cdbd2cSJim Jagielski 	UpdateCurrencyFormat();
1258*b1cdbd2cSJim Jagielski }
1259*b1cdbd2cSJim Jagielski 
1260*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
DoubleCurrencyField(Window * pParent,const ResId & rResId)1261*b1cdbd2cSJim Jagielski DoubleCurrencyField::DoubleCurrencyField(Window* pParent, const ResId& rResId)
1262*b1cdbd2cSJim Jagielski 	:FormattedField(pParent, rResId)
1263*b1cdbd2cSJim Jagielski 	,m_bChangingFormat(sal_False)
1264*b1cdbd2cSJim Jagielski {
1265*b1cdbd2cSJim Jagielski 	m_bPrependCurrSym = sal_False;
1266*b1cdbd2cSJim Jagielski 
1267*b1cdbd2cSJim Jagielski 	// initialize with a system currency format
1268*b1cdbd2cSJim Jagielski     m_sCurrencySymbol = SvtSysLocale().GetLocaleData().getCurrSymbol();
1269*b1cdbd2cSJim Jagielski 	UpdateCurrencyFormat();
1270*b1cdbd2cSJim Jagielski }
1271*b1cdbd2cSJim Jagielski 
1272*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
FormatChanged(FORMAT_CHANGE_TYPE nWhat)1273*b1cdbd2cSJim Jagielski void DoubleCurrencyField::FormatChanged(FORMAT_CHANGE_TYPE nWhat)
1274*b1cdbd2cSJim Jagielski {
1275*b1cdbd2cSJim Jagielski 	if (m_bChangingFormat)
1276*b1cdbd2cSJim Jagielski 	{
1277*b1cdbd2cSJim Jagielski 		FormattedField::FormatChanged(nWhat);
1278*b1cdbd2cSJim Jagielski 		return;
1279*b1cdbd2cSJim Jagielski 	}
1280*b1cdbd2cSJim Jagielski 
1281*b1cdbd2cSJim Jagielski 	switch (nWhat)
1282*b1cdbd2cSJim Jagielski 	{
1283*b1cdbd2cSJim Jagielski 		case FCT_FORMATTER:
1284*b1cdbd2cSJim Jagielski 		case FCT_PRECISION:
1285*b1cdbd2cSJim Jagielski 		case FCT_THOUSANDSSEP:
1286*b1cdbd2cSJim Jagielski 			// the aspects which changed don't take our currency settings into account (in fact, they most probably
1287*b1cdbd2cSJim Jagielski 			// destroyed them)
1288*b1cdbd2cSJim Jagielski 			UpdateCurrencyFormat();
1289*b1cdbd2cSJim Jagielski 			break;
1290*b1cdbd2cSJim Jagielski 		case FCT_KEYONLY:
1291*b1cdbd2cSJim Jagielski 			DBG_ERROR("DoubleCurrencyField::FormatChanged : somebody modified my key !");
1292*b1cdbd2cSJim Jagielski 			// We always build our own format from the settings we get via special methods (setCurrencySymbol etc.).
1293*b1cdbd2cSJim Jagielski 			// Nobody but ourself should modifiy the format key directly !
1294*b1cdbd2cSJim Jagielski 			break;
1295*b1cdbd2cSJim Jagielski 	}
1296*b1cdbd2cSJim Jagielski 
1297*b1cdbd2cSJim Jagielski 	FormattedField::FormatChanged(nWhat);
1298*b1cdbd2cSJim Jagielski }
1299*b1cdbd2cSJim Jagielski 
1300*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
setCurrencySymbol(const String & _sSymbol)1301*b1cdbd2cSJim Jagielski void DoubleCurrencyField::setCurrencySymbol(const String& _sSymbol)
1302*b1cdbd2cSJim Jagielski {
1303*b1cdbd2cSJim Jagielski 	if (m_sCurrencySymbol == _sSymbol)
1304*b1cdbd2cSJim Jagielski 		return;
1305*b1cdbd2cSJim Jagielski 
1306*b1cdbd2cSJim Jagielski 	m_sCurrencySymbol  = _sSymbol;
1307*b1cdbd2cSJim Jagielski 	UpdateCurrencyFormat();
1308*b1cdbd2cSJim Jagielski 	FormatChanged(FCT_CURRENCY_SYMBOL);
1309*b1cdbd2cSJim Jagielski }
1310*b1cdbd2cSJim Jagielski 
1311*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
setPrependCurrSym(sal_Bool _bPrepend)1312*b1cdbd2cSJim Jagielski void DoubleCurrencyField::setPrependCurrSym(sal_Bool _bPrepend)
1313*b1cdbd2cSJim Jagielski {
1314*b1cdbd2cSJim Jagielski 	if (m_bPrependCurrSym == _bPrepend)
1315*b1cdbd2cSJim Jagielski 		 return;
1316*b1cdbd2cSJim Jagielski 
1317*b1cdbd2cSJim Jagielski 	m_bPrependCurrSym = _bPrepend;
1318*b1cdbd2cSJim Jagielski 	UpdateCurrencyFormat();
1319*b1cdbd2cSJim Jagielski 	FormatChanged(FCT_CURRSYM_POSITION);
1320*b1cdbd2cSJim Jagielski }
1321*b1cdbd2cSJim Jagielski 
1322*b1cdbd2cSJim Jagielski //------------------------------------------------------------------------------
UpdateCurrencyFormat()1323*b1cdbd2cSJim Jagielski void DoubleCurrencyField::UpdateCurrencyFormat()
1324*b1cdbd2cSJim Jagielski {
1325*b1cdbd2cSJim Jagielski 	// the old settings
1326*b1cdbd2cSJim Jagielski 	XubString sOldFormat;
1327*b1cdbd2cSJim Jagielski 	LanguageType eLanguage;
1328*b1cdbd2cSJim Jagielski 	GetFormat(sOldFormat, eLanguage);
1329*b1cdbd2cSJim Jagielski 	sal_Bool bThSep = GetThousandsSep();
1330*b1cdbd2cSJim Jagielski 	sal_uInt16 nDigits = GetDecimalDigits();
1331*b1cdbd2cSJim Jagielski 
1332*b1cdbd2cSJim Jagielski 	// build a new format string with the base class' and my own settings
1333*b1cdbd2cSJim Jagielski     Locale aLocale;
1334*b1cdbd2cSJim Jagielski     MsLangId::convertLanguageToLocale( eLanguage, aLocale );
1335*b1cdbd2cSJim Jagielski 	LocaleDataWrapper aLocaleInfo(::comphelper::getProcessServiceFactory(), aLocale);
1336*b1cdbd2cSJim Jagielski 
1337*b1cdbd2cSJim Jagielski 	XubString sNewFormat;
1338*b1cdbd2cSJim Jagielski 	if (bThSep)
1339*b1cdbd2cSJim Jagielski 	{
1340*b1cdbd2cSJim Jagielski 		sNewFormat = '#';
1341*b1cdbd2cSJim Jagielski 		sNewFormat += aLocaleInfo.getNumThousandSep();
1342*b1cdbd2cSJim Jagielski 		sNewFormat.AppendAscii("##0");
1343*b1cdbd2cSJim Jagielski 	}
1344*b1cdbd2cSJim Jagielski 	else
1345*b1cdbd2cSJim Jagielski 		sNewFormat = '0';
1346*b1cdbd2cSJim Jagielski 
1347*b1cdbd2cSJim Jagielski 	if (nDigits)
1348*b1cdbd2cSJim Jagielski 	{
1349*b1cdbd2cSJim Jagielski 		sNewFormat += aLocaleInfo.getNumDecimalSep();
1350*b1cdbd2cSJim Jagielski 
1351*b1cdbd2cSJim Jagielski 		XubString sTemp;
1352*b1cdbd2cSJim Jagielski 		sTemp.Fill(nDigits, '0');
1353*b1cdbd2cSJim Jagielski 		sNewFormat += sTemp;
1354*b1cdbd2cSJim Jagielski 	}
1355*b1cdbd2cSJim Jagielski 
1356*b1cdbd2cSJim Jagielski 	if (getPrependCurrSym())
1357*b1cdbd2cSJim Jagielski 	{
1358*b1cdbd2cSJim Jagielski 		XubString sSymbol = getCurrencySymbol();
1359*b1cdbd2cSJim Jagielski 		sSymbol.EraseLeadingChars(' ');
1360*b1cdbd2cSJim Jagielski 		sSymbol.EraseTrailingChars(' ');
1361*b1cdbd2cSJim Jagielski 
1362*b1cdbd2cSJim Jagielski 		XubString sTemp = String::CreateFromAscii("[$");
1363*b1cdbd2cSJim Jagielski 		sTemp += sSymbol;
1364*b1cdbd2cSJim Jagielski 		sTemp.AppendAscii("] ");
1365*b1cdbd2cSJim Jagielski 		sTemp += sNewFormat;
1366*b1cdbd2cSJim Jagielski 
1367*b1cdbd2cSJim Jagielski 		// for negative values : $ -0.00, not -$ 0.00 ...
1368*b1cdbd2cSJim Jagielski 		// (the real solution would be a possibility to choose a "positive currency format" and a "negative currency format" ...
1369*b1cdbd2cSJim Jagielski 		// But not now ... (and hey, you could take a formatted field for this ....))
1370*b1cdbd2cSJim Jagielski 		// FS - 31.03.00 74642
1371*b1cdbd2cSJim Jagielski 		sTemp.AppendAscii(";[$");
1372*b1cdbd2cSJim Jagielski 		sTemp += sSymbol;
1373*b1cdbd2cSJim Jagielski 		sTemp.AppendAscii("] -");
1374*b1cdbd2cSJim Jagielski 		sTemp += sNewFormat;
1375*b1cdbd2cSJim Jagielski 
1376*b1cdbd2cSJim Jagielski 		sNewFormat = sTemp;
1377*b1cdbd2cSJim Jagielski 	}
1378*b1cdbd2cSJim Jagielski 	else
1379*b1cdbd2cSJim Jagielski 	{
1380*b1cdbd2cSJim Jagielski 		XubString sTemp = getCurrencySymbol();
1381*b1cdbd2cSJim Jagielski 		sTemp.EraseLeadingChars(' ');
1382*b1cdbd2cSJim Jagielski 		sTemp.EraseTrailingChars(' ');
1383*b1cdbd2cSJim Jagielski 
1384*b1cdbd2cSJim Jagielski 		sNewFormat += String::CreateFromAscii(" [$");
1385*b1cdbd2cSJim Jagielski 		sNewFormat += sTemp;
1386*b1cdbd2cSJim Jagielski 		sNewFormat += ']';
1387*b1cdbd2cSJim Jagielski 	}
1388*b1cdbd2cSJim Jagielski 
1389*b1cdbd2cSJim Jagielski 	// set this new basic format
1390*b1cdbd2cSJim Jagielski 	m_bChangingFormat = sal_True;
1391*b1cdbd2cSJim Jagielski 	SetFormat(sNewFormat, eLanguage);
1392*b1cdbd2cSJim Jagielski 	m_bChangingFormat = sal_False;
1393*b1cdbd2cSJim Jagielski }
1394*b1cdbd2cSJim Jagielski 
1395