LCOV - code coverage report
Current view: top level - svtools/source/control - fmtfield.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 418 505 82.8 %
Date: 2014-11-03 Functions: 59 64 92.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <stdio.h>
      21             : #include <tools/debug.hxx>
      22             : #include <comphelper/processfactory.hxx>
      23             : #include <comphelper/string.hxx>
      24             : #include <unotools/localedatawrapper.hxx>
      25             : #include <vcl/svapp.hxx>
      26             : #include <vcl/builder.hxx>
      27             : #include <vcl/settings.hxx>
      28             : #include <svl/zformat.hxx>
      29             : #include <svtools/fmtfield.hxx>
      30             : #include <i18nlangtag/languagetag.hxx>
      31             : #include <com/sun/star/lang/Locale.hpp>
      32             : #include <com/sun/star/util/SearchOptions.hpp>
      33             : #include <com/sun/star/util/SearchAlgorithms.hpp>
      34             : #include <com/sun/star/util/SearchResult.hpp>
      35             : #include <com/sun/star/util/SearchFlags.hpp>
      36             : #include <unotools/syslocale.hxx>
      37             : #include <map>
      38             : #include <rtl/math.hxx>
      39             : #include <rtl/ustrbuf.hxx>
      40             : 
      41             : using namespace ::com::sun::star::lang;
      42             : using namespace ::com::sun::star::util;
      43             : 
      44             : // hmm. No support for regular expression. Well, I always (not really :) wanted to write a finite automat
      45             : // so here comes a finite automat ...
      46             : 
      47             : namespace validation
      48             : {
      49             :     // the states of our automat.
      50             :     enum State
      51             :     {
      52             :         START,              // at the very start of the string
      53             :         NUM_START,          // the very start of the number
      54             : 
      55             :         DIGIT_PRE_COMMA,    // some pre-comma digits are read, perhaps including some thousand separators
      56             : 
      57             :         DIGIT_POST_COMMA,   // reading digits after the comma
      58             :         EXPONENT_START,     // at the very start of the exponent value
      59             :                             //    (means: not including the "e" which denotes the exponent)
      60             :         EXPONENT_DIGIT,     // currently reading the digits of the exponent
      61             : 
      62             :         END                 // reached the end of the string
      63             :     };
      64             : 
      65             :     // a row in the transition table (means the set of states to be reached from a given state)
      66             :     typedef ::std::map< sal_Unicode, State >        StateTransitions;
      67             : 
      68             :     // a single transition
      69             :     typedef StateTransitions::value_type            Transition;
      70             : 
      71             :     // the complete transition table
      72             :     typedef ::std::map< State, StateTransitions >   TransitionTable;
      73             : 
      74             :     // the validator class
      75         148 :     class NumberValidator
      76             :     {
      77             :     private:
      78             :         TransitionTable     m_aTransitions;
      79             :         const sal_Unicode   m_cThSep;
      80             :         const sal_Unicode   m_cDecSep;
      81             : 
      82             :     public:
      83             :         NumberValidator( const sal_Unicode _cThSep, const sal_Unicode _cDecSep );
      84             : 
      85             :         bool isValidNumericFragment( const OUString& _rText );
      86             : 
      87             :     private:
      88             :         bool implValidateNormalized( const OUString& _rText );
      89             :     };
      90             : 
      91         592 :     static void lcl_insertStopTransition( StateTransitions& _rRow )
      92             :     {
      93         592 :         _rRow.insert( Transition( '_', END ) );
      94         592 :     }
      95             : 
      96         444 :     static void lcl_insertStartExponentTransition( StateTransitions& _rRow )
      97             :     {
      98         444 :         _rRow.insert( Transition( 'e', EXPONENT_START ) );
      99         444 :     }
     100             : 
     101         296 :     static void lcl_insertSignTransitions( StateTransitions& _rRow, const State eNextState )
     102             :     {
     103         296 :         _rRow.insert( Transition( '-', eNextState ) );
     104         296 :         _rRow.insert( Transition( '+', eNextState ) );
     105         296 :     }
     106             : 
     107         740 :     static void lcl_insertDigitTransitions( StateTransitions& _rRow, const State eNextState )
     108             :     {
     109        8140 :         for ( sal_Unicode aChar = '0'; aChar <= '9'; ++aChar )
     110        7400 :             _rRow.insert( Transition( aChar, eNextState ) );
     111         740 :     }
     112             : 
     113         296 :     static void lcl_insertCommonPreCommaTransitions( StateTransitions& _rRow, const sal_Unicode _cThSep, const sal_Unicode _cDecSep )
     114             :     {
     115             :         // digits are allowed
     116         296 :         lcl_insertDigitTransitions( _rRow, DIGIT_PRE_COMMA );
     117             : 
     118             :         // the thousand separator is allowed
     119         296 :         _rRow.insert( Transition( _cThSep, DIGIT_PRE_COMMA ) );
     120             : 
     121             :         // a comma is allowed
     122         296 :         _rRow.insert( Transition( _cDecSep, DIGIT_POST_COMMA ) );
     123         296 :     }
     124             : 
     125         148 :     NumberValidator::NumberValidator( const sal_Unicode _cThSep, const sal_Unicode _cDecSep )
     126             :         :m_cThSep( _cThSep )
     127         148 :         ,m_cDecSep( _cDecSep )
     128             :     {
     129             :         // build up our transition table
     130             : 
     131             :         // how to procede from START
     132             :         {
     133         148 :             StateTransitions& rRow = m_aTransitions[ START ];
     134         148 :             rRow.insert( Transition( '_', NUM_START ) );
     135             :                 // if we encounter the normalizing character, we want to procede with the number
     136             :         }
     137             : 
     138             :         // how to procede from NUM_START
     139             :         {
     140         148 :             StateTransitions& rRow = m_aTransitions[ NUM_START ];
     141             : 
     142             :             // a sign is allowed
     143         148 :             lcl_insertSignTransitions( rRow, DIGIT_PRE_COMMA );
     144             : 
     145             :             // common transitions for the two pre-comma states
     146         148 :             lcl_insertCommonPreCommaTransitions( rRow, m_cThSep, m_cDecSep );
     147             : 
     148             :             // the exponent may start here
     149             :             // (this would mean string like "_+e10_", but this is a valid fragment, though no valid number)
     150         148 :             lcl_insertStartExponentTransition( rRow );
     151             :         }
     152             : 
     153             :         // how to procede from DIGIT_PRE_COMMA
     154             :         {
     155         148 :             StateTransitions& rRow = m_aTransitions[ DIGIT_PRE_COMMA ];
     156             : 
     157             :             // common transitions for the two pre-comma states
     158         148 :             lcl_insertCommonPreCommaTransitions( rRow, m_cThSep, m_cDecSep );
     159             : 
     160             :             // the exponent may start here
     161         148 :             lcl_insertStartExponentTransition( rRow );
     162             : 
     163             :             // the final transition indicating the end of the string
     164             :             // (if there is no comma and no post-comma, then the string may end here)
     165         148 :             lcl_insertStopTransition( rRow );
     166             :         }
     167             : 
     168             :         // how to procede from DIGIT_POST_COMMA
     169             :         {
     170         148 :             StateTransitions& rRow = m_aTransitions[ DIGIT_POST_COMMA ];
     171             : 
     172             :             // there might be digits, which would keep the state at DIGIT_POST_COMMA
     173         148 :             lcl_insertDigitTransitions( rRow, DIGIT_POST_COMMA );
     174             : 
     175             :             // the exponent may start here
     176         148 :             lcl_insertStartExponentTransition( rRow );
     177             : 
     178             :             // the string may end here
     179         148 :             lcl_insertStopTransition( rRow );
     180             :         }
     181             : 
     182             :         // how to procede from EXPONENT_START
     183             :         {
     184         148 :             StateTransitions& rRow = m_aTransitions[ EXPONENT_START ];
     185             : 
     186             :             // there may be a sign
     187         148 :             lcl_insertSignTransitions( rRow, EXPONENT_DIGIT );
     188             : 
     189             :             // there may be digits
     190         148 :             lcl_insertDigitTransitions( rRow, EXPONENT_DIGIT );
     191             : 
     192             :             // the string may end here
     193         148 :             lcl_insertStopTransition( rRow );
     194             :         }
     195             : 
     196             :         // how to procede from EXPONENT_DIGIT
     197             :         {
     198         148 :             StateTransitions& rRow = m_aTransitions[ EXPONENT_DIGIT ];
     199             : 
     200             :             // there may be digits
     201         148 :             lcl_insertDigitTransitions( rRow, EXPONENT_DIGIT );
     202             : 
     203             :             // the string may end here
     204         148 :             lcl_insertStopTransition( rRow );
     205             :         }
     206             : 
     207             :         // how to procede from END
     208             :         {
     209         148 :             /*StateTransitions& rRow =*/ m_aTransitions[ EXPONENT_DIGIT ];
     210             :             // no valid transition to leave this state
     211             :             // (note that we, for consistency, nevertheless want to have a row in the table)
     212             :         }
     213         148 :     }
     214             : 
     215          56 :     bool NumberValidator::implValidateNormalized( const OUString& _rText )
     216             :     {
     217          56 :         const sal_Unicode* pCheckPos = _rText.getStr();
     218          56 :         State eCurrentState = START;
     219             : 
     220         424 :         while ( END != eCurrentState )
     221             :         {
     222             :             // look up the transition row for the current state
     223         328 :             TransitionTable::const_iterator aRow = m_aTransitions.find( eCurrentState );
     224             :             DBG_ASSERT( m_aTransitions.end() != aRow,
     225             :                 "NumberValidator::implValidateNormalized: invalid transition table (row not found)!" );
     226             : 
     227         328 :             if ( m_aTransitions.end() != aRow )
     228             :             {
     229             :                 // look up the current character in this row
     230         328 :                 StateTransitions::const_iterator aTransition = aRow->second.find( *pCheckPos );
     231         328 :                 if ( aRow->second.end() != aTransition )
     232             :                 {
     233             :                     // there is a valid transition for this character
     234         312 :                     eCurrentState = aTransition->second;
     235         312 :                     ++pCheckPos;
     236         312 :                     continue;
     237             :                 }
     238             :             }
     239             : 
     240             :             // if we're here, there is no valid transition
     241          16 :             break;
     242             :         }
     243             : 
     244             :         DBG_ASSERT( ( END != eCurrentState ) || ( 0 == *pCheckPos ),
     245             :             "NumberValidator::implValidateNormalized: inconsistency!" );
     246             :             // if we're at END, then the string should be done, too - the string should be normalized, means ending
     247             :             // a "_" and not containing any other "_" (except at the start), and "_" is the only possibility
     248             :             // to reach the END state
     249             : 
     250             :         // the string is valid if and only if we reached the final state
     251          56 :         return ( END == eCurrentState );
     252             :     }
     253             : 
     254          56 :     bool NumberValidator::isValidNumericFragment( const OUString& _rText )
     255             :     {
     256          56 :         if ( _rText.isEmpty() )
     257             :             // empty strings are always allowed
     258           0 :             return true;
     259             : 
     260             :         // normalize the string
     261          56 :         OUString sNormalized( "_" );
     262          56 :         sNormalized += _rText;
     263          56 :         sNormalized += "_";
     264             : 
     265          56 :         return implValidateNormalized( sNormalized );
     266             :     }
     267             : }
     268             : 
     269             : SvNumberFormatter* FormattedField::StaticFormatter::s_cFormatter = NULL;
     270             : sal_uLong FormattedField::StaticFormatter::s_nReferences = 0;
     271             : 
     272          70 : SvNumberFormatter* FormattedField::StaticFormatter::GetFormatter()
     273             : {
     274          70 :     if (!s_cFormatter)
     275             :     {
     276             :         // get the Office's locale and translate
     277          70 :         LanguageType eSysLanguage = SvtSysLocale().GetLanguageTag().getLanguageType( false);
     278             :         s_cFormatter = new SvNumberFormatter(
     279             :             ::comphelper::getProcessComponentContext(),
     280          70 :             eSysLanguage);
     281             :     }
     282          70 :     return s_cFormatter;
     283             : }
     284             : 
     285         126 : FormattedField::StaticFormatter::StaticFormatter()
     286             : {
     287         126 :     ++s_nReferences;
     288         126 : }
     289             : 
     290         126 : FormattedField::StaticFormatter::~StaticFormatter()
     291             : {
     292         126 :     if (--s_nReferences == 0)
     293             :     {
     294          72 :         delete s_cFormatter;
     295          72 :         s_cFormatter = NULL;
     296             :     }
     297         126 : }
     298             : 
     299             : 
     300         126 : FormattedField::FormattedField(vcl::Window* pParent, WinBits nStyle, SvNumberFormatter* pInitialFormatter, sal_Int32 nFormatKey)
     301             :     :SpinField(pParent, nStyle)
     302             :     ,m_aLastSelection(0,0)
     303             :     ,m_dMinValue(0)
     304             :     ,m_dMaxValue(0)
     305             :     ,m_bHasMin(false)
     306             :     ,m_bHasMax(false)
     307             :     ,m_bStrictFormat(true)
     308             :     ,m_bValueDirty(true)
     309             :     ,m_bEnableEmptyField(true)
     310             :     ,m_bAutoColor(false)
     311             :     ,m_bEnableNaN(false)
     312             :     ,m_dCurrentValue(0)
     313             :     ,m_dDefaultValue(0)
     314             :     ,m_nFormatKey(0)
     315             :     ,m_pFormatter(NULL)
     316             :     ,m_dSpinSize(1)
     317             :     ,m_dSpinFirst(-1000000)
     318             :     ,m_dSpinLast(1000000)
     319             :     ,m_bTreatAsNumber(true)
     320             :     ,m_pLastOutputColor(NULL)
     321         126 :     ,m_bUseInputStringForFormatting(false)
     322             : {
     323             : 
     324         126 :     if (pInitialFormatter)
     325             :     {
     326           0 :         m_pFormatter = pInitialFormatter;
     327           0 :         m_nFormatKey = nFormatKey;
     328             :     }
     329         126 : }
     330             : 
     331           0 : extern "C" SAL_DLLPUBLIC_EXPORT vcl::Window* SAL_CALL makeFormattedField(vcl::Window *pParent, VclBuilder::stringmap &)
     332             : {
     333           0 :     WinBits nWinBits = WB_BORDER | WB_SPIN;
     334           0 :     return new FormattedField(pParent, nWinBits);
     335             : }
     336             : 
     337         184 : FormattedField::~FormattedField()
     338             : {
     339         184 : }
     340             : 
     341         156 : void FormattedField::SetText(const OUString& rStr)
     342             : {
     343             : 
     344         156 :     SpinField::SetText(rStr);
     345         156 :     m_bValueDirty = true;
     346         156 : }
     347             : 
     348           0 : void FormattedField::SetText( const OUString& rStr, const Selection& rNewSelection )
     349             : {
     350             : 
     351           0 :     SpinField::SetText( rStr, rNewSelection );
     352           0 :     m_bValueDirty = true;
     353           0 : }
     354             : 
     355          34 : void FormattedField::SetTextFormatted(const OUString& rStr)
     356             : {
     357             : 
     358             : #if defined DBG_UTIL
     359             :     if (ImplGetFormatter()->IsTextFormat(m_nFormatKey))
     360             :          DBG_WARNING("FormattedField::SetTextFormatted : valid only with text formats !");
     361             : #endif
     362             : 
     363          34 :     m_sCurrentTextValue = rStr;
     364             : 
     365          34 :     OUString sFormatted;
     366          34 :     double dNumber = 0.0;
     367             :     // IsNumberFormat changes the format key parameter
     368          34 :     sal_uInt32 nTempFormatKey = static_cast< sal_uInt32 >( m_nFormatKey );
     369          34 :     if( IsUsingInputStringForFormatting() &&
     370           0 :         ImplGetFormatter()->IsNumberFormat(m_sCurrentTextValue, nTempFormatKey, dNumber) )
     371             :     {
     372           0 :         ImplGetFormatter()->GetInputLineString(dNumber, m_nFormatKey, sFormatted);
     373             :     }
     374             :     else
     375             :     {
     376             :         ImplGetFormatter()->GetOutputString(m_sCurrentTextValue,
     377             :                                             m_nFormatKey,
     378             :                                             sFormatted,
     379          34 :                                             &m_pLastOutputColor);
     380             :     }
     381             : 
     382             :     // calculate the new selection
     383          34 :     Selection aSel(GetSelection());
     384          34 :     Selection aNewSel(aSel);
     385          34 :     aNewSel.Justify();
     386          34 :     sal_Int32 nNewLen = sFormatted.getLength();
     387          34 :     sal_Int32 nCurrentLen = GetText().getLength();
     388          34 :     if ((nNewLen > nCurrentLen) && (aNewSel.Max() == nCurrentLen))
     389             :     {   // the new text is longer and the cursor was behind the last char (of the old text)
     390           6 :         if (aNewSel.Min() == 0)
     391             :         {   // the whole text was selected -> select the new text on the whole, too
     392           6 :             aNewSel.Max() = nNewLen;
     393           6 :             if (!nCurrentLen)
     394             :             {   // there wasn't really a previous selection (as there was no previous text), we're setting a new one -> check the selection options
     395           6 :                 sal_uLong nSelOptions = GetSettings().GetStyleSettings().GetSelectionOptions();
     396           6 :                 if (nSelOptions & SELECTION_OPTION_SHOWFIRST)
     397             :                 {   // selection should be from right to left -> swap min and max
     398           2 :                     aNewSel.Min() = aNewSel.Max();
     399           2 :                     aNewSel.Max() = 0;
     400             :                 }
     401             :             }
     402             :         }
     403           0 :         else if (aNewSel.Max() == aNewSel.Min())
     404             :         {   // there was no selection -> set the cursor behind the new last char
     405           0 :             aNewSel.Max() = nNewLen;
     406           0 :             aNewSel.Min() = nNewLen;
     407             :         }
     408             :     }
     409          28 :     else if (aNewSel.Max() > nNewLen)
     410           0 :         aNewSel.Max() = nNewLen;
     411             :     else
     412          28 :         aNewSel = aSel; // don't use the justified version
     413          34 :     SpinField::SetText(sFormatted, aNewSel);
     414          34 :     m_bValueDirty = false;
     415          34 : }
     416             : 
     417           2 : OUString FormattedField::GetTextValue() const
     418             : {
     419           2 :     if (m_bValueDirty)
     420             :     {
     421           0 :         ((FormattedField*)this)->m_sCurrentTextValue = GetText();
     422           0 :         ((FormattedField*)this)->m_bValueDirty = false;
     423             :     }
     424           2 :     return m_sCurrentTextValue;
     425             : }
     426             : 
     427         106 : void FormattedField::EnableNotANumber( bool _bEnable )
     428             : {
     429         106 :     if ( m_bEnableNaN == _bEnable )
     430         160 :         return;
     431             : 
     432          52 :     m_bEnableNaN = _bEnable;
     433             : }
     434             : 
     435         140 : void FormattedField::SetAutoColor(bool _bAutomatic)
     436             : {
     437         140 :     if (_bAutomatic == m_bAutoColor)
     438         210 :         return;
     439             : 
     440          70 :     m_bAutoColor = _bAutomatic;
     441          70 :     if (m_bAutoColor)
     442             :     {   // if auto color is switched on, adjust the current text color, too
     443          70 :         if (m_pLastOutputColor)
     444           0 :             SetControlForeground(*m_pLastOutputColor);
     445             :         else
     446          70 :             SetControlForeground();
     447             :     }
     448             : }
     449             : 
     450         138 : void FormattedField::impl_Modify(bool makeValueDirty)
     451             : {
     452             : 
     453         138 :     if (!IsStrictFormat())
     454             :     {
     455           0 :         if(makeValueDirty)
     456           0 :             m_bValueDirty = true;
     457           0 :         SpinField::Modify();
     458         138 :         return;
     459             :     }
     460             : 
     461         138 :     OUString sCheck = GetText();
     462         138 :     if (CheckText(sCheck))
     463             :     {
     464         122 :         m_sLastValidText = sCheck;
     465         122 :         m_aLastSelection = GetSelection();
     466         122 :         if(makeValueDirty)
     467         122 :             m_bValueDirty = true;
     468             :     }
     469             :     else
     470             :     {
     471          16 :         ImplSetTextImpl(m_sLastValidText, &m_aLastSelection);
     472             :     }
     473             : 
     474         138 :     SpinField::Modify();
     475             : }
     476             : 
     477         138 : void FormattedField::Modify()
     478             : {
     479             : 
     480         138 :     impl_Modify();
     481         138 : }
     482             : 
     483         164 : void FormattedField::ImplSetTextImpl(const OUString& rNew, Selection* pNewSel)
     484             : {
     485             : 
     486         164 :     if (m_bAutoColor)
     487             :     {
     488         164 :         if (m_pLastOutputColor)
     489           0 :             SetControlForeground(*m_pLastOutputColor);
     490             :         else
     491         164 :             SetControlForeground();
     492             :     }
     493             : 
     494         164 :     if (pNewSel)
     495          16 :         SpinField::SetText(rNew, *pNewSel);
     496             :     else
     497             :     {
     498         148 :         Selection aSel(GetSelection());
     499         148 :         aSel.Justify();
     500             : 
     501         148 :         sal_Int32 nNewLen = rNew.getLength();
     502         148 :         sal_Int32 nCurrentLen = GetText().getLength();
     503             : 
     504         148 :         if ((nNewLen > nCurrentLen) && (aSel.Max() == nCurrentLen))
     505             :         {   // new new text is longer and the cursor is behind the last char
     506          50 :             if (aSel.Min() == 0)
     507             :             {   // the whole text was selected -> select the new text on the whole, too
     508          46 :                 aSel.Max() = nNewLen;
     509          46 :                 if (!nCurrentLen)
     510             :                 {   // there wasn't really a previous selection (as there was no previous text), we're setting a new one -> check the selection options
     511          22 :                     sal_uLong nSelOptions = GetSettings().GetStyleSettings().GetSelectionOptions();
     512          22 :                     if (nSelOptions & SELECTION_OPTION_SHOWFIRST)
     513             :                     {   // selection should be from right to left -> swap min and max
     514           0 :                         aSel.Min() = aSel.Max();
     515           0 :                         aSel.Max() = 0;
     516             :                     }
     517             :                 }
     518             :             }
     519           4 :             else if (aSel.Max() == aSel.Min())
     520             :             {   // there was no selection -> set the cursor behind the new last char
     521           0 :                 aSel.Max() = nNewLen;
     522           0 :                 aSel.Min() = nNewLen;
     523             :             }
     524             :         }
     525          98 :         else if (aSel.Max() > nNewLen)
     526           8 :             aSel.Max() = nNewLen;
     527         148 :         SpinField::SetText(rNew, aSel);
     528             :     }
     529             : 
     530         164 :     m_bValueDirty = true; // not always necessary, but better re-evaluate for safety reasons
     531         164 : }
     532             : 
     533           0 : bool FormattedField::PreNotify(NotifyEvent& rNEvt)
     534             : {
     535           0 :     if (rNEvt.GetType() == EVENT_KEYINPUT)
     536           0 :         m_aLastSelection = GetSelection();
     537           0 :     return SpinField::PreNotify(rNEvt);
     538             : }
     539             : 
     540         410 : void FormattedField::ImplSetFormatKey(sal_uLong nFormatKey)
     541             : {
     542             : 
     543         410 :     m_nFormatKey = nFormatKey;
     544         410 :     bool bNeedFormatter = (m_pFormatter == NULL) && (nFormatKey != 0);
     545         410 :     if (bNeedFormatter)
     546             :     {
     547           0 :         ImplGetFormatter(); // this creates a standard formatter
     548             : 
     549             :         // It might happen that the standard formatter makes no sense here, but it takes a default
     550             :         // format. Thus, it is possible to set one of the other standard keys (which are spanning
     551             :         // across multiple formatters).
     552           0 :         m_nFormatKey = nFormatKey;
     553             :         // When calling SetFormatKey without a formatter, the key must be one of the standard values
     554             :         // that is available for all formatters (and, thus, also in this new one).
     555             :         DBG_ASSERT(m_pFormatter->GetEntry(nFormatKey) != NULL, "FormattedField::ImplSetFormatKey : invalid format key !");
     556             :     }
     557         410 : }
     558             : 
     559         248 : void FormattedField::SetFormatKey(sal_uLong nFormatKey)
     560             : {
     561         248 :     bool bNoFormatter = (m_pFormatter == NULL);
     562         248 :     ImplSetFormatKey(nFormatKey);
     563         248 :     FormatChanged((bNoFormatter && (m_pFormatter != NULL)) ? FCT_FORMATTER : FCT_KEYONLY);
     564         248 : }
     565             : 
     566         128 : void FormattedField::SetFormatter(SvNumberFormatter* pFormatter, bool bResetFormat)
     567             : {
     568             : 
     569         128 :     if (bResetFormat)
     570             :     {
     571         126 :         m_pFormatter = pFormatter;
     572             : 
     573             :         // calc the default format key from the Office's UI locale
     574         126 :         if ( m_pFormatter )
     575             :         {
     576             :             // get the Office's locale and translate
     577         126 :             LanguageType eSysLanguage = SvtSysLocale().GetLanguageTag().getLanguageType( false);
     578             :             // get the standard numeric format for this language
     579         126 :             m_nFormatKey = m_pFormatter->GetStandardFormat( NUMBERFORMAT_NUMBER, eSysLanguage );
     580             :         }
     581             :         else
     582           0 :             m_nFormatKey = 0;
     583             :     }
     584             :     else
     585             :     {
     586             :         LanguageType aOldLang;
     587           2 :         OUString sOldFormat = GetFormat(aOldLang);
     588             : 
     589           2 :         sal_uInt32 nDestKey = pFormatter->TestNewString(sOldFormat);
     590           2 :         if (nDestKey == NUMBERFORMAT_ENTRY_NOT_FOUND)
     591             :         {
     592             :             // language of the new formatter
     593           0 :             const SvNumberformat* pDefaultEntry = pFormatter->GetEntry(0);
     594           0 :             LanguageType aNewLang = pDefaultEntry ? pDefaultEntry->GetLanguage() : LANGUAGE_DONTKNOW;
     595             : 
     596             :             // convert the old format string into the new language
     597             :             sal_Int32 nCheckPos;
     598             :             short nType;
     599           0 :             pFormatter->PutandConvertEntry(sOldFormat, nCheckPos, nType, nDestKey, aOldLang, aNewLang);
     600           0 :             m_nFormatKey = nDestKey;
     601             :         }
     602           2 :         m_pFormatter = pFormatter;
     603             :     }
     604             : 
     605         128 :     FormatChanged(FCT_FORMATTER);
     606         128 : }
     607             : 
     608         388 : OUString FormattedField::GetFormat(LanguageType& eLang) const
     609             : {
     610         388 :     const SvNumberformat* pFormatEntry = ImplGetFormatter()->GetEntry(m_nFormatKey);
     611             :     DBG_ASSERT(pFormatEntry != NULL, "FormattedField::GetFormat: no number format for the given format key.");
     612         388 :     OUString sFormatString = pFormatEntry ? pFormatEntry->GetFormatstring() : OUString();
     613         388 :     eLang = pFormatEntry ? pFormatEntry->GetLanguage() : LANGUAGE_DONTKNOW;
     614             : 
     615         388 :     return sFormatString;
     616             : }
     617             : 
     618         224 : bool FormattedField::SetFormat(const OUString& rFormatString, LanguageType eLang)
     619             : {
     620         224 :     sal_uInt32 nNewKey = ImplGetFormatter()->TestNewString(rFormatString, eLang);
     621         224 :     if (nNewKey == NUMBERFORMAT_ENTRY_NOT_FOUND)
     622             :     {
     623             :         sal_Int32 nCheckPos;
     624             :         short nType;
     625         189 :         OUString rFormat(rFormatString);
     626         189 :         if (!ImplGetFormatter()->PutEntry(rFormat, nCheckPos, nType, nNewKey, eLang))
     627           0 :             return false;
     628         189 :         DBG_ASSERT(nNewKey != NUMBERFORMAT_ENTRY_NOT_FOUND, "FormattedField::SetFormatString : PutEntry returned an invalid key !");
     629             :     }
     630             : 
     631         224 :     if (nNewKey != m_nFormatKey)
     632         190 :         SetFormatKey(nNewKey);
     633         224 :     return true;
     634             : }
     635             : 
     636         224 : bool FormattedField::GetThousandsSep() const
     637             : {
     638             :     DBG_ASSERT(!ImplGetFormatter()->IsTextFormat(m_nFormatKey),
     639             :         "FormattedField::GetThousandsSep : Are you sure what you are doing when setting the precision of a text format?");
     640             : 
     641             :     bool bThousand, IsRed;
     642             :     sal_uInt16 nPrecision, nAnzLeading;
     643         224 :     ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nAnzLeading);
     644             : 
     645         224 :     return bThousand;
     646             : }
     647             : 
     648         101 : void FormattedField::SetThousandsSep(bool _bUseSeparator)
     649             : {
     650             :     DBG_ASSERT(!ImplGetFormatter()->IsTextFormat(m_nFormatKey),
     651             :         "FormattedField::SetThousandsSep : Are you sure what you are doing when setting the precision of a text format?");
     652             : 
     653             :     // get the current settings
     654             :     bool bThousand, IsRed;
     655             :     sal_uInt16 nPrecision, nAnzLeading;
     656         101 :     ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nAnzLeading);
     657         101 :     if (bThousand == (bool)_bUseSeparator)
     658         148 :         return;
     659             : 
     660             :     // we need the language for the following
     661             :     LanguageType eLang;
     662          54 :     GetFormat(eLang);
     663             : 
     664             :     // generate a new format ...
     665          54 :     OUString sFmtDescription = ImplGetFormatter()->GenerateFormat(m_nFormatKey, eLang, _bUseSeparator, IsRed, nPrecision, nAnzLeading);
     666             :     // ... and introduce it to the formatter
     667          54 :     sal_Int32 nCheckPos = 0;
     668             :     sal_uInt32 nNewKey;
     669             :     short nType;
     670          54 :     ImplGetFormatter()->PutEntry(sFmtDescription, nCheckPos, nType, nNewKey, eLang);
     671             : 
     672             :     // set the new key
     673          54 :     ImplSetFormatKey(nNewKey);
     674          54 :     FormatChanged(FCT_THOUSANDSSEP);
     675             : }
     676             : 
     677         224 : sal_uInt16 FormattedField::GetDecimalDigits() const
     678             : {
     679             :     DBG_ASSERT(!ImplGetFormatter()->IsTextFormat(m_nFormatKey),
     680             :         "FormattedField::GetDecimalDigits : Are you sure what you are doing when setting the precision of a text format?");
     681             : 
     682             :     bool bThousand, IsRed;
     683             :     sal_uInt16 nPrecision, nAnzLeading;
     684         224 :     ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nAnzLeading);
     685             : 
     686         224 :     return nPrecision;
     687             : }
     688             : 
     689         108 : void FormattedField::SetDecimalDigits(sal_uInt16 _nPrecision)
     690             : {
     691             :     DBG_ASSERT(!ImplGetFormatter()->IsTextFormat(m_nFormatKey),
     692             :         "FormattedField::SetDecimalDigits : Are you sure what you are doing when setting the precision of a text format?");
     693             : 
     694             :     // get the current settings
     695             :     bool bThousand, IsRed;
     696             :     sal_uInt16 nPrecision, nAnzLeading;
     697         108 :     ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nAnzLeading);
     698         108 :     if (nPrecision == _nPrecision)
     699         108 :         return;
     700             : 
     701             :     // we need the language for the following
     702             :     LanguageType eLang;
     703         108 :     GetFormat(eLang);
     704             : 
     705             :     // generate a new format ...
     706         108 :     OUString sFmtDescription = ImplGetFormatter()->GenerateFormat(m_nFormatKey, eLang, bThousand, IsRed, _nPrecision, nAnzLeading);
     707             :     // ... and introduce it to the formatter
     708         108 :     sal_Int32 nCheckPos = 0;
     709             :     sal_uInt32 nNewKey;
     710             :     short nType;
     711         108 :     ImplGetFormatter()->PutEntry(sFmtDescription, nCheckPos, nType, nNewKey, eLang);
     712             : 
     713             :     // set the new key
     714         108 :     ImplSetFormatKey(nNewKey);
     715         108 :     FormatChanged(FCT_PRECISION);
     716             : }
     717             : 
     718         612 : void FormattedField::FormatChanged( FORMAT_CHANGE_TYPE _nWhat )
     719             : {
     720         612 :     m_pLastOutputColor = NULL;
     721             : 
     722         612 :     if ( ( 0 != ( _nWhat & FCT_FORMATTER ) ) && m_pFormatter )
     723         182 :         m_pFormatter->SetEvalDateFormat( NF_EVALDATEFORMAT_INTL_FORMAT );
     724             : 
     725         612 :     ReFormat();
     726         612 : }
     727             : 
     728           2 : void FormattedField::Commit()
     729             : {
     730             :     // remember the old text
     731           2 :     OUString sOld( GetText() );
     732             : 
     733             :     // do the reformat
     734           2 :     ReFormat();
     735             : 
     736             :     // did the text change?
     737           2 :     if ( GetText() != sOld )
     738             :     {   // consider the field as modified,
     739             :         // but we already have the most recent value;
     740             :         // don't reparse it from the text
     741             :         // (can lead to data loss when the format is lossy,
     742             :         //  as is e.g. our default date format: 2-digit year!)
     743           0 :         impl_Modify(false);
     744           2 :     }
     745           2 : }
     746             : 
     747         846 : void FormattedField::ReFormat()
     748             : {
     749         846 :     if (!IsEmptyFieldEnabled() || !GetText().isEmpty())
     750             :     {
     751          96 :         if (TreatingAsNumber())
     752             :         {
     753          94 :             double dValue = GetValue();
     754          94 :             if ( m_bEnableNaN && ::rtl::math::isNan( dValue ) )
     755         846 :                 return;
     756          94 :             ImplSetValue( dValue, true );
     757             :         }
     758             :         else
     759           2 :             SetTextFormatted(GetTextValue());
     760             :     }
     761             : }
     762             : 
     763          50 : bool FormattedField::Notify(NotifyEvent& rNEvt)
     764             : {
     765             : 
     766          50 :     if ((rNEvt.GetType() == EVENT_KEYINPUT) && !IsReadOnly())
     767             :     {
     768           0 :         const KeyEvent& rKEvt = *rNEvt.GetKeyEvent();
     769           0 :         sal_uInt16 nMod = rKEvt.GetKeyCode().GetModifier();
     770           0 :         switch ( rKEvt.GetKeyCode().GetCode() )
     771             :         {
     772             :             case KEY_UP:
     773             :             case KEY_DOWN:
     774             :             case KEY_PAGEUP:
     775             :             case KEY_PAGEDOWN:
     776           0 :                 if (!nMod && ImplGetFormatter()->IsTextFormat(m_nFormatKey))
     777             :                 {
     778             :                     // the base class would translate this into calls to Up/Down/First/Last,
     779             :                     // but we don't want this if we are text-formatted
     780           0 :                     return true;
     781             :                 }
     782             :         }
     783             :     }
     784             : 
     785          50 :     if ((rNEvt.GetType() == EVENT_COMMAND) && !IsReadOnly())
     786             :     {
     787           0 :         const CommandEvent* pCommand = rNEvt.GetCommandEvent();
     788           0 :         if (pCommand->GetCommand() == COMMAND_WHEEL)
     789             :         {
     790           0 :             const CommandWheelData* pData = rNEvt.GetCommandEvent()->GetWheelData();
     791           0 :             if ((pData->GetMode() == CommandWheelMode::SCROLL) && ImplGetFormatter()->IsTextFormat(m_nFormatKey))
     792             :             {
     793             :                 // same as above : prevent the base class from doing Up/Down-calls
     794             :                 // (normally I should put this test into the Up/Down methods itself, shouldn't I ?)
     795             :                 // FS - 71553 - 19.01.00
     796           0 :                 return true;
     797             :             }
     798             :         }
     799             :     }
     800             : 
     801          50 :     if (rNEvt.GetType() == EVENT_LOSEFOCUS)
     802             :     {
     803             :         // Sonderbehandlung fuer leere Texte
     804           0 :         if (GetText().isEmpty())
     805             :         {
     806           0 :             if (!IsEmptyFieldEnabled())
     807             :             {
     808           0 :                 if (TreatingAsNumber())
     809             :                 {
     810           0 :                     ImplSetValue(m_dCurrentValue, true);
     811           0 :                     Modify();
     812             :                 }
     813             :                 else
     814             :                 {
     815           0 :                     OUString sNew = GetTextValue();
     816           0 :                     if (!sNew.isEmpty())
     817           0 :                         SetTextFormatted(sNew);
     818             :                     else
     819           0 :                         SetTextFormatted(m_sDefaultText);
     820             :                 }
     821           0 :                 m_bValueDirty = false;
     822             :             }
     823             :         }
     824             :         else
     825             :         {
     826           0 :             Commit();
     827             :         }
     828             :     }
     829             : 
     830          50 :     return SpinField::Notify( rNEvt );
     831             : }
     832             : 
     833         116 : void FormattedField::SetMinValue(double dMin)
     834             : {
     835             :     DBG_ASSERT(m_bTreatAsNumber, "FormattedField::SetMinValue : only to be used in numeric mode !");
     836             : 
     837         116 :     m_dMinValue = dMin;
     838         116 :     m_bHasMin = true;
     839             :     // for checking the current value at the new border -> ImplSetValue
     840         116 :     ReFormat();
     841         116 : }
     842             : 
     843         116 : void FormattedField::SetMaxValue(double dMax)
     844             : {
     845             :     DBG_ASSERT(m_bTreatAsNumber, "FormattedField::SetMaxValue : only to be used in numeric mode !");
     846             : 
     847         116 :     m_dMaxValue = dMax;
     848         116 :     m_bHasMax = true;
     849             :     // for checking the current value at the new border -> ImplSetValue
     850         116 :     ReFormat();
     851         116 : }
     852             : 
     853           0 : void FormattedField::SetTextValue(const OUString& rText)
     854             : {
     855           0 :     SetText(rText);
     856           0 :     ReFormat();
     857           0 : }
     858             : 
     859           2 : void FormattedField::EnableEmptyField(bool bEnable)
     860             : {
     861           2 :     if (bEnable == m_bEnableEmptyField)
     862           4 :         return;
     863             : 
     864           0 :     m_bEnableEmptyField = bEnable;
     865           0 :     if (!m_bEnableEmptyField && GetText().isEmpty())
     866           0 :         ImplSetValue(m_dCurrentValue, true);
     867             : }
     868             : 
     869         160 : void FormattedField::ImplSetValue(double dVal, bool bForce)
     870             : {
     871             : 
     872         160 :     if (m_bHasMin && (dVal<m_dMinValue))
     873           0 :         dVal = m_dMinValue;
     874         160 :     if (m_bHasMax && (dVal>m_dMaxValue))
     875          12 :         dVal = m_dMaxValue;
     876         160 :     if (!bForce && (dVal == GetValue()))
     877         172 :         return;
     878             : 
     879             :     DBG_ASSERT(ImplGetFormatter() != NULL, "FormattedField::ImplSetValue : can't set a value without a formatter !");
     880             : 
     881         148 :     m_bValueDirty = false;
     882         148 :     m_dCurrentValue = dVal;
     883             : 
     884         148 :     OUString sNewText;
     885         148 :     if (ImplGetFormatter()->IsTextFormat(m_nFormatKey))
     886             :     {
     887             :         // first convert the number as string in standard format
     888           0 :         OUString sTemp;
     889           0 :         ImplGetFormatter()->GetOutputString(dVal, 0, sTemp, &m_pLastOutputColor);
     890             :         // then encode the string in the corresponding text format
     891           0 :         ImplGetFormatter()->GetOutputString(sTemp, m_nFormatKey, sNewText, &m_pLastOutputColor);
     892             :     }
     893             :     else
     894             :     {
     895         148 :         if( IsUsingInputStringForFormatting())
     896             :         {
     897           0 :             ImplGetFormatter()->GetInputLineString(dVal, m_nFormatKey, sNewText);
     898             :         }
     899             :         else
     900             :         {
     901         148 :             ImplGetFormatter()->GetOutputString(dVal, m_nFormatKey, sNewText, &m_pLastOutputColor);
     902             :         }
     903             :     }
     904             : 
     905         148 :     ImplSetTextImpl(sNewText, NULL);
     906         148 :     m_bValueDirty = false;
     907         148 :     DBG_ASSERT(CheckText(sNewText), "FormattedField::ImplSetValue : formatted string doesn't match the criteria !");
     908             : }
     909             : 
     910         582 : bool FormattedField::ImplGetValue(double& dNewVal)
     911             : {
     912             : 
     913         582 :     dNewVal = m_dCurrentValue;
     914         582 :     if (!m_bValueDirty)
     915         438 :         return true;
     916             : 
     917         144 :     dNewVal = m_dDefaultValue;
     918         144 :     OUString sText(GetText());
     919         144 :     if (sText.isEmpty())
     920          10 :         return true;
     921             : 
     922             :     DBG_ASSERT(ImplGetFormatter() != NULL, "FormattedField::ImplGetValue : can't give you a current value without a formatter !");
     923             : 
     924         134 :     sal_uInt32 nFormatKey = m_nFormatKey; // IsNumberFormat changes the FormatKey!
     925             : 
     926         134 :     if (ImplGetFormatter()->IsTextFormat(nFormatKey) && m_bTreatAsNumber)
     927             :         // for detection of values like "1,1" in fields that are formated as text
     928           0 :         nFormatKey = 0;
     929             : 
     930             :     // special treatment for percentage formatting
     931         134 :     if (ImplGetFormatter()->GetType(m_nFormatKey) == NUMBERFORMAT_PERCENT)
     932             :     {
     933             :         // the language of our format
     934           0 :         LanguageType eLanguage = m_pFormatter->GetEntry(m_nFormatKey)->GetLanguage();
     935             :         // the default number format for this language
     936           0 :         sal_uLong nStandardNumericFormat = m_pFormatter->GetStandardFormat(NUMBERFORMAT_NUMBER, eLanguage);
     937             : 
     938           0 :         sal_uInt32 nTempFormat = nStandardNumericFormat;
     939             :         double dTemp;
     940           0 :         if (m_pFormatter->IsNumberFormat(sText, nTempFormat, dTemp) &&
     941           0 :             NUMBERFORMAT_NUMBER == m_pFormatter->GetType(nTempFormat))
     942             :             // the string is equivalent to a number formatted one (has no % sign) -> append it
     943           0 :             sText += "%";
     944             :         // (with this, a input of '3' becomes '3%', which then by the formatter is translated
     945             :         // into 0.03. Without this, the formatter would give us the double 3 for an input '3',
     946             :         // which equals 300 percent.
     947             :     }
     948         134 :     if (!ImplGetFormatter()->IsNumberFormat(sText, nFormatKey, dNewVal))
     949          26 :         return false;
     950             : 
     951         108 :     if (m_bHasMin && (dNewVal<m_dMinValue))
     952           0 :         dNewVal = m_dMinValue;
     953         108 :     if (m_bHasMax && (dNewVal>m_dMaxValue))
     954           0 :         dNewVal = m_dMaxValue;
     955         108 :     return true;
     956             : }
     957             : 
     958          66 : void FormattedField::SetValue(double dVal)
     959             : {
     960          66 :     ImplSetValue(dVal, m_bValueDirty);
     961          66 : }
     962             : 
     963         582 : double FormattedField::GetValue()
     964             : {
     965             : 
     966         582 :     if ( !ImplGetValue( m_dCurrentValue ) )
     967             :     {
     968          26 :         if ( m_bEnableNaN )
     969           0 :             ::rtl::math::setNan( &m_dCurrentValue );
     970             :         else
     971          26 :             m_dCurrentValue = m_dDefaultValue;
     972             :     }
     973             : 
     974         582 :     m_bValueDirty = false;
     975         582 :     return m_dCurrentValue;
     976             : }
     977             : 
     978          20 : void FormattedField::Up()
     979             : {
     980             :     // setValue handles under- and overflows (min/max) automatically
     981          20 :     SetValue(GetValue() + m_dSpinSize);
     982          20 :     SetModifyFlag();
     983          20 :     Modify();
     984             : 
     985          20 :     SpinField::Up();
     986          20 : }
     987             : 
     988          10 : void FormattedField::Down()
     989             : {
     990          10 :     SetValue(GetValue() - m_dSpinSize);
     991          10 :     SetModifyFlag();
     992          10 :     Modify();
     993             : 
     994          10 :     SpinField::Down();
     995          10 : }
     996             : 
     997          10 : void FormattedField::First()
     998             : {
     999          10 :     if (m_bHasMin)
    1000             :     {
    1001           8 :         SetValue(m_dMinValue);
    1002           8 :         SetModifyFlag();
    1003           8 :         Modify();
    1004             :     }
    1005             : 
    1006          10 :     SpinField::First();
    1007          10 : }
    1008             : 
    1009          10 : void FormattedField::Last()
    1010             : {
    1011          10 :     if (m_bHasMax)
    1012             :     {
    1013           8 :         SetValue(m_dMaxValue);
    1014           8 :         SetModifyFlag();
    1015           8 :         Modify();
    1016             :     }
    1017             : 
    1018          10 :     SpinField::Last();
    1019          10 : }
    1020             : 
    1021           0 : void FormattedField::UseInputStringForFormatting( bool bUseInputStr /* = true */ )
    1022             : {
    1023           0 :     m_bUseInputStringForFormatting = bUseInputStr;
    1024           0 : }
    1025             : 
    1026             : 
    1027         102 : DoubleNumericField::~DoubleNumericField()
    1028             : {
    1029          34 :     delete m_pNumberValidator;
    1030          68 : }
    1031             : 
    1032         114 : void DoubleNumericField::FormatChanged(FORMAT_CHANGE_TYPE nWhat)
    1033             : {
    1034         114 :     ResetConformanceTester();
    1035         114 :     FormattedField::FormatChanged(nWhat);
    1036         114 : }
    1037             : 
    1038          56 : bool DoubleNumericField::CheckText(const OUString& sText) const
    1039             : {
    1040             :     // We'd like to implement this using the NumberFormatter::IsNumberFormat, but unfortunately, this doesn't
    1041             :     // recognize fragments of numbers (like, for instance "1e", which happens during entering e.g. "1e10")
    1042             :     // Thus, the roundabout way via a regular expression
    1043          56 :     return m_pNumberValidator->isValidNumericFragment( sText );
    1044             : }
    1045             : 
    1046         148 : void DoubleNumericField::ResetConformanceTester()
    1047             : {
    1048             :     // the thousands and the decimal separator are language dependent
    1049         148 :     const SvNumberformat* pFormatEntry = ImplGetFormatter()->GetEntry(m_nFormatKey);
    1050             : 
    1051         148 :     sal_Unicode cSeparatorThousand = ',';
    1052         148 :     sal_Unicode cSeparatorDecimal = '.';
    1053         148 :     if (pFormatEntry)
    1054             :     {
    1055         148 :         LocaleDataWrapper aLocaleInfo( LanguageTag( pFormatEntry->GetLanguage()) );
    1056             : 
    1057         296 :         OUString sSeparator = aLocaleInfo.getNumThousandSep();
    1058         148 :         if (!sSeparator.isEmpty())
    1059         148 :             cSeparatorThousand = sSeparator[0];
    1060             : 
    1061         148 :         sSeparator = aLocaleInfo.getNumDecimalSep();
    1062         148 :         if (!sSeparator.isEmpty())
    1063         296 :             cSeparatorDecimal = sSeparator[0];
    1064             :     }
    1065             : 
    1066         148 :     delete m_pNumberValidator;
    1067         148 :     m_pNumberValidator = new validation::NumberValidator( cSeparatorThousand, cSeparatorDecimal );
    1068         148 : }
    1069             : 
    1070          34 : DoubleCurrencyField::DoubleCurrencyField(vcl::Window* pParent, WinBits nStyle)
    1071             :     :FormattedField(pParent, nStyle)
    1072          34 :     ,m_bChangingFormat(false)
    1073             : {
    1074          34 :     m_bPrependCurrSym = false;
    1075             : 
    1076             :     // initialize with a system currency format
    1077          34 :     m_sCurrencySymbol = SvtSysLocale().GetLocaleData().getCurrSymbol();
    1078          34 :     UpdateCurrencyFormat();
    1079          34 : }
    1080             : 
    1081         380 : void DoubleCurrencyField::FormatChanged(FORMAT_CHANGE_TYPE nWhat)
    1082             : {
    1083         380 :     if (m_bChangingFormat)
    1084             :     {
    1085         190 :         FormattedField::FormatChanged(nWhat);
    1086         570 :         return;
    1087             :     }
    1088             : 
    1089         190 :     switch (nWhat)
    1090             :     {
    1091             :         case FCT_FORMATTER:
    1092             :         case FCT_PRECISION:
    1093             :         case FCT_THOUSANDSSEP:
    1094             :             // the aspects which changed don't take our currency settings into account (in fact, they most probably
    1095             :             // destroyed them)
    1096         116 :             UpdateCurrencyFormat();
    1097         116 :             break;
    1098             :         case FCT_KEYONLY:
    1099             :             OSL_FAIL("DoubleCurrencyField::FormatChanged : somebody modified my key !");
    1100             :             // We always build our own format from the settings we get via special methods (setCurrencySymbol etc.).
    1101             :             // Nobody but ourself should modifiy the format key directly !
    1102           0 :             break;
    1103             :     }
    1104             : 
    1105         190 :     FormattedField::FormatChanged(nWhat);
    1106             : }
    1107             : 
    1108          50 : void DoubleCurrencyField::setCurrencySymbol(const OUString& rSymbol)
    1109             : {
    1110          50 :     if (m_sCurrencySymbol == rSymbol)
    1111          66 :         return;
    1112             : 
    1113          34 :     m_sCurrencySymbol = rSymbol;
    1114          34 :     UpdateCurrencyFormat();
    1115          34 :     FormatChanged(FCT_CURRENCY_SYMBOL);
    1116             : }
    1117             : 
    1118          50 : void DoubleCurrencyField::setPrependCurrSym(bool _bPrepend)
    1119             : {
    1120          50 :     if (m_bPrependCurrSym == _bPrepend)
    1121          60 :          return;
    1122             : 
    1123          40 :     m_bPrependCurrSym = _bPrepend;
    1124          40 :     UpdateCurrencyFormat();
    1125          40 :     FormatChanged(FCT_CURRSYM_POSITION);
    1126             : }
    1127             : 
    1128         224 : void DoubleCurrencyField::UpdateCurrencyFormat()
    1129             : {
    1130             :     // the old settings
    1131             :     LanguageType eLanguage;
    1132         224 :     GetFormat(eLanguage);
    1133         224 :     bool bThSep = GetThousandsSep();
    1134         224 :     sal_uInt16 nDigits = GetDecimalDigits();
    1135             : 
    1136             :     // build a new format string with the base class' and my own settings
    1137             : 
    1138             :     /* Strangely with gcc 4.6.3 this needs a temporary LanguageTag, otherwise
    1139             :      * there's
    1140             :      * error: request for member 'getNumThousandSep' in 'aLocaleInfo', which is
    1141             :      * of non-class type 'LocaleDataWrapper(LanguageTag)' */
    1142         224 :     LanguageTag aLanguageTag( eLanguage);
    1143         448 :     LocaleDataWrapper aLocaleInfo( aLanguageTag );
    1144             : 
    1145         448 :     OUStringBuffer sNewFormat;
    1146         224 :     if (bThSep)
    1147             :     {
    1148          37 :         sNewFormat.append('#');
    1149          37 :         sNewFormat.append(aLocaleInfo.getNumThousandSep());
    1150          37 :         sNewFormat.append("##0");
    1151             :     }
    1152             :     else
    1153         187 :         sNewFormat.append('0');
    1154             : 
    1155         224 :     if (nDigits)
    1156             :     {
    1157         138 :         sNewFormat.append(aLocaleInfo.getNumDecimalSep());
    1158             : 
    1159         138 :         OUStringBuffer sTemp;
    1160         138 :         comphelper::string::padToLength(sTemp, nDigits, '0');
    1161         138 :         sNewFormat.append(sTemp);
    1162             :     }
    1163             : 
    1164         224 :     if (getPrependCurrSym())
    1165             :     {
    1166          61 :         OUString sSymbol = getCurrencySymbol();
    1167          61 :         sSymbol = comphelper::string::stripStart(sSymbol, ' ');
    1168          61 :         sSymbol = comphelper::string::stripEnd(sSymbol, ' ');
    1169             : 
    1170         122 :         OUStringBuffer sTemp("[$");
    1171          61 :         sTemp.append(sSymbol);
    1172          61 :         sTemp.append("] ");
    1173          61 :         sTemp.append(sNewFormat);
    1174             : 
    1175             :         // for negative values : $ -0.00, not -$ 0.00 ...
    1176             :         // (the real solution would be a possibility to choose a "positive currency format" and a "negative currency format" ...
    1177             :         // But not now ... (and hey, you could take a formatted field for this ....))
    1178             :         // FS - 31.03.00 74642
    1179          61 :         sTemp.append(";[$");
    1180          61 :         sTemp.append(sSymbol);
    1181          61 :         sTemp.append("] -");
    1182          61 :         sTemp.append(sNewFormat);
    1183             : 
    1184         122 :         sNewFormat = sTemp;
    1185             :     }
    1186             :     else
    1187             :     {
    1188         163 :         OUString sTemp = getCurrencySymbol();
    1189         163 :         sTemp = comphelper::string::stripStart(sTemp, ' ');
    1190         163 :         sTemp = comphelper::string::stripEnd(sTemp, ' ');
    1191             : 
    1192         163 :         sNewFormat.append(" [$");
    1193         163 :         sNewFormat.append(sTemp);
    1194         163 :         sNewFormat.append(']');
    1195             :     }
    1196             : 
    1197             :     // set this new basic format
    1198         224 :     m_bChangingFormat = true;
    1199         224 :     SetFormat(sNewFormat.makeStringAndClear(), eLanguage);
    1200         448 :     m_bChangingFormat = false;
    1201        1451 : }
    1202             : 
    1203             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10