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