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

Generated by: LCOV version 1.10