LCOV - code coverage report
Current view: top level - svtools/source/control - fmtfield.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 507 0.0 %
Date: 2014-04-14 Functions: 0 63 0.0 %
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           0 :     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           0 :     static void lcl_insertStopTransition( StateTransitions& _rRow )
      92             :     {
      93           0 :         _rRow.insert( Transition( '_', END ) );
      94           0 :     }
      95             : 
      96           0 :     static void lcl_insertStartExponentTransition( StateTransitions& _rRow )
      97             :     {
      98           0 :         _rRow.insert( Transition( 'e', EXPONENT_START ) );
      99           0 :     }
     100             : 
     101           0 :     static void lcl_insertSignTransitions( StateTransitions& _rRow, const State eNextState )
     102             :     {
     103           0 :         _rRow.insert( Transition( '-', eNextState ) );
     104           0 :         _rRow.insert( Transition( '+', eNextState ) );
     105           0 :     }
     106             : 
     107           0 :     static void lcl_insertDigitTransitions( StateTransitions& _rRow, const State eNextState )
     108             :     {
     109           0 :         for ( sal_Unicode aChar = '0'; aChar <= '9'; ++aChar )
     110           0 :             _rRow.insert( Transition( aChar, eNextState ) );
     111           0 :     }
     112             : 
     113           0 :     static void lcl_insertCommonPreCommaTransitions( StateTransitions& _rRow, const sal_Unicode _cThSep, const sal_Unicode _cDecSep )
     114             :     {
     115             :         // digits are allowed
     116           0 :         lcl_insertDigitTransitions( _rRow, DIGIT_PRE_COMMA );
     117             : 
     118             :         // the thousand separator is allowed
     119           0 :         _rRow.insert( Transition( _cThSep, DIGIT_PRE_COMMA ) );
     120             : 
     121             :         // a comma is allowed
     122           0 :         _rRow.insert( Transition( _cDecSep, DIGIT_POST_COMMA ) );
     123           0 :     }
     124             : 
     125           0 :     NumberValidator::NumberValidator( const sal_Unicode _cThSep, const sal_Unicode _cDecSep )
     126             :         :m_cThSep( _cThSep )
     127           0 :         ,m_cDecSep( _cDecSep )
     128             :     {
     129             :         // build up our transition table
     130             : 
     131             :         // how to procede from START
     132             :         {
     133           0 :             StateTransitions& rRow = m_aTransitions[ START ];
     134           0 :             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           0 :             StateTransitions& rRow = m_aTransitions[ NUM_START ];
     141             : 
     142             :             // a sign is allowed
     143           0 :             lcl_insertSignTransitions( rRow, DIGIT_PRE_COMMA );
     144             : 
     145             :             // common transitions for the two pre-comma states
     146           0 :             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           0 :             lcl_insertStartExponentTransition( rRow );
     151             :         }
     152             : 
     153             :         // how to procede from DIGIT_PRE_COMMA
     154             :         {
     155           0 :             StateTransitions& rRow = m_aTransitions[ DIGIT_PRE_COMMA ];
     156             : 
     157             :             // common transitions for the two pre-comma states
     158           0 :             lcl_insertCommonPreCommaTransitions( rRow, m_cThSep, m_cDecSep );
     159             : 
     160             :             // the exponent may start here
     161           0 :             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           0 :             lcl_insertStopTransition( rRow );
     166             :         }
     167             : 
     168             :         // how to procede from DIGIT_POST_COMMA
     169             :         {
     170           0 :             StateTransitions& rRow = m_aTransitions[ DIGIT_POST_COMMA ];
     171             : 
     172             :             // there might be digits, which would keep the state at DIGIT_POST_COMMA
     173           0 :             lcl_insertDigitTransitions( rRow, DIGIT_POST_COMMA );
     174             : 
     175             :             // the exponent may start here
     176           0 :             lcl_insertStartExponentTransition( rRow );
     177             : 
     178             :             // the string may end here
     179           0 :             lcl_insertStopTransition( rRow );
     180             :         }
     181             : 
     182             :         // how to procede from EXPONENT_START
     183             :         {
     184           0 :             StateTransitions& rRow = m_aTransitions[ EXPONENT_START ];
     185             : 
     186             :             // there may be a sign
     187           0 :             lcl_insertSignTransitions( rRow, EXPONENT_DIGIT );
     188             : 
     189             :             // there may be digits
     190           0 :             lcl_insertDigitTransitions( rRow, EXPONENT_DIGIT );
     191             : 
     192             :             // the string may end here
     193           0 :             lcl_insertStopTransition( rRow );
     194             :         }
     195             : 
     196             :         // how to procede from EXPONENT_DIGIT
     197             :         {
     198           0 :             StateTransitions& rRow = m_aTransitions[ EXPONENT_DIGIT ];
     199             : 
     200             :             // there may be digits
     201           0 :             lcl_insertDigitTransitions( rRow, EXPONENT_DIGIT );
     202             : 
     203             :             // the string may end here
     204           0 :             lcl_insertStopTransition( rRow );
     205             :         }
     206             : 
     207             :         // how to procede from END
     208             :         {
     209           0 :             /*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           0 :     }
     214             : 
     215           0 :     bool NumberValidator::implValidateNormalized( const OUString& _rText )
     216             :     {
     217           0 :         const sal_Unicode* pCheckPos = _rText.getStr();
     218           0 :         State eCurrentState = START;
     219             : 
     220           0 :         while ( END != eCurrentState )
     221             :         {
     222             :             // look up the transition row for the current state
     223           0 :             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           0 :             if ( m_aTransitions.end() != aRow )
     228             :             {
     229             :                 // look up the current character in this row
     230           0 :                 StateTransitions::const_iterator aTransition = aRow->second.find( *pCheckPos );
     231           0 :                 if ( aRow->second.end() != aTransition )
     232             :                 {
     233             :                     // there is a valid transition for this character
     234           0 :                     eCurrentState = aTransition->second;
     235           0 :                     ++pCheckPos;
     236           0 :                     continue;
     237             :                 }
     238             :             }
     239             : 
     240             :             // if we're here, there is no valid transition
     241           0 :             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           0 :         return ( END == eCurrentState );
     252             :     }
     253             : 
     254           0 :     bool NumberValidator::isValidNumericFragment( const OUString& _rText )
     255             :     {
     256           0 :         if ( _rText.isEmpty() )
     257             :             // empty strings are always allowed
     258           0 :             return true;
     259             : 
     260             :         // normalize the string
     261           0 :         OUString sNormalized( "_" );
     262           0 :         sNormalized += _rText;
     263           0 :         sNormalized += "_";
     264             : 
     265           0 :         return implValidateNormalized( sNormalized );
     266             :     }
     267             : }
     268             : 
     269             : SvNumberFormatter* FormattedField::StaticFormatter::s_cFormatter = NULL;
     270             : sal_uLong FormattedField::StaticFormatter::s_nReferences = 0;
     271             : 
     272           0 : SvNumberFormatter* FormattedField::StaticFormatter::GetFormatter()
     273             : {
     274           0 :     if (!s_cFormatter)
     275             :     {
     276             :         // get the Office's locale and translate
     277           0 :         LanguageType eSysLanguage = SvtSysLocale().GetLanguageTag().getLanguageType( false);
     278             :         s_cFormatter = new SvNumberFormatter(
     279             :             ::comphelper::getProcessComponentContext(),
     280           0 :             eSysLanguage);
     281             :     }
     282           0 :     return s_cFormatter;
     283             : }
     284             : 
     285           0 : FormattedField::StaticFormatter::StaticFormatter()
     286             : {
     287           0 :     ++s_nReferences;
     288           0 : }
     289             : 
     290           0 : FormattedField::StaticFormatter::~StaticFormatter()
     291             : {
     292           0 :     if (--s_nReferences == 0)
     293             :     {
     294           0 :         delete s_cFormatter;
     295           0 :         s_cFormatter = NULL;
     296             :     }
     297           0 : }
     298             : 
     299             : 
     300           0 : FormattedField::FormattedField(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           0 :     ,m_bUseInputStringForFormatting(false)
     322             : {
     323             : 
     324           0 :     if (pInitialFormatter)
     325             :     {
     326           0 :         m_pFormatter = pInitialFormatter;
     327           0 :         m_nFormatKey = nFormatKey;
     328             :     }
     329           0 : }
     330             : 
     331           0 : extern "C" SAL_DLLPUBLIC_EXPORT Window* SAL_CALL makeFormattedField(Window *pParent, VclBuilder::stringmap &)
     332             : {
     333           0 :     WinBits nWinBits = WB_BORDER;
     334           0 :     return new FormattedField(pParent, nWinBits);
     335             : }
     336             : 
     337           0 : FormattedField::~FormattedField()
     338             : {
     339           0 : }
     340             : 
     341           0 : void FormattedField::SetText(const OUString& rStr)
     342             : {
     343             : 
     344           0 :     SpinField::SetText(rStr);
     345           0 :     m_bValueDirty = true;
     346           0 : }
     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           0 : 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           0 :     m_sCurrentTextValue = rStr;
     364             : 
     365           0 :     OUString sFormatted;
     366           0 :     double dNumber = 0.0;
     367             :     // IsNumberFormat changes the format key parameter
     368           0 :     sal_uInt32 nTempFormatKey = static_cast< sal_uInt32 >( m_nFormatKey );
     369           0 :     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           0 :                                             &m_pLastOutputColor);
     380             :     }
     381             : 
     382             :     // calculate the new selection
     383           0 :     Selection aSel(GetSelection());
     384           0 :     Selection aNewSel(aSel);
     385           0 :     aNewSel.Justify();
     386           0 :     sal_Int32 nNewLen = sFormatted.getLength();
     387           0 :     sal_Int32 nCurrentLen = GetText().getLength();
     388           0 :     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           0 :         if (aNewSel.Min() == 0)
     391             :         {   // the whole text was selected -> select the new text on the whole, too
     392           0 :             aNewSel.Max() = nNewLen;
     393           0 :             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           0 :                 sal_uLong nSelOptions = GetSettings().GetStyleSettings().GetSelectionOptions();
     396           0 :                 if (nSelOptions & SELECTION_OPTION_SHOWFIRST)
     397             :                 {   // selection should be from right to left -> swap min and max
     398           0 :                     aNewSel.Min() = aNewSel.Max();
     399           0 :                     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           0 :     else if (aNewSel.Max() > nNewLen)
     410           0 :         aNewSel.Max() = nNewLen;
     411             :     else
     412           0 :         aNewSel = aSel; // don't use the justified version
     413           0 :     SpinField::SetText(sFormatted, aNewSel);
     414           0 :     m_bValueDirty = false;
     415           0 : }
     416             : 
     417           0 : OUString FormattedField::GetTextValue() const
     418             : {
     419           0 :     if (m_bValueDirty)
     420             :     {
     421           0 :         ((FormattedField*)this)->m_sCurrentTextValue = GetText();
     422           0 :         ((FormattedField*)this)->m_bValueDirty = false;
     423             :     }
     424           0 :     return m_sCurrentTextValue;
     425             : }
     426             : 
     427           0 : void FormattedField::EnableNotANumber( bool _bEnable )
     428             : {
     429           0 :     if ( m_bEnableNaN == _bEnable )
     430           0 :         return;
     431             : 
     432           0 :     m_bEnableNaN = _bEnable;
     433             : }
     434             : 
     435           0 : void FormattedField::SetAutoColor(bool _bAutomatic)
     436             : {
     437           0 :     if (_bAutomatic == m_bAutoColor)
     438           0 :         return;
     439             : 
     440           0 :     m_bAutoColor = _bAutomatic;
     441           0 :     if (m_bAutoColor)
     442             :     {   // if auto color is switched on, adjust the current text color, too
     443           0 :         if (m_pLastOutputColor)
     444           0 :             SetControlForeground(*m_pLastOutputColor);
     445             :         else
     446           0 :             SetControlForeground();
     447             :     }
     448             : }
     449             : 
     450           0 : void FormattedField::impl_Modify(bool makeValueDirty)
     451             : {
     452             : 
     453           0 :     if (!IsStrictFormat())
     454             :     {
     455           0 :         if(makeValueDirty)
     456           0 :             m_bValueDirty = true;
     457           0 :         SpinField::Modify();
     458           0 :         return;
     459             :     }
     460             : 
     461           0 :     OUString sCheck = GetText();
     462           0 :     if (CheckText(sCheck))
     463             :     {
     464           0 :         m_sLastValidText = sCheck;
     465           0 :         m_aLastSelection = GetSelection();
     466           0 :         if(makeValueDirty)
     467           0 :             m_bValueDirty = true;
     468             :     }
     469             :     else
     470             :     {
     471           0 :         ImplSetTextImpl(m_sLastValidText, &m_aLastSelection);
     472             :     }
     473             : 
     474           0 :     SpinField::Modify();
     475             : }
     476             : 
     477           0 : void FormattedField::Modify()
     478             : {
     479             : 
     480           0 :     impl_Modify();
     481           0 : }
     482             : 
     483           0 : void FormattedField::ImplSetTextImpl(const OUString& rNew, Selection* pNewSel)
     484             : {
     485             : 
     486           0 :     if (m_bAutoColor)
     487             :     {
     488           0 :         if (m_pLastOutputColor)
     489           0 :             SetControlForeground(*m_pLastOutputColor);
     490             :         else
     491           0 :             SetControlForeground();
     492             :     }
     493             : 
     494           0 :     if (pNewSel)
     495           0 :         SpinField::SetText(rNew, *pNewSel);
     496             :     else
     497             :     {
     498           0 :         Selection aSel(GetSelection());
     499           0 :         aSel.Justify();
     500             : 
     501           0 :         sal_Int32 nNewLen = rNew.getLength();
     502           0 :         sal_Int32 nCurrentLen = GetText().getLength();
     503             : 
     504           0 :         if ((nNewLen > nCurrentLen) && (aSel.Max() == nCurrentLen))
     505             :         {   // new new text is longer and the cursor is behind the last char
     506           0 :             if (aSel.Min() == 0)
     507             :             {   // the whole text was selected -> select the new text on the whole, too
     508           0 :                 aSel.Max() = nNewLen;
     509           0 :                 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           0 :                     sal_uLong nSelOptions = GetSettings().GetStyleSettings().GetSelectionOptions();
     512           0 :                     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           0 :             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           0 :         else if (aSel.Max() > nNewLen)
     526           0 :             aSel.Max() = nNewLen;
     527           0 :         SpinField::SetText(rNew, aSel);
     528             :     }
     529             : 
     530           0 :     m_bValueDirty = true; // not always necessary, but better re-evaluate for safety reasons
     531           0 : }
     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           0 : void FormattedField::ImplSetFormatKey(sal_uLong nFormatKey)
     541             : {
     542             : 
     543           0 :     m_nFormatKey = nFormatKey;
     544           0 :     bool bNeedFormatter = (m_pFormatter == NULL) && (nFormatKey != 0);
     545           0 :     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           0 : }
     558             : 
     559           0 : void FormattedField::SetFormatKey(sal_uLong nFormatKey)
     560             : {
     561           0 :     bool bNoFormatter = (m_pFormatter == NULL);
     562           0 :     ImplSetFormatKey(nFormatKey);
     563           0 :     FormatChanged((bNoFormatter && (m_pFormatter != NULL)) ? FCT_FORMATTER : FCT_KEYONLY);
     564           0 : }
     565             : 
     566           0 : void FormattedField::SetFormatter(SvNumberFormatter* pFormatter, bool bResetFormat)
     567             : {
     568             : 
     569           0 :     if (bResetFormat)
     570             :     {
     571           0 :         m_pFormatter = pFormatter;
     572             : 
     573             :         // calc the default format key from the Office's UI locale
     574           0 :         if ( m_pFormatter )
     575             :         {
     576             :             // get the Office's locale and translate
     577           0 :             LanguageType eSysLanguage = SvtSysLocale().GetLanguageTag().getLanguageType( false);
     578             :             // get the standard numeric format for this language
     579           0 :             m_nFormatKey = m_pFormatter->GetStandardFormat( NUMBERFORMAT_NUMBER, eSysLanguage );
     580             :         }
     581             :         else
     582           0 :             m_nFormatKey = 0;
     583             :     }
     584             :     else
     585             :     {
     586             :         LanguageType aOldLang;
     587           0 :         OUString sOldFormat = GetFormat(aOldLang);
     588             : 
     589           0 :         sal_uInt32 nDestKey = pFormatter->TestNewString(sOldFormat);
     590           0 :         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           0 :         m_pFormatter = pFormatter;
     603             :     }
     604             : 
     605           0 :     FormatChanged(FCT_FORMATTER);
     606           0 : }
     607             : 
     608           0 : OUString FormattedField::GetFormat(LanguageType& eLang) const
     609             : {
     610           0 :     const SvNumberformat* pFormatEntry = ImplGetFormatter()->GetEntry(m_nFormatKey);
     611             :     DBG_ASSERT(pFormatEntry != NULL, "FormattedField::GetFormat: no number format for the given format key.");
     612           0 :     OUString sFormatString = pFormatEntry ? pFormatEntry->GetFormatstring() : OUString();
     613           0 :     eLang = pFormatEntry ? pFormatEntry->GetLanguage() : LANGUAGE_DONTKNOW;
     614             : 
     615           0 :     return sFormatString;
     616             : }
     617             : 
     618           0 : bool FormattedField::SetFormat(const OUString& rFormatString, LanguageType eLang)
     619             : {
     620           0 :     sal_uInt32 nNewKey = ImplGetFormatter()->TestNewString(rFormatString, eLang);
     621           0 :     if (nNewKey == NUMBERFORMAT_ENTRY_NOT_FOUND)
     622             :     {
     623             :         sal_Int32 nCheckPos;
     624             :         short nType;
     625           0 :         OUString rFormat(rFormatString);
     626           0 :         if (!ImplGetFormatter()->PutEntry(rFormat, nCheckPos, nType, nNewKey, eLang))
     627           0 :             return false;
     628           0 :         DBG_ASSERT(nNewKey != NUMBERFORMAT_ENTRY_NOT_FOUND, "FormattedField::SetFormatString : PutEntry returned an invalid key !");
     629             :     }
     630             : 
     631           0 :     if (nNewKey != m_nFormatKey)
     632           0 :         SetFormatKey(nNewKey);
     633           0 :     return true;
     634             : }
     635             : 
     636           0 : 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           0 :     ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nAnzLeading);
     644             : 
     645           0 :     return bThousand;
     646             : }
     647             : 
     648           0 : 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           0 :     ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nAnzLeading);
     657           0 :     if (bThousand == (bool)_bUseSeparator)
     658           0 :         return;
     659             : 
     660             :     // we need the language for the following
     661             :     LanguageType eLang;
     662           0 :     GetFormat(eLang);
     663             : 
     664             :     // generate a new format ...
     665           0 :     OUString sFmtDescription = ImplGetFormatter()->GenerateFormat(m_nFormatKey, eLang, _bUseSeparator, IsRed, nPrecision, nAnzLeading);
     666             :     // ... and introduce it to the formatter
     667           0 :     sal_Int32 nCheckPos = 0;
     668             :     sal_uInt32 nNewKey;
     669             :     short nType;
     670           0 :     ImplGetFormatter()->PutEntry(sFmtDescription, nCheckPos, nType, nNewKey, eLang);
     671             : 
     672             :     // set the new key
     673           0 :     ImplSetFormatKey(nNewKey);
     674           0 :     FormatChanged(FCT_THOUSANDSSEP);
     675             : }
     676             : 
     677           0 : 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           0 :     ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nAnzLeading);
     685             : 
     686           0 :     return nPrecision;
     687             : }
     688             : 
     689           0 : 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           0 :     ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nAnzLeading);
     698           0 :     if (nPrecision == _nPrecision)
     699           0 :         return;
     700             : 
     701             :     // we need the language for the following
     702             :     LanguageType eLang;
     703           0 :     GetFormat(eLang);
     704             : 
     705             :     // generate a new format ...
     706           0 :     OUString sFmtDescription = ImplGetFormatter()->GenerateFormat(m_nFormatKey, eLang, bThousand, IsRed, _nPrecision, nAnzLeading);
     707             :     // ... and introduce it to the formatter
     708           0 :     sal_Int32 nCheckPos = 0;
     709             :     sal_uInt32 nNewKey;
     710             :     short nType;
     711           0 :     ImplGetFormatter()->PutEntry(sFmtDescription, nCheckPos, nType, nNewKey, eLang);
     712             : 
     713             :     // set the new key
     714           0 :     ImplSetFormatKey(nNewKey);
     715           0 :     FormatChanged(FCT_PRECISION);
     716             : }
     717             : 
     718           0 : void FormattedField::FormatChanged( FORMAT_CHANGE_TYPE _nWhat )
     719             : {
     720           0 :     m_pLastOutputColor = NULL;
     721             : 
     722           0 :     if ( ( 0 != ( _nWhat & FCT_FORMATTER ) ) && m_pFormatter )
     723           0 :         m_pFormatter->SetEvalDateFormat( NF_EVALDATEFORMAT_INTL_FORMAT );
     724             : 
     725           0 :     ReFormat();
     726           0 : }
     727             : 
     728           0 : void FormattedField::Commit()
     729             : {
     730             :     // remember the old text
     731           0 :     OUString sOld( GetText() );
     732             : 
     733             :     // do the reformat
     734           0 :     ReFormat();
     735             : 
     736             :     // did the text change?
     737           0 :     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           0 :     }
     745           0 : }
     746             : 
     747           0 : void FormattedField::ReFormat()
     748             : {
     749           0 :     if (!IsEmptyFieldEnabled() || !GetText().isEmpty())
     750             :     {
     751           0 :         if (TreatingAsNumber())
     752             :         {
     753           0 :             double dValue = GetValue();
     754           0 :             if ( m_bEnableNaN && ::rtl::math::isNan( dValue ) )
     755           0 :                 return;
     756           0 :             ImplSetValue( dValue, true );
     757             :         }
     758             :         else
     759           0 :             SetTextFormatted(GetTextValue());
     760             :     }
     761             : }
     762             : 
     763           0 : bool FormattedField::Notify(NotifyEvent& rNEvt)
     764             : {
     765             : 
     766           0 :     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           0 :     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() == COMMAND_WHEEL_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           0 :     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           0 :     return SpinField::Notify( rNEvt );
     831             : }
     832             : 
     833           0 : void FormattedField::SetMinValue(double dMin)
     834             : {
     835             :     DBG_ASSERT(m_bTreatAsNumber, "FormattedField::SetMinValue : only to be used in numeric mode !");
     836             : 
     837           0 :     m_dMinValue = dMin;
     838           0 :     m_bHasMin = true;
     839             :     // for checking the current value at the new border -> ImplSetValue
     840           0 :     ReFormat();
     841           0 : }
     842             : 
     843           0 : void FormattedField::SetMaxValue(double dMax)
     844             : {
     845             :     DBG_ASSERT(m_bTreatAsNumber, "FormattedField::SetMaxValue : only to be used in numeric mode !");
     846             : 
     847           0 :     m_dMaxValue = dMax;
     848           0 :     m_bHasMax = true;
     849             :     // for checking the current value at the new border -> ImplSetValue
     850           0 :     ReFormat();
     851           0 : }
     852             : 
     853           0 : void FormattedField::SetTextValue(const OUString& rText)
     854             : {
     855           0 :     SetText(rText);
     856           0 :     ReFormat();
     857           0 : }
     858             : 
     859           0 : void FormattedField::EnableEmptyField(bool bEnable)
     860             : {
     861           0 :     if (bEnable == m_bEnableEmptyField)
     862           0 :         return;
     863             : 
     864           0 :     m_bEnableEmptyField = bEnable;
     865           0 :     if (!m_bEnableEmptyField && GetText().isEmpty())
     866           0 :         ImplSetValue(m_dCurrentValue, true);
     867             : }
     868             : 
     869           0 : void FormattedField::ImplSetValue(double dVal, bool bForce)
     870             : {
     871             : 
     872           0 :     if (m_bHasMin && (dVal<m_dMinValue))
     873           0 :         dVal = m_dMinValue;
     874           0 :     if (m_bHasMax && (dVal>m_dMaxValue))
     875           0 :         dVal = m_dMaxValue;
     876           0 :     if (!bForce && (dVal == GetValue()))
     877           0 :         return;
     878             : 
     879             :     DBG_ASSERT(ImplGetFormatter() != NULL, "FormattedField::ImplSetValue : can't set a value without a formatter !");
     880             : 
     881           0 :     m_bValueDirty = false;
     882           0 :     m_dCurrentValue = dVal;
     883             : 
     884           0 :     OUString sNewText;
     885           0 :     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           0 :         if( IsUsingInputStringForFormatting())
     896             :         {
     897           0 :             ImplGetFormatter()->GetInputLineString(dVal, m_nFormatKey, sNewText);
     898             :         }
     899             :         else
     900             :         {
     901           0 :             ImplGetFormatter()->GetOutputString(dVal, m_nFormatKey, sNewText, &m_pLastOutputColor);
     902             :         }
     903             :     }
     904             : 
     905           0 :     ImplSetTextImpl(sNewText, NULL);
     906           0 :     m_bValueDirty = false;
     907           0 :     DBG_ASSERT(CheckText(sNewText), "FormattedField::ImplSetValue : formatted string doesn't match the criteria !");
     908             : }
     909             : 
     910           0 : bool FormattedField::ImplGetValue(double& dNewVal)
     911             : {
     912             : 
     913           0 :     dNewVal = m_dCurrentValue;
     914           0 :     if (!m_bValueDirty)
     915           0 :         return true;
     916             : 
     917           0 :     dNewVal = m_dDefaultValue;
     918           0 :     OUString sText(GetText());
     919           0 :     if (sText.isEmpty())
     920           0 :         return true;
     921             : 
     922             :     DBG_ASSERT(ImplGetFormatter() != NULL, "FormattedField::ImplGetValue : can't give you a current value without a formatter !");
     923             : 
     924           0 :     sal_uInt32 nFormatKey = m_nFormatKey; // IsNumberFormat changes the FormatKey!
     925             : 
     926           0 :     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           0 :     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           0 :     if (!ImplGetFormatter()->IsNumberFormat(sText, nFormatKey, dNewVal))
     949           0 :         return false;
     950             : 
     951           0 :     if (m_bHasMin && (dNewVal<m_dMinValue))
     952           0 :         dNewVal = m_dMinValue;
     953           0 :     if (m_bHasMax && (dNewVal>m_dMaxValue))
     954           0 :         dNewVal = m_dMaxValue;
     955           0 :     return true;
     956             : }
     957             : 
     958           0 : void FormattedField::SetValue(double dVal)
     959             : {
     960           0 :     ImplSetValue(dVal, m_bValueDirty);
     961           0 : }
     962             : 
     963           0 : double FormattedField::GetValue()
     964             : {
     965             : 
     966           0 :     if ( !ImplGetValue( m_dCurrentValue ) )
     967             :     {
     968           0 :         if ( m_bEnableNaN )
     969           0 :             ::rtl::math::setNan( &m_dCurrentValue );
     970             :         else
     971           0 :             m_dCurrentValue = m_dDefaultValue;
     972             :     }
     973             : 
     974           0 :     m_bValueDirty = false;
     975           0 :     return m_dCurrentValue;
     976             : }
     977             : 
     978           0 : void FormattedField::Up()
     979             : {
     980             :     // setValue handles under- and overflows (min/max) automatically
     981           0 :     SetValue(GetValue() + m_dSpinSize);
     982           0 :     SetModifyFlag();
     983           0 :     Modify();
     984             : 
     985           0 :     SpinField::Up();
     986           0 : }
     987             : 
     988           0 : void FormattedField::Down()
     989             : {
     990           0 :     SetValue(GetValue() - m_dSpinSize);
     991           0 :     SetModifyFlag();
     992           0 :     Modify();
     993             : 
     994           0 :     SpinField::Down();
     995           0 : }
     996             : 
     997           0 : void FormattedField::First()
     998             : {
     999           0 :     if (m_bHasMin)
    1000             :     {
    1001           0 :         SetValue(m_dMinValue);
    1002           0 :         SetModifyFlag();
    1003           0 :         Modify();
    1004             :     }
    1005             : 
    1006           0 :     SpinField::First();
    1007           0 : }
    1008             : 
    1009           0 : void FormattedField::Last()
    1010             : {
    1011           0 :     if (m_bHasMax)
    1012             :     {
    1013           0 :         SetValue(m_dMaxValue);
    1014           0 :         SetModifyFlag();
    1015           0 :         Modify();
    1016             :     }
    1017             : 
    1018           0 :     SpinField::Last();
    1019           0 : }
    1020             : 
    1021           0 : void FormattedField::UseInputStringForFormatting( bool bUseInputStr /* = true */ )
    1022             : {
    1023           0 :     m_bUseInputStringForFormatting = bUseInputStr;
    1024           0 : }
    1025             : 
    1026           0 : bool FormattedField::IsUsingInputStringForFormatting() const
    1027             : {
    1028           0 :     return m_bUseInputStringForFormatting;
    1029             : }
    1030             : 
    1031           0 : DoubleNumericField::~DoubleNumericField()
    1032             : {
    1033           0 :     delete m_pNumberValidator;
    1034           0 : }
    1035             : 
    1036           0 : void DoubleNumericField::FormatChanged(FORMAT_CHANGE_TYPE nWhat)
    1037             : {
    1038           0 :     ResetConformanceTester();
    1039           0 :     FormattedField::FormatChanged(nWhat);
    1040           0 : }
    1041             : 
    1042           0 : bool DoubleNumericField::CheckText(const OUString& sText) const
    1043             : {
    1044             :     // We'd like to implement this using the NumberFormatter::IsNumberFormat, but unfortunately, this doesn't
    1045             :     // recognize fragments of numbers (like, for instance "1e", which happens during entering e.g. "1e10")
    1046             :     // Thus, the roundabout way via a regular expression
    1047           0 :     return m_pNumberValidator->isValidNumericFragment( sText );
    1048             : }
    1049             : 
    1050           0 : void DoubleNumericField::ResetConformanceTester()
    1051             : {
    1052             :     // the thousands and the decimal separator are language dependent
    1053           0 :     const SvNumberformat* pFormatEntry = ImplGetFormatter()->GetEntry(m_nFormatKey);
    1054             : 
    1055           0 :     sal_Unicode cSeparatorThousand = ',';
    1056           0 :     sal_Unicode cSeparatorDecimal = '.';
    1057           0 :     if (pFormatEntry)
    1058             :     {
    1059           0 :         LocaleDataWrapper aLocaleInfo( LanguageTag( pFormatEntry->GetLanguage()) );
    1060             : 
    1061           0 :         OUString sSeparator = aLocaleInfo.getNumThousandSep();
    1062           0 :         if (!sSeparator.isEmpty())
    1063           0 :             cSeparatorThousand = sSeparator[0];
    1064             : 
    1065           0 :         sSeparator = aLocaleInfo.getNumDecimalSep();
    1066           0 :         if (!sSeparator.isEmpty())
    1067           0 :             cSeparatorDecimal = sSeparator[0];
    1068             :     }
    1069             : 
    1070           0 :     delete m_pNumberValidator;
    1071           0 :     m_pNumberValidator = new validation::NumberValidator( cSeparatorThousand, cSeparatorDecimal );
    1072           0 : }
    1073             : 
    1074           0 : DoubleCurrencyField::DoubleCurrencyField(Window* pParent, WinBits nStyle)
    1075             :     :FormattedField(pParent, nStyle)
    1076           0 :     ,m_bChangingFormat(false)
    1077             : {
    1078           0 :     m_bPrependCurrSym = false;
    1079             : 
    1080             :     // initialize with a system currency format
    1081           0 :     m_sCurrencySymbol = SvtSysLocale().GetLocaleData().getCurrSymbol();
    1082           0 :     UpdateCurrencyFormat();
    1083           0 : }
    1084             : 
    1085           0 : void DoubleCurrencyField::FormatChanged(FORMAT_CHANGE_TYPE nWhat)
    1086             : {
    1087           0 :     if (m_bChangingFormat)
    1088             :     {
    1089           0 :         FormattedField::FormatChanged(nWhat);
    1090           0 :         return;
    1091             :     }
    1092             : 
    1093           0 :     switch (nWhat)
    1094             :     {
    1095             :         case FCT_FORMATTER:
    1096             :         case FCT_PRECISION:
    1097             :         case FCT_THOUSANDSSEP:
    1098             :             // the aspects which changed don't take our currency settings into account (in fact, they most probably
    1099             :             // destroyed them)
    1100           0 :             UpdateCurrencyFormat();
    1101           0 :             break;
    1102             :         case FCT_KEYONLY:
    1103             :             OSL_FAIL("DoubleCurrencyField::FormatChanged : somebody modified my key !");
    1104             :             // We always build our own format from the settings we get via special methods (setCurrencySymbol etc.).
    1105             :             // Nobody but ourself should modifiy the format key directly !
    1106           0 :             break;
    1107             :     }
    1108             : 
    1109           0 :     FormattedField::FormatChanged(nWhat);
    1110             : }
    1111             : 
    1112           0 : void DoubleCurrencyField::setCurrencySymbol(const OUString& rSymbol)
    1113             : {
    1114           0 :     if (m_sCurrencySymbol == rSymbol)
    1115           0 :         return;
    1116             : 
    1117           0 :     m_sCurrencySymbol = rSymbol;
    1118           0 :     UpdateCurrencyFormat();
    1119           0 :     FormatChanged(FCT_CURRENCY_SYMBOL);
    1120             : }
    1121             : 
    1122           0 : void DoubleCurrencyField::setPrependCurrSym(bool _bPrepend)
    1123             : {
    1124           0 :     if (m_bPrependCurrSym == _bPrepend)
    1125           0 :          return;
    1126             : 
    1127           0 :     m_bPrependCurrSym = _bPrepend;
    1128           0 :     UpdateCurrencyFormat();
    1129           0 :     FormatChanged(FCT_CURRSYM_POSITION);
    1130             : }
    1131             : 
    1132           0 : void DoubleCurrencyField::UpdateCurrencyFormat()
    1133             : {
    1134             :     // the old settings
    1135             :     LanguageType eLanguage;
    1136           0 :     GetFormat(eLanguage);
    1137           0 :     bool bThSep = GetThousandsSep();
    1138           0 :     sal_uInt16 nDigits = GetDecimalDigits();
    1139             : 
    1140             :     // build a new format string with the base class' and my own settings
    1141             : 
    1142             :     /* Strangely with gcc 4.6.3 this needs a temporary LanguageTag, otherwise
    1143             :      * there's
    1144             :      * error: request for member 'getNumThousandSep' in 'aLocaleInfo', which is
    1145             :      * of non-class type 'LocaleDataWrapper(LanguageTag)' */
    1146           0 :     LanguageTag aLanguageTag( eLanguage);
    1147           0 :     LocaleDataWrapper aLocaleInfo( aLanguageTag );
    1148             : 
    1149           0 :     OUStringBuffer sNewFormat;
    1150           0 :     if (bThSep)
    1151             :     {
    1152           0 :         sNewFormat.append('#');
    1153           0 :         sNewFormat.append(aLocaleInfo.getNumThousandSep());
    1154           0 :         sNewFormat.append("##0");
    1155             :     }
    1156             :     else
    1157           0 :         sNewFormat.append('0');
    1158             : 
    1159           0 :     if (nDigits)
    1160             :     {
    1161           0 :         sNewFormat.append(aLocaleInfo.getNumDecimalSep());
    1162             : 
    1163           0 :         OUStringBuffer sTemp;
    1164           0 :         comphelper::string::padToLength(sTemp, nDigits, '0');
    1165           0 :         sNewFormat.append(sTemp);
    1166             :     }
    1167             : 
    1168           0 :     if (getPrependCurrSym())
    1169             :     {
    1170           0 :         OUString sSymbol = getCurrencySymbol();
    1171           0 :         sSymbol = comphelper::string::stripStart(sSymbol, ' ');
    1172           0 :         sSymbol = comphelper::string::stripEnd(sSymbol, ' ');
    1173             : 
    1174           0 :         OUStringBuffer sTemp("[$");
    1175           0 :         sTemp.append(sSymbol);
    1176           0 :         sTemp.append("] ");
    1177           0 :         sTemp.append(sNewFormat);
    1178             : 
    1179             :         // for negative values : $ -0.00, not -$ 0.00 ...
    1180             :         // (the real solution would be a possibility to choose a "positive currency format" and a "negative currency format" ...
    1181             :         // But not now ... (and hey, you could take a formatted field for this ....))
    1182             :         // FS - 31.03.00 74642
    1183           0 :         sTemp.append(";[$");
    1184           0 :         sTemp.append(sSymbol);
    1185           0 :         sTemp.append("] -");
    1186           0 :         sTemp.append(sNewFormat);
    1187             : 
    1188           0 :         sNewFormat = sTemp;
    1189             :     }
    1190             :     else
    1191             :     {
    1192           0 :         OUString sTemp = getCurrencySymbol();
    1193           0 :         sTemp = comphelper::string::stripStart(sTemp, ' ');
    1194           0 :         sTemp = comphelper::string::stripEnd(sTemp, ' ');
    1195             : 
    1196           0 :         sNewFormat.append(" [$");
    1197           0 :         sNewFormat.append(sTemp);
    1198           0 :         sNewFormat.append(']');
    1199             :     }
    1200             : 
    1201             :     // set this new basic format
    1202           0 :     m_bChangingFormat = true;
    1203           0 :     SetFormat(sNewFormat.makeStringAndClear(), eLanguage);
    1204           0 :     m_bChangingFormat = false;
    1205           0 : }
    1206             : 
    1207             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10