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