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