LCOV - code coverage report
Current view: top level - vcl/source/control - field.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 529 1178 44.9 %
Date: 2015-06-13 12:38:46 Functions: 81 167 48.5 %
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 "sal/config.h"
      21             : 
      22             : #include <comphelper/processfactory.hxx>
      23             : #include <comphelper/string.hxx>
      24             : 
      25             : #include "tools/debug.hxx"
      26             : 
      27             : #include "tools/rc.h"
      28             : 
      29             : #include "vcl/dialog.hxx"
      30             : #include "vcl/field.hxx"
      31             : #include "vcl/event.hxx"
      32             : #include "vcl/svapp.hxx"
      33             : #include "vcl/settings.hxx"
      34             : 
      35             : #include "svids.hrc"
      36             : #include "svdata.hxx"
      37             : 
      38             : #include "i18nutil/unicode.hxx"
      39             : 
      40             : #include "rtl/math.hxx"
      41             : 
      42             : #include <unotools/localedatawrapper.hxx>
      43             : 
      44             : using namespace ::com::sun::star;
      45             : using namespace ::comphelper;
      46             : 
      47             : namespace
      48             : {
      49             : 
      50             : #define FORMAT_NUMERIC       1
      51             : #define FORMAT_METRIC        2
      52             : #define FORMAT_CURRENCY      3
      53             : 
      54       43807 : static sal_Int64 ImplPower10( sal_uInt16 n )
      55             : {
      56             :     sal_uInt16  i;
      57       43807 :     sal_Int64   nValue = 1;
      58             : 
      59      101713 :     for ( i=0; i < n; i++ )
      60       57906 :         nValue *= 10;
      61             : 
      62       43807 :     return nValue;
      63             : }
      64             : 
      65           0 : static bool ImplNumericProcessKeyInput( Edit*, const KeyEvent& rKEvt,
      66             :                                         bool bStrictFormat, bool bThousandSep,
      67             :                                         const LocaleDataWrapper& rLocaleDataWrappper )
      68             : {
      69           0 :     if ( !bStrictFormat )
      70           0 :         return false;
      71             :     else
      72             :     {
      73           0 :         sal_Unicode cChar = rKEvt.GetCharCode();
      74           0 :         sal_uInt16      nGroup = rKEvt.GetKeyCode().GetGroup();
      75             : 
      76           0 :         if ( (nGroup == KEYGROUP_FKEYS) || (nGroup == KEYGROUP_CURSOR) ||
      77           0 :              (nGroup == KEYGROUP_MISC) ||
      78           0 :              ((cChar >= '0') && (cChar <= '9')) ||
      79           0 :              string::equals(rLocaleDataWrappper.getNumDecimalSep(), cChar) ||
      80           0 :              (bThousandSep && string::equals(rLocaleDataWrappper.getNumThousandSep(), cChar)) ||
      81             :              (cChar == '-') )
      82           0 :             return false;
      83             :         else
      84           0 :             return true;
      85             :     }
      86             : }
      87             : 
      88       34937 : static bool ImplNumericGetValue( const OUString& rStr, sal_Int64& rValue,
      89             :                                  sal_uInt16 nDecDigits, const LocaleDataWrapper& rLocaleDataWrappper,
      90             :                                  bool bCurrency = false )
      91             : {
      92       34937 :     OUString            aStr = rStr;
      93       69874 :     OUStringBuffer      aStr1, aStr2, aStrFrac, aStrNum, aStrDenom;
      94       34937 :     bool                bNegative = false;
      95       34937 :     bool                bFrac = false;
      96             :     sal_Int32           nDecPos, nFracDivPos, nFracNumPos;
      97             :     sal_Int64           nValue;
      98             : 
      99             :     // react on empty string
     100       34937 :     if ( rStr.isEmpty() )
     101        4320 :         return false;
     102             : 
     103             :     // remove leading and trailing spaces
     104       30617 :     aStr = aStr.trim();
     105             : 
     106             : 
     107             : 
     108             :     // find position of decimal point
     109       30617 :     nDecPos = aStr.indexOf( rLocaleDataWrappper.getNumDecimalSep() );
     110             :     // find position of fraction
     111       30617 :     nFracDivPos = aStr.indexOf( '/' );
     112             : 
     113             :     // parse fractional strings
     114       30617 :     if (nFracDivPos > 0)
     115             :     {
     116           0 :         bFrac = true;
     117           0 :         nFracNumPos = aStr.lastIndexOf(' ', nFracDivPos);
     118             : 
     119             :         // If in "a b/c" format.
     120           0 :         if(nFracNumPos != -1 )
     121             :         {
     122           0 :             aStr1.append(aStr.getStr(), nFracNumPos);
     123           0 :             aStrNum.append(aStr.getStr()+nFracNumPos+1, nFracDivPos-nFracNumPos-1);
     124           0 :             aStrDenom.append(aStr.getStr()+nFracDivPos+1);
     125             :         }
     126             :         // "a/b" format, or not a fraction at all
     127             :         else
     128             :         {
     129           0 :             aStrNum.append(aStr.getStr(), nFracDivPos);
     130           0 :             aStrDenom.append(aStr.getStr()+nFracDivPos+1);
     131             :         }
     132             : 
     133             :     }
     134             :     // parse decimal strings
     135       30617 :     else if ( nDecPos >= 0)
     136             :     {
     137       13964 :         aStr1.append(aStr.getStr(), nDecPos);
     138       13964 :         aStr2.append(aStr.getStr()+nDecPos+1);
     139             :     }
     140             :     else
     141       16653 :         aStr1 = aStr;
     142             : 
     143             :     // negative?
     144       30617 :     if ( bCurrency )
     145             :     {
     146           0 :         if ( aStr.startsWith("(") && aStr.endsWith(")") )
     147           0 :             bNegative = true;
     148           0 :         if ( !bNegative )
     149             :         {
     150           0 :             for (sal_Int32 i=0; i < aStr.getLength(); i++ )
     151             :             {
     152           0 :                 if ( (aStr[i] >= '0') && (aStr[i] <= '9') )
     153           0 :                     break;
     154           0 :                 else if ( aStr[i] == '-' )
     155             :                 {
     156           0 :                     bNegative = true;
     157           0 :                     break;
     158             :                 }
     159             :             }
     160             :         }
     161           0 :         if ( !bNegative && bCurrency && !aStr.isEmpty() )
     162             :         {
     163           0 :             sal_uInt16 nFormat = rLocaleDataWrappper.getCurrNegativeFormat();
     164           0 :             if ( (nFormat == 3) || (nFormat == 6)  || // $1- || 1-$
     165           0 :                  (nFormat == 7) || (nFormat == 10) )  // 1$- || 1 $-
     166             :             {
     167           0 :                 for (sal_Int32 i = aStr.getLength()-1; i > 0; --i )
     168             :                 {
     169           0 :                     if ( (aStr[i] >= '0') && (aStr[i] <= '9') )
     170           0 :                         break;
     171           0 :                     else if ( aStr[i] == '-' )
     172             :                     {
     173           0 :                         bNegative = true;
     174           0 :                         break;
     175             :                     }
     176             :                 }
     177             :             }
     178             :         }
     179             :     }
     180             :     else
     181             :     {
     182       30617 :         if ( !aStr1.isEmpty() && aStr1[0] == '-')
     183           0 :             bNegative = true;
     184       30617 :         if ( !aStrNum.isEmpty() && aStrNum[0] == '-') // For non-mixed fractions
     185           0 :             bNegative = true;
     186             :     }
     187             : 
     188             :     // remove all unwanted charaters
     189             :     // For whole number
     190       95335 :     for (sal_Int32 i=0; i < aStr1.getLength(); )
     191             :     {
     192       34101 :         if ( (aStr1[i] >= '0') && (aStr1[i] <= '9') )
     193       32988 :             i++;
     194             :         else
     195        1113 :             aStr1.remove( i, 1 );
     196             :     }
     197             :     // For decimal
     198       30617 :     if (!bFrac) {
     199      110322 :         for (sal_Int32 i=0; i < aStr2.getLength(); )
     200             :         {
     201       49088 :             if ((aStr2[i] >= '0') && (aStr2[i] <= '9'))
     202       27926 :                 ++i;
     203             :             else
     204       21162 :                 aStr2.remove(i, 1);
     205             :         }
     206             :     }
     207             :     else {
     208             :         // for numerator
     209           0 :         for (sal_Int32 i=0; i < aStrNum.getLength(); )
     210             :         {
     211           0 :             if ((aStrNum[i] >= '0') && (aStrNum[i] <= '9'))
     212           0 :                 ++i;
     213             :             else
     214           0 :                 aStrNum.remove(i, 1);
     215             :         }
     216             :         // for denominator
     217           0 :         for (sal_Int32 i=0; i < aStrDenom.getLength(); )
     218             :         {
     219           0 :             if ((aStrDenom[i] >= '0') && (aStrDenom[i] <= '9'))
     220           0 :                 ++i;
     221             :             else
     222           0 :                 aStrDenom.remove(i, 1);
     223             :         }
     224             :     }
     225             : 
     226             : 
     227       30617 :     if ( !bFrac && aStr1.isEmpty() && aStr2.isEmpty() )
     228           0 :         return false;
     229       30617 :     else if ( bFrac && aStr1.isEmpty() && (aStrNum.isEmpty() || aStrDenom.isEmpty()) )
     230           0 :         return false;
     231             : 
     232       30617 :     if ( aStr1.isEmpty() )
     233           0 :         aStr1 = "0";
     234       30617 :     if ( bNegative )
     235           0 :         aStr1.insert(0, "-");
     236             : 
     237             :     // Convert fractional strings
     238       30617 :     if (bFrac) {
     239             :         // Convert to fraction
     240           0 :         sal_Int64 nWholeNum = aStr1.makeStringAndClear().toInt64();
     241           0 :         sal_Int64 nNum = aStrNum.makeStringAndClear().toInt64();
     242           0 :         sal_Int64 nDenom = aStrDenom.makeStringAndClear().toInt64();
     243           0 :         if (nDenom == 0) return false; // Division by zero
     244           0 :         double nFrac2Dec = nWholeNum + (double)nNum/nDenom; // Convert to double for floating point precision
     245           0 :         aStrFrac.append(nFrac2Dec);
     246             :         // Reconvert division result to string and parse
     247           0 :         nDecPos = aStrFrac.indexOf( rLocaleDataWrappper.getNumDecimalSep() );
     248           0 :         if ( nDecPos >= 0)
     249             :         {
     250           0 :             aStr1.append(aStrFrac.getStr(), nDecPos);
     251           0 :             aStr2.append(aStrFrac.getStr()+nDecPos+1);
     252             :         }
     253             :         else
     254           0 :             aStr1 = aStrFrac;
     255             :     }
     256             : 
     257             :     // prune and round fraction
     258       30617 :     bool bRound = false;
     259       30617 :     if (aStr2.getLength() > nDecDigits)
     260             :     {
     261           0 :         if (aStr2[nDecDigits] >= '5')
     262           0 :             bRound = true;
     263           0 :         string::truncateToLength(aStr2, nDecDigits);
     264             :     }
     265       30617 :     if (aStr2.getLength() < nDecDigits)
     266        9693 :         string::padToLength(aStr2, nDecDigits, '0');
     267             : 
     268       30617 :     aStr  = aStr1.makeStringAndClear() + aStr2.makeStringAndClear();
     269             : 
     270             :     // check range
     271       30617 :     nValue = aStr.toInt64();
     272       30617 :     if( nValue == 0 )
     273             :     {
     274             :         // check if string is equivalent to zero
     275       26181 :         sal_Int16 nIndex = bNegative ? 1 : 0;
     276      115167 :         while (nIndex < aStr.getLength() && aStr[nIndex] == '0')
     277       62805 :             ++nIndex;
     278       26181 :         if( nIndex < aStr.getLength() )
     279             :         {
     280           0 :             rValue = bNegative ? SAL_MIN_INT64 : SAL_MAX_INT64;
     281           0 :             return true;
     282             :         }
     283             :     }
     284       30617 :     if (bRound)
     285             :     {
     286           0 :         if ( !bNegative )
     287           0 :             nValue++;
     288             :         else
     289           0 :             nValue--;
     290             :     }
     291             : 
     292       30617 :     rValue = nValue;
     293             : 
     294       65554 :     return true;
     295             : }
     296             : 
     297           0 : static void ImplUpdateSeparatorString( OUString& io_rText,
     298             :                                        const OUString& rOldDecSep, const OUString& rNewDecSep,
     299             :                                        const OUString& rOldThSep, const OUString& rNewThSep )
     300             : {
     301           0 :     OUStringBuffer aBuf( io_rText.getLength() );
     302           0 :     sal_Int32 nIndexDec = 0, nIndexTh = 0, nIndex = 0;
     303             : 
     304           0 :     const sal_Unicode* pBuffer = io_rText.getStr();
     305           0 :     while( nIndex != -1 )
     306             :     {
     307           0 :         nIndexDec = io_rText.indexOf( rOldDecSep, nIndex );
     308           0 :         nIndexTh = io_rText.indexOf( rOldThSep, nIndex );
     309           0 :         if(   (nIndexTh != -1 && nIndexDec != -1 && nIndexTh < nIndexDec )
     310           0 :            || (nIndexTh != -1 && nIndexDec == -1)
     311             :            )
     312             :         {
     313           0 :             aBuf.append( pBuffer + nIndex, nIndexTh - nIndex );
     314           0 :             aBuf.append( rNewThSep );
     315           0 :             nIndex = nIndexTh + rOldThSep.getLength();
     316             :         }
     317           0 :         else if( nIndexDec != -1 )
     318             :         {
     319           0 :             aBuf.append( pBuffer + nIndex, nIndexDec - nIndex );
     320           0 :             aBuf.append( rNewDecSep );
     321           0 :             nIndex = nIndexDec + rOldDecSep.getLength();
     322             :         }
     323             :         else
     324             :         {
     325           0 :             aBuf.append( pBuffer + nIndex );
     326           0 :             nIndex = -1;
     327             :         }
     328             :     }
     329             : 
     330           0 :     io_rText = aBuf.makeStringAndClear();
     331           0 : }
     332             : 
     333           0 : static void ImplUpdateSeparators( const OUString& rOldDecSep, const OUString& rNewDecSep,
     334             :                                   const OUString& rOldThSep, const OUString& rNewThSep,
     335             :                                   Edit* pEdit )
     336             : {
     337           0 :     bool bChangeDec = (rOldDecSep != rNewDecSep);
     338           0 :     bool bChangeTh = (rOldThSep != rNewThSep );
     339             : 
     340           0 :     if( bChangeDec || bChangeTh )
     341             :     {
     342           0 :         bool bUpdateMode = pEdit->IsUpdateMode();
     343           0 :         pEdit->SetUpdateMode( false );
     344           0 :         OUString aText = pEdit->GetText();
     345           0 :         ImplUpdateSeparatorString( aText, rOldDecSep, rNewDecSep, rOldThSep, rNewThSep );
     346           0 :         pEdit->SetText( aText );
     347             : 
     348           0 :         ComboBox* pCombo = dynamic_cast<ComboBox*>(pEdit);
     349           0 :         if( pCombo )
     350             :         {
     351             :             // update box entries
     352           0 :             sal_Int32 nEntryCount = pCombo->GetEntryCount();
     353           0 :             for ( sal_Int32 i=0; i < nEntryCount; i++ )
     354             :             {
     355           0 :                 aText = pCombo->GetEntry( i );
     356           0 :                 void* pEntryData = pCombo->GetEntryData( i );
     357           0 :                 ImplUpdateSeparatorString( aText, rOldDecSep, rNewDecSep, rOldThSep, rNewThSep );
     358           0 :                 pCombo->RemoveEntryAt(i);
     359           0 :                 pCombo->InsertEntry( aText, i );
     360           0 :                 pCombo->SetEntryData( i, pEntryData );
     361             :             }
     362             :         }
     363           0 :         if( bUpdateMode )
     364           0 :             pEdit->SetUpdateMode( bUpdateMode );
     365             :     }
     366           0 : }
     367             : 
     368             : } // namespace
     369             : 
     370        3394 : FormatterBase::FormatterBase( Edit* pField )
     371             : {
     372        3394 :     mpField                     = pField;
     373        3394 :     mpLocaleDataWrapper         = NULL;
     374        3394 :     mbReformat                  = false;
     375        3394 :     mbStrictFormat              = false;
     376        3394 :     mbEmptyFieldValue           = false;
     377        3394 :     mbEmptyFieldValueEnabled    = false;
     378        3394 :     mbDefaultLocale             = true;
     379        3394 : }
     380             : 
     381           0 : FormatterBase::~FormatterBase()
     382             : {
     383           0 :     delete mpLocaleDataWrapper;
     384           0 : }
     385             : 
     386      114350 : LocaleDataWrapper& FormatterBase::ImplGetLocaleDataWrapper() const
     387             : {
     388      114350 :     if ( !mpLocaleDataWrapper )
     389             :     {
     390        3386 :         const_cast<FormatterBase*>(this)->mpLocaleDataWrapper = new LocaleDataWrapper( GetLanguageTag() );
     391             :     }
     392      114350 :     return *mpLocaleDataWrapper;
     393             : }
     394             : 
     395           0 : const LocaleDataWrapper& FormatterBase::GetLocaleDataWrapper() const
     396             : {
     397           0 :     return ImplGetLocaleDataWrapper();
     398             : }
     399             : 
     400           0 : void FormatterBase::Reformat()
     401             : {
     402           0 : }
     403             : 
     404       26437 : void FormatterBase::ReformatAll()
     405             : {
     406       26437 :     Reformat();
     407       26437 : };
     408             : 
     409         129 : void FormatterBase::SetStrictFormat( bool bStrict )
     410             : {
     411         129 :     if ( bStrict != mbStrictFormat )
     412             :     {
     413          80 :         mbStrictFormat = bStrict;
     414          80 :         if ( mbStrictFormat )
     415          69 :             ReformatAll();
     416             :     }
     417         129 : }
     418             : 
     419           0 : void FormatterBase::SetLocale( const lang::Locale& rLocale )
     420             : {
     421           0 :     ImplGetLocaleDataWrapper().setLanguageTag( LanguageTag( rLocale) );
     422           0 :     mbDefaultLocale = false;
     423           0 :     ReformatAll();
     424           0 : }
     425             : 
     426          34 : const lang::Locale& FormatterBase::GetLocale() const
     427             : {
     428          34 :     if ( !mpLocaleDataWrapper || mbDefaultLocale )
     429             :     {
     430          34 :         if ( mpField )
     431          34 :             return mpField->GetSettings().GetLanguageTag().getLocale();
     432             :         else
     433           0 :             return Application::GetSettings().GetLanguageTag().getLocale();
     434             :     }
     435             : 
     436           0 :     return mpLocaleDataWrapper->getLanguageTag().getLocale();
     437             : }
     438             : 
     439        3386 : const LanguageTag& FormatterBase::GetLanguageTag() const
     440             : {
     441        3386 :     if ( !mpLocaleDataWrapper || mbDefaultLocale )
     442             :     {
     443        3386 :         if ( mpField )
     444        3386 :             return mpField->GetSettings().GetLanguageTag();
     445             :         else
     446           0 :             return Application::GetSettings().GetLanguageTag();
     447             :     }
     448             : 
     449           0 :     return mpLocaleDataWrapper->getLanguageTag();
     450             : }
     451             : 
     452         666 : const AllSettings& FormatterBase::GetFieldSettings() const
     453             : {
     454         666 :     if ( mpField )
     455         666 :         return mpField->GetSettings();
     456             :     else
     457           0 :         return Application::GetSettings();
     458             : }
     459             : 
     460       37312 : void FormatterBase::ImplSetText( const OUString& rText, Selection* pNewSelection )
     461             : {
     462       37312 :     if ( mpField )
     463             :     {
     464       37312 :         if ( pNewSelection )
     465          20 :             mpField->SetText( rText, *pNewSelection );
     466             :         else
     467             :         {
     468       37292 :             Selection aSel = mpField->GetSelection();
     469       37292 :             aSel.Min() = aSel.Max();
     470       37292 :             mpField->SetText( rText, aSel );
     471             :         }
     472             : 
     473       37312 :         MarkToBeReformatted( false );
     474             :     }
     475       37312 : }
     476             : 
     477          42 : void FormatterBase::SetEmptyFieldValue()
     478             : {
     479          42 :     if ( mpField )
     480          42 :         mpField->SetText( OUString() );
     481          42 :     mbEmptyFieldValue = true;
     482          42 : }
     483             : 
     484       18175 : bool FormatterBase::IsEmptyFieldValue() const
     485             : {
     486       18175 :     return (!mpField || mpField->GetText().isEmpty());
     487             : }
     488             : 
     489         463 : bool NumericFormatter::ImplNumericReformat( const OUString& rStr, sal_Int64& rValue,
     490             :                                                 OUString& rOutStr )
     491             : {
     492         463 :     if ( !ImplNumericGetValue( rStr, rValue, GetDecimalDigits(), ImplGetLocaleDataWrapper() ) )
     493         348 :         return true;
     494             :     else
     495             :     {
     496         115 :         sal_Int64 nTempVal = ClipAgainstMinMax(rValue);
     497             : 
     498         115 :         if ( GetErrorHdl().IsSet() && (rValue != nTempVal) )
     499             :         {
     500           0 :             mnCorrectedValue = nTempVal;
     501           0 :             if ( !GetErrorHdl().Call( this ) )
     502             :             {
     503           0 :                 mnCorrectedValue = 0;
     504           0 :                 return false;
     505             :             }
     506             :             else
     507           0 :                 mnCorrectedValue = 0;
     508             :         }
     509             : 
     510         115 :         rOutStr = CreateFieldText( nTempVal );
     511         115 :         return true;
     512             :     }
     513             : }
     514             : 
     515        3334 : void NumericFormatter::ImplInit()
     516             : {
     517        3334 :     mnFieldValue        = 0;
     518        3334 :     mnLastValue         = 0;
     519        3334 :     mnMin               = 0;
     520        3334 :     mnMax               = SAL_MAX_INT64;
     521        3334 :     mnCorrectedValue    = 0;
     522        3334 :     mnDecimalDigits     = 2;
     523        3334 :     mnType              = FORMAT_NUMERIC;
     524        3334 :     mbThousandSep       = true;
     525        3334 :     mbShowTrailingZeros = true;
     526        3334 :     mbWrapOnLimits      = false;
     527             : 
     528             :     // for fields
     529        3334 :     mnSpinSize          = 1;
     530        3334 :     mnFirst             = mnMin;
     531        3334 :     mnLast              = mnMax;
     532             : 
     533        3334 :     SetDecimalDigits( 0 );
     534        3334 : }
     535             : 
     536        3334 : NumericFormatter::NumericFormatter()
     537             : {
     538        3334 :     ImplInit();
     539        3334 : }
     540             : 
     541           8 : void NumericFormatter::ImplLoadRes( const ResId& rResId )
     542             : {
     543           8 :     ResMgr*     pMgr = rResId.GetResMgr();
     544             : 
     545           8 :     if( pMgr )
     546             :     {
     547           8 :         sal_uLong nMask = pMgr->ReadLong();
     548             : 
     549           8 :         if ( NUMERICFORMATTER_MIN & nMask )
     550           8 :             mnMin = pMgr->ReadLong();
     551             : 
     552           8 :         if ( NUMERICFORMATTER_MAX & nMask )
     553           8 :             mnMax = pMgr->ReadLong();
     554             : 
     555           8 :         if ( NUMERICFORMATTER_STRICTFORMAT & nMask )
     556           0 :             SetStrictFormat( pMgr->ReadShort() != 0 );
     557             : 
     558           8 :         if ( NUMERICFORMATTER_DECIMALDIGITS & nMask )
     559           0 :             SetDecimalDigits( pMgr->ReadShort() );
     560             : 
     561           8 :         if ( NUMERICFORMATTER_VALUE & nMask )
     562             :         {
     563           8 :             mnFieldValue = ClipAgainstMinMax(pMgr->ReadLong());
     564           8 :             mnLastValue = mnFieldValue;
     565             :         }
     566             : 
     567           8 :         if ( NUMERICFORMATTER_NOTHOUSANDSEP & nMask )
     568           0 :             SetUseThousandSep( pMgr->ReadShort() == 0 );
     569             :     }
     570           8 : }
     571             : 
     572           0 : NumericFormatter::~NumericFormatter()
     573             : {
     574           0 : }
     575             : 
     576        8744 : void NumericFormatter::SetMin( sal_Int64 nNewMin )
     577             : {
     578        8744 :     mnMin = nNewMin;
     579        8744 :     if ( !IsEmptyFieldValue() )
     580        8744 :         ReformatAll();
     581        8744 : }
     582             : 
     583        9233 : void NumericFormatter::SetMax( sal_Int64 nNewMax )
     584             : {
     585        9233 :     mnMax = nNewMax;
     586        9233 :     if ( !IsEmptyFieldValue() )
     587        9232 :         ReformatAll();
     588        9233 : }
     589             : 
     590           0 : void NumericFormatter::SetUseThousandSep( bool bValue )
     591             : {
     592           0 :     mbThousandSep = bValue;
     593           0 :     ReformatAll();
     594           0 : }
     595             : 
     596        7900 : void NumericFormatter::SetDecimalDigits( sal_uInt16 nDigits )
     597             : {
     598        7900 :     mnDecimalDigits = nDigits;
     599        7900 :     ReformatAll();
     600        7900 : }
     601             : 
     602         986 : void NumericFormatter::SetShowTrailingZeros( bool bShowTrailingZeros )
     603             : {
     604         986 :     if ( mbShowTrailingZeros != bShowTrailingZeros )
     605             :     {
     606         986 :         mbShowTrailingZeros = bShowTrailingZeros;
     607         986 :         ReformatAll();
     608             :     }
     609         986 : }
     610             : 
     611             : 
     612         430 : void NumericFormatter::SetValue( sal_Int64 nNewValue )
     613             : {
     614         430 :     SetUserValue( nNewValue );
     615         430 :     mnFieldValue = mnLastValue;
     616         430 :     SetEmptyFieldValueData( false );
     617         430 : }
     618             : 
     619       77599 : OUString NumericFormatter::CreateFieldText( sal_Int64 nValue ) const
     620             : {
     621       77599 :     return OUString(ImplGetLocaleDataWrapper().getNum( nValue, GetDecimalDigits(), IsUseThousandSep(), IsShowTrailingZeros() ));
     622             : }
     623             : 
     624        9542 : void NumericFormatter::ImplSetUserValue( sal_Int64 nNewValue, Selection* pNewSelection )
     625             : {
     626        9542 :     nNewValue = ClipAgainstMinMax(nNewValue);
     627        9542 :     mnLastValue = nNewValue;
     628             : 
     629        9542 :     if ( GetField() )
     630        9542 :         ImplSetText( CreateFieldText( nNewValue ), pNewSelection );
     631        9542 : }
     632             : 
     633        9542 : void NumericFormatter::SetUserValue( sal_Int64 nNewValue )
     634             : {
     635        9542 :     ImplSetUserValue( nNewValue );
     636        9542 : }
     637             : 
     638           0 : sal_Int64 NumericFormatter::GetValue() const
     639             : {
     640           0 :     if ( !GetField() )
     641           0 :         return 0;
     642             : 
     643             :     sal_Int64 nTempValue;
     644             : 
     645           0 :     if ( ImplNumericGetValue( GetField()->GetText(), nTempValue,
     646           0 :                               GetDecimalDigits(), ImplGetLocaleDataWrapper() ) )
     647             :     {
     648           0 :         return ClipAgainstMinMax(nTempValue);
     649             :     }
     650             :     else
     651           0 :         return mnLastValue;
     652             : }
     653             : 
     654           0 : bool NumericFormatter::IsValueModified() const
     655             : {
     656           0 :     if ( ImplGetEmptyFieldValue() )
     657           0 :         return !IsEmptyFieldValue();
     658           0 :     else if ( GetValue() != mnFieldValue )
     659           0 :         return true;
     660             :     else
     661           0 :         return false;
     662             : }
     663             : 
     664       22789 : sal_Int64 NumericFormatter::Normalize( sal_Int64 nValue ) const
     665             : {
     666       22789 :     return (nValue * ImplPower10( GetDecimalDigits() ) );
     667             : }
     668             : 
     669       20988 : sal_Int64 NumericFormatter::Denormalize( sal_Int64 nValue ) const
     670             : {
     671       20988 :     sal_Int64 nFactor = ImplPower10( GetDecimalDigits() );
     672             : 
     673       41976 :     if ((nValue < ( SAL_MIN_INT64 + nFactor )) ||
     674       20988 :         (nValue > ( SAL_MAX_INT64 - nFactor )))
     675             :     {
     676        7106 :         return ( nValue / nFactor );
     677             :     }
     678             : 
     679       13882 :     if( nValue < 0 )
     680             :     {
     681           8 :         sal_Int64 nHalf = nFactor / 2;
     682           8 :         return ((nValue - nHalf) / nFactor );
     683             :     }
     684             :     else
     685             :     {
     686       13874 :         sal_Int64 nHalf = nFactor / 2;
     687       13874 :         return ((nValue + nHalf) / nFactor );
     688             :     }
     689             : }
     690             : 
     691        3797 : void NumericFormatter::Reformat()
     692             : {
     693        3797 :     if ( !GetField() )
     694        6668 :         return;
     695             : 
     696         463 :     if ( GetField()->GetText().isEmpty() && ImplGetEmptyFieldValue() )
     697           0 :         return;
     698             : 
     699         463 :     OUString aStr;
     700         463 :     sal_Int64 nTemp = mnLastValue;
     701         463 :     bool bOK = ImplNumericReformat( GetField()->GetText(), nTemp, aStr );
     702         463 :     mnLastValue = nTemp;
     703         463 :     if ( !bOK )
     704           0 :         return;
     705             : 
     706         463 :     if ( !aStr.isEmpty() )
     707         115 :         ImplSetText( aStr );
     708             :     else
     709         348 :         SetValue( mnLastValue );
     710             : }
     711             : 
     712           0 : void NumericFormatter::FieldUp()
     713             : {
     714           0 :     sal_Int64 nValue = GetValue();
     715           0 :     sal_Int64 nRemainder = nValue % mnSpinSize;
     716           0 :     if (nValue >= 0)
     717           0 :         nValue = (nRemainder == 0) ? nValue + mnSpinSize : nValue + mnSpinSize - nRemainder;
     718             :     else
     719           0 :         nValue = (nRemainder == 0) ? nValue + mnSpinSize : nValue - nRemainder;
     720             : 
     721           0 :     nValue = ClipAgainstMinMax(nValue);
     722             : 
     723           0 :     ImplNewFieldValue( nValue );
     724           0 : }
     725             : 
     726           0 : void NumericFormatter::FieldDown()
     727             : {
     728           0 :     sal_Int64 nValue = GetValue();
     729           0 :     sal_Int64 nRemainder = nValue % mnSpinSize;
     730           0 :     if (nValue >= 0)
     731           0 :         nValue = (nRemainder == 0) ? nValue - mnSpinSize : nValue - nRemainder;
     732             :     else
     733           0 :         nValue = (nRemainder == 0) ? nValue - mnSpinSize : nValue - mnSpinSize - nRemainder;
     734             : 
     735           0 :     nValue = ClipAgainstMinMax(nValue);
     736             : 
     737           0 :     ImplNewFieldValue( nValue );
     738           0 : }
     739             : 
     740           0 : void NumericFormatter::FieldFirst()
     741             : {
     742           0 :     ImplNewFieldValue( mnFirst );
     743           0 : }
     744             : 
     745           0 : void NumericFormatter::FieldLast()
     746             : {
     747           0 :     ImplNewFieldValue( mnLast );
     748           0 : }
     749             : 
     750           0 : void NumericFormatter::ImplNewFieldValue( sal_Int64 nNewValue )
     751             : {
     752           0 :     if ( GetField() )
     753             :     {
     754             :         // !!! We should check why we do not validate in ImplSetUserValue() if the value was
     755             :         // changed. This should be done there as well since otherwise the call to Modify would not
     756             :         // be allowed. Anyway, the paths from ImplNewFieldValue, ImplSetUserValue, and ImplSetText
     757             :         // should be checked and clearly traced (with comment) in order to find out what happens.
     758             : 
     759           0 :         Selection aSelection = GetField()->GetSelection();
     760           0 :         aSelection.Justify();
     761           0 :         OUString aText = GetField()->GetText();
     762             :         // leave it as is if selected until end
     763           0 :         if ( (sal_Int32)aSelection.Max() == aText.getLength() )
     764             :         {
     765           0 :             if ( !aSelection.Len() )
     766           0 :                 aSelection.Min() = SELECTION_MAX;
     767           0 :             aSelection.Max() = SELECTION_MAX;
     768             :         }
     769             : 
     770           0 :         sal_Int64 nOldLastValue  = mnLastValue;
     771           0 :         ImplSetUserValue( nNewValue, &aSelection );
     772           0 :         mnLastValue = nOldLastValue;
     773             : 
     774             :         // Modify during Edit is only set during KeyInput
     775           0 :         if ( GetField()->GetText() != aText )
     776             :         {
     777           0 :             GetField()->SetModifyFlag();
     778           0 :             GetField()->Modify();
     779           0 :         }
     780             :     }
     781           0 : }
     782             : 
     783        9665 : sal_Int64 NumericFormatter::ClipAgainstMinMax(sal_Int64 nValue) const
     784             : {
     785        9665 :     if (nValue > mnMax)
     786           0 :         nValue = mbWrapOnLimits ? ((nValue - mnMin) % (mnMax + 1)) + mnMin
     787           0 :                                 : mnMax;
     788        9665 :     else if (nValue < mnMin)
     789           0 :         nValue = mbWrapOnLimits ? ((nValue + mnMax + 1 - mnMin) % (mnMax + 1)) + mnMin
     790        1028 :                                 : mnMin;
     791        9665 :     return nValue;
     792             : }
     793             : 
     794         340 : NumericField::NumericField( vcl::Window* pParent, WinBits nWinStyle ) :
     795         340 :     SpinField( pParent, nWinStyle )
     796             : {
     797         340 :     SetField( this );
     798         340 :     Reformat();
     799         340 : }
     800             : 
     801           8 : NumericField::NumericField( vcl::Window* pParent, const ResId& rResId ) :
     802           8 :     SpinField( WINDOW_NUMERICFIELD )
     803             : {
     804           8 :     rResId.SetRT( RSC_NUMERICFIELD );
     805           8 :     WinBits nStyle = ImplInitRes( rResId ) ;
     806           8 :     SpinField::ImplInit( pParent, nStyle );
     807           8 :     SetField( this );
     808           8 :     ImplLoadRes( rResId );
     809           8 :     Reformat();
     810             : 
     811           8 :     if ( !(nStyle & WB_HIDE ) )
     812           8 :         Show();
     813           8 : }
     814             : 
     815        1812 : bool NumericField::set_property(const OString &rKey, const OString &rValue)
     816             : {
     817        1812 :     if (rKey == "digits")
     818           0 :         SetDecimalDigits(rValue.toInt32());
     819        1812 :     else if (rKey == "spin-size")
     820           0 :         SetSpinSize(rValue.toInt32());
     821        1812 :     else if (rKey == "wrap")
     822           0 :         mbWrapOnLimits = toBool(rValue);
     823             :     else
     824        1812 :         return SpinField::set_property(rKey, rValue);
     825           0 :     return true;
     826             : }
     827             : 
     828           8 : void NumericField::ImplLoadRes( const ResId& rResId )
     829             : {
     830           8 :     SpinField::ImplLoadRes( rResId );
     831           8 :     NumericFormatter::ImplLoadRes( ResId( static_cast<RSHEADER_TYPE *>(GetClassRes()), *rResId.GetResMgr() ) );
     832             : 
     833           8 :     sal_uLong      nMask = ReadLongRes();
     834             : 
     835           8 :     if ( NUMERICFIELD_FIRST & nMask )
     836           8 :         mnFirst = ReadLongRes();
     837             : 
     838           8 :     if ( NUMERICFIELD_LAST & nMask )
     839           8 :         mnLast = ReadLongRes();
     840             : 
     841           8 :     if ( NUMERICFIELD_SPINSIZE & nMask )
     842           0 :         mnSpinSize = ReadLongRes();
     843           8 : }
     844             : 
     845           0 : bool NumericField::PreNotify( NotifyEvent& rNEvt )
     846             : {
     847           0 :         if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
     848             :     {
     849           0 :         if ( ImplNumericProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
     850           0 :             return true;
     851             :     }
     852             : 
     853           0 :     return SpinField::PreNotify( rNEvt );
     854             : }
     855             : 
     856         340 : bool NumericField::Notify( NotifyEvent& rNEvt )
     857             : {
     858         340 :     if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
     859           0 :         MarkToBeReformatted( false );
     860         340 :     else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
     861             :     {
     862           0 :         if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
     863           0 :             Reformat();
     864             :     }
     865             : 
     866         340 :     return SpinField::Notify( rNEvt );
     867             : }
     868             : 
     869         314 : void NumericField::DataChanged( const DataChangedEvent& rDCEvt )
     870             : {
     871         314 :     SpinField::DataChanged( rDCEvt );
     872             : 
     873         314 :     if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
     874             :     {
     875           0 :         OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
     876           0 :         OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
     877           0 :         if ( IsDefaultLocale() )
     878           0 :             ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
     879           0 :         OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
     880           0 :         OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
     881           0 :         ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
     882           0 :         ReformatAll();
     883             :     }
     884         314 : }
     885             : 
     886           0 : void NumericField::Modify()
     887             : {
     888           0 :     MarkToBeReformatted( true );
     889           0 :     SpinField::Modify();
     890           0 : }
     891             : 
     892           0 : void NumericField::Up()
     893             : {
     894           0 :     FieldUp();
     895           0 :     SpinField::Up();
     896           0 : }
     897             : 
     898           0 : void NumericField::Down()
     899             : {
     900           0 :     FieldDown();
     901           0 :     SpinField::Down();
     902           0 : }
     903             : 
     904           0 : void NumericField::First()
     905             : {
     906           0 :     FieldFirst();
     907           0 :     SpinField::First();
     908           0 : }
     909             : 
     910           0 : void NumericField::Last()
     911             : {
     912           0 :     FieldLast();
     913           0 :     SpinField::Last();
     914           0 : }
     915             : 
     916             : namespace
     917             : {
     918        4975 :     Size calcMinimumSize(const Edit &rSpinField, const NumericFormatter &rFormatter)
     919             :     {
     920        4975 :         OUStringBuffer aBuf;
     921             :         sal_Int32 nTextLen;
     922             : 
     923        4975 :         nTextLen = OUString::number(rFormatter.GetMin()).getLength();
     924        4975 :         string::padToLength(aBuf, nTextLen, '9');
     925             :         Size aMinTextSize = rSpinField.CalcMinimumSizeForText(
     926        4975 :             rFormatter.CreateFieldText(aBuf.makeStringAndClear().toInt64()));
     927             : 
     928        4975 :         nTextLen = OUString::number(rFormatter.GetMax()).getLength();
     929        4975 :         string::padToLength(aBuf, nTextLen, '9');
     930             :         Size aMaxTextSize = rSpinField.CalcMinimumSizeForText(
     931        4975 :             rFormatter.CreateFieldText(aBuf.makeStringAndClear().toInt64()));
     932             : 
     933        4975 :         Size aRet(std::max(aMinTextSize.Width(), aMaxTextSize.Width()),
     934        9950 :                   std::max(aMinTextSize.Height(), aMaxTextSize.Height()));
     935             : 
     936        9950 :         OUStringBuffer sBuf("999999999");
     937        4975 :         sal_uInt16 nDigits = rFormatter.GetDecimalDigits();
     938        4975 :         if (nDigits)
     939             :         {
     940        4371 :             sBuf.append('.');
     941        4371 :             string::padToLength(aBuf, aBuf.getLength() + nDigits, '9');
     942             :         }
     943        4975 :         aMaxTextSize = rSpinField.CalcMinimumSizeForText(sBuf.makeStringAndClear());
     944        4975 :         aRet.Width() = std::min(aRet.Width(), aMaxTextSize.Width());
     945             : 
     946        9950 :         return aRet;
     947             :     }
     948             : }
     949             : 
     950         302 : Size NumericField::CalcMinimumSize() const
     951             : {
     952         302 :     return calcMinimumSize(*this, *this);
     953             : }
     954             : 
     955           0 : NumericBox::NumericBox( vcl::Window* pParent, WinBits nWinStyle ) :
     956           0 :     ComboBox( pParent, nWinStyle )
     957             : {
     958           0 :     SetField( this );
     959           0 :     Reformat();
     960           0 :     if ( !(nWinStyle & WB_HIDE ) )
     961           0 :         Show();
     962           0 : }
     963             : 
     964           0 : Size NumericBox::CalcMinimumSize() const
     965             : {
     966           0 :     Size aRet(calcMinimumSize(*this, *this));
     967             : 
     968           0 :     if (IsDropDownBox())
     969             :     {
     970           0 :         Size aComboSugg(ComboBox::CalcMinimumSize());
     971           0 :         aRet.Width() = std::max(aRet.Width(), aComboSugg.Width());
     972           0 :         aRet.Height() = std::max(aRet.Height(), aComboSugg.Height());
     973             :     }
     974             : 
     975           0 :     return aRet;
     976             : }
     977             : 
     978           0 : bool NumericBox::PreNotify( NotifyEvent& rNEvt )
     979             : {
     980           0 :     if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
     981             :     {
     982           0 :         if ( ImplNumericProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
     983           0 :             return true;
     984             :     }
     985             : 
     986           0 :     return ComboBox::PreNotify( rNEvt );
     987             : }
     988             : 
     989           0 : bool NumericBox::Notify( NotifyEvent& rNEvt )
     990             : {
     991           0 :     if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
     992           0 :         MarkToBeReformatted( false );
     993           0 :     else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
     994             :     {
     995           0 :         if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
     996           0 :             Reformat();
     997             :     }
     998             : 
     999           0 :     return ComboBox::Notify( rNEvt );
    1000             : }
    1001             : 
    1002           0 : void NumericBox::DataChanged( const DataChangedEvent& rDCEvt )
    1003             : {
    1004           0 :     ComboBox::DataChanged( rDCEvt );
    1005             : 
    1006           0 :     if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
    1007             :     {
    1008           0 :         OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
    1009           0 :         OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
    1010           0 :         if ( IsDefaultLocale() )
    1011           0 :             ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
    1012           0 :         OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
    1013           0 :         OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
    1014           0 :         ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
    1015           0 :         ReformatAll();
    1016             :     }
    1017           0 : }
    1018             : 
    1019           0 : void NumericBox::Modify()
    1020             : {
    1021           0 :     MarkToBeReformatted( true );
    1022           0 :     ComboBox::Modify();
    1023           0 : }
    1024             : 
    1025           0 : void NumericBox::ReformatAll()
    1026             : {
    1027             :     sal_Int64 nValue;
    1028           0 :     OUString aStr;
    1029           0 :     SetUpdateMode( false );
    1030           0 :     sal_Int32 nEntryCount = GetEntryCount();
    1031           0 :     for ( sal_Int32 i=0; i < nEntryCount; i++ )
    1032             :     {
    1033           0 :         ImplNumericReformat( GetEntry( i ), nValue, aStr );
    1034           0 :         RemoveEntryAt(i);
    1035           0 :         InsertEntry( aStr, i );
    1036             :     }
    1037           0 :     NumericFormatter::Reformat();
    1038           0 :     SetUpdateMode( true );
    1039           0 : }
    1040             : 
    1041           0 : void NumericBox::InsertValue( sal_Int64 nValue, sal_Int32 nPos )
    1042             : {
    1043           0 :     ComboBox::InsertEntry( CreateFieldText( nValue ), nPos );
    1044           0 : }
    1045             : 
    1046           0 : static bool ImplMetricProcessKeyInput( Edit* pEdit, const KeyEvent& rKEvt,
    1047             :                                        bool, bool bUseThousandSep, const LocaleDataWrapper& rWrapper )
    1048             : {
    1049             :     // no meaningfull strict format; therefore allow all characters
    1050           0 :     return ImplNumericProcessKeyInput( pEdit, rKEvt, false, bUseThousandSep, rWrapper );
    1051             : }
    1052             : 
    1053       40642 : static OUString ImplMetricGetUnitText(const OUString& rStr)
    1054             : {
    1055             :     // fetch unit text
    1056       40642 :     OUStringBuffer aStr;
    1057      104401 :     for (sal_Int32 i = rStr.getLength()-1; i >= 0; --i)
    1058             :     {
    1059       74672 :         sal_Unicode c = rStr[i];
    1060       74672 :         if ( (c == '\'') || (c == '\"') || (c == '%' ) || unicode::isAlpha(c) || unicode::isControl(c) )
    1061       11215 :             aStr.insert(0, c);
    1062             :         else
    1063             :         {
    1064       63457 :             if (!aStr.isEmpty())
    1065       10913 :                 break;
    1066             :         }
    1067             :     }
    1068       40642 :     return aStr.makeStringAndClear();
    1069             : }
    1070             : 
    1071             : // #104355# support localized mesaurements
    1072             : 
    1073       62870 : static const OUString ImplMetricToString( FieldUnit rUnit )
    1074             : {
    1075       62870 :     FieldUnitStringList* pList = ImplGetFieldUnits();
    1076       62870 :     if( pList )
    1077             :     {
    1078             :         // return unit's default string (ie, the first one )
    1079     1278862 :         for( FieldUnitStringList::const_iterator it = pList->begin(); it != pList->end(); ++it )
    1080             :         {
    1081     1235744 :             if ( it->second == rUnit )
    1082       19752 :                 return it->first;
    1083             :         }
    1084             :     }
    1085             : 
    1086       43118 :     return OUString();
    1087             : }
    1088             : 
    1089       30502 : static FieldUnit ImplStringToMetric(const OUString &rMetricString)
    1090             : {
    1091       30502 :     FieldUnitStringList* pList = ImplGetCleanedFieldUnits();
    1092       30502 :     if( pList )
    1093             :     {
    1094             :         // return FieldUnit
    1095       30502 :         OUString aStr(rMetricString.toAsciiLowerCase());
    1096       30502 :         aStr = string::remove(aStr, ' ');
    1097      587450 :         for( FieldUnitStringList::const_iterator it = pList->begin(); it != pList->end(); ++it )
    1098             :         {
    1099      567854 :             if ( it->first == aStr )
    1100       10906 :                 return it->second;
    1101       19596 :         }
    1102             :     }
    1103             : 
    1104       19596 :     return FUNIT_NONE;
    1105             : }
    1106             : 
    1107       30502 : static FieldUnit ImplMetricGetUnit(const OUString& rStr)
    1108             : {
    1109       30502 :     OUString aStr = ImplMetricGetUnitText( rStr );
    1110       30502 :     return ImplStringToMetric( aStr );
    1111             : }
    1112             : 
    1113             : #define K *1000L
    1114             : #define M *1000000LL
    1115             : #define X *5280L
    1116             : 
    1117             : // twip in km = 254 / 14 400 000 000
    1118             : // expressions too big for default size 32 bit need LL to avoid overflow
    1119             : 
    1120             : static const sal_Int64 aImplFactor[FUNIT_LINE+1][FUNIT_LINE+1] =
    1121             : { /*
    1122             : mm/100    mm    cm       m     km  twip point  pica  inch    foot       mile     char     line  */
    1123             : {    1,  100,  1 K,  100 K, 100 M, 2540, 2540, 2540, 2540,2540*12,2540*12 X ,   53340, 396240},
    1124             : {    1,    1,   10,    1 K,   1 M, 2540, 2540, 2540, 2540,2540*12,2540*12 X ,    5334, 396240},
    1125             : {    1,    1,    1,    100, 100 K,  254,  254,  254,  254, 254*12, 254*12 X ,    5334,  39624},
    1126             : {    1,    1,    1,      1,   1 K,  254,  254,  254,  254, 254*12, 254*12 X ,  533400,  39624},
    1127             : {    1,    1,    1,      1,     1,  254,  254,  254,  254, 254*12, 254*12 X ,533400 K,  39624},
    1128             : { 1440,144 K,144 K,14400 K,14400LL M, 1,   20,  240, 1440,1440*12,1440*12 X ,     210,   3120},
    1129             : {   72, 7200, 7200,  720 K, 720 M,    1,    1,   12,   72,  72*12,  72*12 X ,     210,    156},
    1130             : {    6,  600,  600,   60 K,  60 M,    1,    1,    1,    6,   6*12,   6*12 X ,     210,     10},
    1131             : {    1,  100,  100,   10 K,  10 M,    1,    1,    1,    1,     12,     12 X ,     210,     45},
    1132             : {    1,  100,  100,   10 K,  10 M,    1,    1,    1,    1,      1,      1 X ,     210,     45},
    1133             : {    1,  100,  100,   10 K,  10 M,    1,    1,    1,    1,      1,        1 ,     210,     45},
    1134             : {  144, 1440,14400,  14400, 14400,    1,   20,  240, 1440,1440*12, 1440*12 X,       1,   156 },
    1135             : {  720,72000,72000, 7200 K,7200LL M, 20,   10,   13,   11,  11*12,   11*12 X,     105,     1 }
    1136             : };
    1137             : #undef X
    1138             : #undef M
    1139             : #undef K
    1140             : 
    1141             : static FieldUnit eDefaultUnit = FUNIT_NONE;
    1142             : 
    1143        2986 : FieldUnit MetricField::GetDefaultUnit() { return eDefaultUnit; }
    1144           0 : void MetricField::SetDefaultUnit( FieldUnit meUnit ) { eDefaultUnit = meUnit; }
    1145             : 
    1146          18 : static FieldUnit ImplMap2FieldUnit( MapUnit meUnit, long& nDecDigits )
    1147             : {
    1148          18 :     switch( meUnit )
    1149             :     {
    1150             :         case MAP_100TH_MM :
    1151          18 :             nDecDigits -= 2;
    1152          18 :             return FUNIT_MM;
    1153             :         case MAP_10TH_MM :
    1154           0 :             nDecDigits -= 1;
    1155           0 :             return FUNIT_MM;
    1156             :         case MAP_MM :
    1157           0 :             return FUNIT_MM;
    1158             :         case MAP_CM :
    1159           0 :             return FUNIT_CM;
    1160             :         case MAP_1000TH_INCH :
    1161           0 :             nDecDigits -= 3;
    1162           0 :             return FUNIT_INCH;
    1163             :         case MAP_100TH_INCH :
    1164           0 :             nDecDigits -= 2;
    1165           0 :             return FUNIT_INCH;
    1166             :         case MAP_10TH_INCH :
    1167           0 :             nDecDigits -= 1;
    1168           0 :             return FUNIT_INCH;
    1169             :         case MAP_INCH :
    1170           0 :             return FUNIT_INCH;
    1171             :         case MAP_POINT :
    1172           0 :             return FUNIT_POINT;
    1173             :         case MAP_TWIP :
    1174           0 :             return FUNIT_TWIP;
    1175             :         default:
    1176             :             OSL_FAIL( "default eInUnit" );
    1177           0 :             break;
    1178             :     }
    1179           0 :     return FUNIT_NONE;
    1180             : }
    1181             : 
    1182       98546 : static double nonValueDoubleToValueDouble( double nValue )
    1183             : {
    1184       98546 :     return rtl::math::isFinite( nValue ) ? nValue : 0.0;
    1185             : }
    1186             : 
    1187       98528 : sal_Int64 MetricField::ConvertValue( sal_Int64 nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits,
    1188             :                                      FieldUnit eInUnit, FieldUnit eOutUnit )
    1189             : {
    1190             :     double nDouble = nonValueDoubleToValueDouble( ConvertDoubleValue(
    1191       98528 :                 (double)nValue, mnBaseValue, nDecDigits, eInUnit, eOutUnit ) );
    1192             :     sal_Int64 nLong ;
    1193             : 
    1194             :     // caution: precision loss in double cast
    1195       98528 :     if ( nDouble <= (double)SAL_MIN_INT64 )
    1196           0 :         nLong = SAL_MIN_INT64;
    1197       98528 :     else if ( nDouble >= (double)SAL_MAX_INT64 )
    1198       12506 :         nLong = SAL_MAX_INT64;
    1199             :     else
    1200       86022 :         nLong = static_cast<sal_Int64>( nDouble );
    1201             : 
    1202       98528 :     return nLong;
    1203             : }
    1204             : 
    1205          18 : sal_Int64 MetricField::ConvertValue( sal_Int64 nValue, sal_uInt16 nDigits,
    1206             :                                      MapUnit eInUnit, FieldUnit eOutUnit )
    1207             : {
    1208             :     return static_cast<sal_Int64>(
    1209             :         nonValueDoubleToValueDouble(
    1210          18 :             ConvertDoubleValue( nValue, nDigits, eInUnit, eOutUnit ) ) );
    1211             : }
    1212             : 
    1213      137992 : double MetricField::ConvertDoubleValue( double nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits,
    1214             :                                         FieldUnit eInUnit, FieldUnit eOutUnit )
    1215             : {
    1216      137992 :     if ( eInUnit != eOutUnit )
    1217             :     {
    1218       54750 :         sal_Int64 nMult = 1, nDiv = 1;
    1219             : 
    1220       54750 :         if ( eInUnit == FUNIT_PERCENT )
    1221             :         {
    1222           0 :             if ( (mnBaseValue <= 0) || (nValue <= 0) )
    1223           0 :                 return nValue;
    1224           0 :             nDiv = 100 * ImplPower10(nDecDigits);
    1225             : 
    1226           0 :             nMult = mnBaseValue;
    1227             :         }
    1228       54750 :         else if ( eOutUnit == FUNIT_PERCENT ||
    1229       37832 :                   eOutUnit == FUNIT_CUSTOM ||
    1230       37832 :                   eOutUnit == FUNIT_NONE ||
    1231       36224 :                   eOutUnit == FUNIT_DEGREE ||
    1232       36224 :                   eOutUnit == FUNIT_SECOND ||
    1233       36224 :                   eOutUnit == FUNIT_MILLISECOND ||
    1234       36224 :                   eOutUnit == FUNIT_PIXEL ||
    1235       22704 :                   eInUnit  == FUNIT_CUSTOM ||
    1236       20141 :                   eInUnit  == FUNIT_NONE ||
    1237       20141 :                   eInUnit  == FUNIT_DEGREE ||
    1238       20141 :                   eInUnit  == FUNIT_MILLISECOND ||
    1239             :                   eInUnit  == FUNIT_PIXEL )
    1240       34609 :              return nValue;
    1241             :         else
    1242             :         {
    1243       20141 :             if ( eOutUnit == FUNIT_100TH_MM )
    1244        1742 :                 eOutUnit = FUNIT_NONE;
    1245       20141 :             if ( eInUnit == FUNIT_100TH_MM )
    1246       11071 :                 eInUnit = FUNIT_NONE;
    1247             : 
    1248       20141 :             nDiv  = aImplFactor[eInUnit][eOutUnit];
    1249       20141 :             nMult = aImplFactor[eOutUnit][eInUnit];
    1250             : 
    1251             :             DBG_ASSERT( nMult > 0, "illegal *" );
    1252             :             DBG_ASSERT( nDiv  > 0, "illegal /" );
    1253             :         }
    1254             : 
    1255       20141 :         if ( nMult != 1 && nMult > 0 )
    1256        9002 :             nValue *= nMult;
    1257       20141 :         if ( nDiv != 1 && nDiv > 0 )
    1258             :         {
    1259       20101 :             nValue += ( nValue < 0 ) ? (-nDiv/2) : (nDiv/2);
    1260       20101 :             nValue /= nDiv;
    1261             :         }
    1262             :     }
    1263             : 
    1264      103383 :     return nValue;
    1265             : }
    1266             : 
    1267          18 : double MetricField::ConvertDoubleValue( double nValue, sal_uInt16 nDigits,
    1268             :                                         MapUnit eInUnit, FieldUnit eOutUnit )
    1269             : {
    1270          18 :     if ( eOutUnit == FUNIT_PERCENT ||
    1271          18 :          eOutUnit == FUNIT_CUSTOM ||
    1272          18 :          eOutUnit == FUNIT_NONE ||
    1273          18 :          eInUnit == MAP_PIXEL ||
    1274          18 :          eInUnit == MAP_SYSFONT ||
    1275          18 :          eInUnit == MAP_APPFONT ||
    1276             :          eInUnit == MAP_RELATIVE )
    1277             :     {
    1278             :         OSL_FAIL( "invalid parameters" );
    1279           0 :         return nValue;
    1280             :     }
    1281             : 
    1282          18 :     long nDecDigits = nDigits;
    1283          18 :     FieldUnit eFieldUnit = ImplMap2FieldUnit( eInUnit, nDecDigits );
    1284             : 
    1285          18 :     if ( nDecDigits < 0 )
    1286             :     {
    1287           8 :         while ( nDecDigits )
    1288             :         {
    1289           4 :             nValue += 5;
    1290           4 :             nValue /= 10;
    1291           4 :             nDecDigits++;
    1292             :         }
    1293             :     }
    1294             :     else
    1295             :     {
    1296          16 :         nValue *= ImplPower10(nDecDigits);
    1297             :     }
    1298             : 
    1299          18 :     if ( eFieldUnit != eOutUnit )
    1300             :     {
    1301          18 :         sal_Int64 nDiv  = aImplFactor[eFieldUnit][eOutUnit];
    1302          18 :         sal_Int64 nMult = aImplFactor[eOutUnit][eFieldUnit];
    1303             : 
    1304             :         DBG_ASSERT( nMult > 0, "illegal *" );
    1305             :         DBG_ASSERT( nDiv  > 0, "illegal /" );
    1306             : 
    1307          18 :         if ( nMult != 1 && nMult > 0)
    1308          18 :             nValue *= nMult;
    1309          18 :         if ( nDiv != 1 && nDiv > 0 )
    1310             :         {
    1311          18 :             nValue += (nValue < 0) ? (-nDiv/2) : (nDiv/2);
    1312          18 :             nValue /= nDiv;
    1313             :         }
    1314             :     }
    1315          18 :     return nValue;
    1316             : }
    1317             : 
    1318           0 : double MetricField::ConvertDoubleValue( double nValue, sal_uInt16 nDigits,
    1319             :                                         FieldUnit eInUnit, MapUnit eOutUnit )
    1320             : {
    1321           0 :     if ( eInUnit == FUNIT_PERCENT ||
    1322           0 :          eInUnit == FUNIT_CUSTOM ||
    1323           0 :          eInUnit == FUNIT_NONE ||
    1324           0 :          eInUnit == FUNIT_DEGREE ||
    1325           0 :          eInUnit == FUNIT_SECOND ||
    1326           0 :          eInUnit == FUNIT_MILLISECOND ||
    1327           0 :          eInUnit == FUNIT_PIXEL ||
    1328           0 :          eOutUnit == MAP_PIXEL ||
    1329           0 :          eOutUnit == MAP_SYSFONT ||
    1330           0 :          eOutUnit == MAP_APPFONT ||
    1331             :          eOutUnit == MAP_RELATIVE )
    1332             :     {
    1333             :         OSL_FAIL( "invalid parameters" );
    1334           0 :         return nValue;
    1335             :     }
    1336             : 
    1337           0 :     long nDecDigits = nDigits;
    1338           0 :     FieldUnit eFieldUnit = ImplMap2FieldUnit( eOutUnit, nDecDigits );
    1339             : 
    1340           0 :     if ( nDecDigits < 0 )
    1341             :     {
    1342           0 :         nValue *= ImplPower10(-nDecDigits);
    1343             :     }
    1344             :     else
    1345             :     {
    1346           0 :         nValue /= ImplPower10(nDecDigits);
    1347             :     }
    1348             : 
    1349           0 :     if ( eFieldUnit != eInUnit )
    1350             :     {
    1351           0 :         sal_Int64 nDiv  = aImplFactor[eInUnit][eFieldUnit];
    1352           0 :         sal_Int64 nMult = aImplFactor[eFieldUnit][eInUnit];
    1353             : 
    1354             :         DBG_ASSERT( nMult > 0, "illegal *" );
    1355             :         DBG_ASSERT( nDiv  > 0, "illegal /" );
    1356             : 
    1357           0 :         if( nMult != 1 && nMult > 0 )
    1358           0 :             nValue *= nMult;
    1359           0 :         if( nDiv != 1 && nDiv > 0 )
    1360             :         {
    1361           0 :             nValue += (nValue < 0) ? (-nDiv/2) : (nDiv/2);
    1362           0 :             nValue /= nDiv;
    1363             :         }
    1364             :     }
    1365           0 :     return nValue;
    1366             : }
    1367             : 
    1368       34474 : static bool ImplMetricGetValue( const OUString& rStr, double& rValue, sal_Int64 nBaseValue,
    1369             :                                 sal_uInt16 nDecDigits, const LocaleDataWrapper& rLocaleDataWrapper, FieldUnit eUnit )
    1370             : {
    1371             :     // Get value
    1372             :     sal_Int64 nValue;
    1373       34474 :     if ( !ImplNumericGetValue( rStr, nValue, nDecDigits, rLocaleDataWrapper ) )
    1374        3972 :         return false;
    1375             : 
    1376             :     // Determine unit
    1377       30502 :     FieldUnit eEntryUnit = ImplMetricGetUnit( rStr );
    1378             : 
    1379             :     // Recalculate unit
    1380             :     // caution: conversion to double loses precision
    1381       30502 :     rValue = MetricField::ConvertDoubleValue( (double)nValue, nBaseValue, nDecDigits, eEntryUnit, eUnit );
    1382             : 
    1383       30502 :     return true;
    1384             : }
    1385             : 
    1386       30136 : bool MetricFormatter::ImplMetricReformat( const OUString& rStr, double& rValue, OUString& rOutStr )
    1387             : {
    1388       30136 :     if ( !ImplMetricGetValue( rStr, rValue, mnBaseValue, GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit ) )
    1389        2986 :         return true;
    1390             :     else
    1391             :     {
    1392       27150 :         double nTempVal = rValue;
    1393             :         // caution: precision loss in double cast
    1394       27150 :         if ( nTempVal > GetMax() )
    1395           0 :             nTempVal = (double)GetMax();
    1396       27150 :         else if ( nTempVal < GetMin())
    1397         986 :             nTempVal = (double)GetMin();
    1398             : 
    1399       27150 :         if ( GetErrorHdl().IsSet() && (rValue != nTempVal) )
    1400             :         {
    1401           0 :             mnCorrectedValue = (sal_Int64)nTempVal;
    1402           0 :             if ( !GetErrorHdl().Call( this ) )
    1403             :             {
    1404           0 :                 mnCorrectedValue = 0;
    1405           0 :                 return false;
    1406             :             }
    1407             :             else
    1408           0 :                 mnCorrectedValue = 0;
    1409             :         }
    1410             : 
    1411       27150 :         rOutStr = CreateFieldText( (sal_Int64)nTempVal );
    1412       27150 :         return true;
    1413             :     }
    1414             : }
    1415             : 
    1416        2986 : inline void MetricFormatter::ImplInit()
    1417             : {
    1418        2986 :     mnBaseValue = 0;
    1419        2986 :     meUnit = MetricField::GetDefaultUnit();
    1420        2986 :     mnType = FORMAT_METRIC;
    1421        2986 : }
    1422             : 
    1423        2986 : MetricFormatter::MetricFormatter()
    1424             : {
    1425        2986 :     ImplInit();
    1426        2986 : }
    1427             : 
    1428           0 : void MetricFormatter::ImplLoadRes( const ResId& rResId )
    1429             : {
    1430           0 :     NumericFormatter::ImplLoadRes( rResId );
    1431             : 
    1432           0 :     ResMgr*     pMgr = rResId.GetResMgr();
    1433           0 :     if( pMgr )
    1434             :     {
    1435           0 :         sal_uLong       nMask = pMgr->ReadLong();
    1436             : 
    1437           0 :         if ( METRICFORMATTER_UNIT & nMask )
    1438             :         {
    1439           0 :             sal_uLong nUnit = pMgr->ReadLong();
    1440             :             assert(nUnit <= FUNIT_MILLISECOND && "out of FieldUnit bounds");
    1441           0 :             if (nUnit <= FUNIT_MILLISECOND)
    1442           0 :                 meUnit = (FieldUnit)nUnit;
    1443             :         }
    1444             : 
    1445           0 :         if ( METRICFORMATTER_CUSTOMUNITTEXT & nMask )
    1446           0 :             maCustomUnitText = pMgr->ReadString();
    1447             :     }
    1448           0 : }
    1449             : 
    1450           0 : MetricFormatter::~MetricFormatter()
    1451             : {
    1452           0 : }
    1453             : 
    1454        3699 : void MetricFormatter::SetUnit( FieldUnit eNewUnit )
    1455             : {
    1456        3699 :     if ( eNewUnit == FUNIT_100TH_MM )
    1457             :     {
    1458           0 :         SetDecimalDigits( GetDecimalDigits() + 2 );
    1459           0 :         meUnit = FUNIT_MM;
    1460             :     }
    1461             :     else
    1462        3699 :         meUnit = eNewUnit;
    1463        3699 :     ReformatAll();
    1464        3699 : }
    1465             : 
    1466           0 : void MetricFormatter::SetCustomUnitText( const OUString& rStr )
    1467             : {
    1468           0 :     maCustomUnitText = rStr;
    1469           0 :     ReformatAll();
    1470           0 : }
    1471             : 
    1472        9112 : void MetricFormatter::SetValue( sal_Int64 nNewValue, FieldUnit eInUnit )
    1473             : {
    1474        9112 :     SetUserValue( nNewValue, eInUnit );
    1475        9112 :     mnFieldValue = mnLastValue;
    1476        9112 : }
    1477             : 
    1478       76404 : OUString MetricFormatter::CreateFieldText( sal_Int64 nValue ) const
    1479             : {
    1480             :     //whether percent is separated from its number is locale
    1481             :     //specific, pawn it off to icu to decide
    1482       76404 :     if (meUnit == FUNIT_PERCENT)
    1483             :     {
    1484          14 :         double dValue = nValue;
    1485          14 :         dValue /= ImplPower10(GetDecimalDigits());
    1486          14 :         return unicode::formatPercent(dValue, Application::GetSettings().GetUILanguageTag());
    1487             :     }
    1488             : 
    1489       76390 :     OUString aStr = NumericFormatter::CreateFieldText( nValue );
    1490             : 
    1491       76390 :     if( meUnit == FUNIT_CUSTOM )
    1492       13520 :         aStr += maCustomUnitText;
    1493             :     else
    1494             :     {
    1495       62870 :         if (meUnit != FUNIT_NONE && meUnit != FUNIT_DEGREE)
    1496       17842 :             aStr += " ";
    1497             :         assert(meUnit != FUNIT_PERCENT);
    1498       62870 :         aStr += ImplMetricToString( meUnit );
    1499             :     }
    1500       76390 :     return aStr;
    1501             : }
    1502             : 
    1503        9112 : void MetricFormatter::SetUserValue( sal_Int64 nNewValue, FieldUnit eInUnit )
    1504             : {
    1505             :     // convert to previously configured units
    1506        9112 :     nNewValue = MetricField::ConvertValue( nNewValue, mnBaseValue, GetDecimalDigits(), eInUnit, meUnit );
    1507        9112 :     NumericFormatter::SetUserValue( nNewValue );
    1508        9112 : }
    1509             : 
    1510        4338 : sal_Int64 MetricFormatter::GetValue( FieldUnit eOutUnit ) const
    1511             : {
    1512        4338 :     if ( !GetField() )
    1513           0 :         return 0;
    1514             : 
    1515             :     double nTempValue;
    1516             :     // caution: precision loss in double cast
    1517        4338 :     if ( !ImplMetricGetValue( GetField()->GetText(), nTempValue, mnBaseValue, GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit ) )
    1518         986 :         nTempValue = (double)mnLastValue;
    1519             : 
    1520             :     // caution: precision loss in double cast
    1521        4338 :     if ( nTempValue > mnMax )
    1522           0 :         nTempValue = (double)mnMax;
    1523        4338 :     else if ( nTempValue < mnMin )
    1524           0 :         nTempValue = (double)mnMin;
    1525             : 
    1526             :     // convert to requested units
    1527        4338 :     return MetricField::ConvertValue( (sal_Int64)nTempValue, mnBaseValue, GetDecimalDigits(), meUnit, eOutUnit );
    1528             : }
    1529             : 
    1530        3163 : void MetricFormatter::SetValue( sal_Int64 nValue )
    1531             : {
    1532             :     // Implementation not inline, because it is a virtual Function
    1533        3163 :     SetValue( nValue, FUNIT_NONE );
    1534        3163 : }
    1535             : 
    1536           0 : sal_Int64 MetricFormatter::GetValue() const
    1537             : {
    1538             :     // Implementation not inline, because it is a virtual Function
    1539           0 :     return GetValue( FUNIT_NONE );
    1540             : }
    1541             : 
    1542        6020 : void MetricFormatter::SetMin( sal_Int64 nNewMin, FieldUnit eInUnit )
    1543             : {
    1544             :     // convert to requested units
    1545        6020 :     NumericFormatter::SetMin( MetricField::ConvertValue( nNewMin, mnBaseValue, GetDecimalDigits(),
    1546       12040 :                                                          eInUnit, meUnit ) );
    1547        6020 : }
    1548             : 
    1549        5247 : sal_Int64 MetricFormatter::GetMin( FieldUnit eOutUnit ) const
    1550             : {
    1551             :     // convert to requested units
    1552             :     return MetricField::ConvertValue( NumericFormatter::GetMin(), mnBaseValue,
    1553        5247 :                                       GetDecimalDigits(), meUnit, eOutUnit );
    1554             : }
    1555             : 
    1556        6548 : void MetricFormatter::SetMax( sal_Int64 nNewMax, FieldUnit eInUnit )
    1557             : {
    1558             :     // convert to requested units
    1559        6548 :     NumericFormatter::SetMax( MetricField::ConvertValue( nNewMax, mnBaseValue, GetDecimalDigits(),
    1560       13096 :                                                          eInUnit, meUnit ) );
    1561        6548 : }
    1562             : 
    1563        5247 : sal_Int64 MetricFormatter::GetMax( FieldUnit eOutUnit ) const
    1564             : {
    1565             :     // convert to requested units
    1566             :     return MetricField::ConvertValue( NumericFormatter::GetMax(), mnBaseValue,
    1567        5247 :                                       GetDecimalDigits(), meUnit, eOutUnit );
    1568             : }
    1569             : 
    1570           0 : void MetricFormatter::SetBaseValue( sal_Int64 nNewBase, FieldUnit eInUnit )
    1571             : {
    1572           0 :     mnBaseValue = MetricField::ConvertValue( nNewBase, mnBaseValue, GetDecimalDigits(),
    1573           0 :                                              eInUnit, meUnit );
    1574           0 : }
    1575             : 
    1576        4636 : sal_Int64 MetricFormatter::GetBaseValue( FieldUnit eOutUnit ) const
    1577             : {
    1578             :     // convert to requested units
    1579        4636 :     return MetricField::ConvertValue( mnBaseValue, mnBaseValue, GetDecimalDigits(),
    1580        9272 :                                       meUnit, eOutUnit );
    1581             : }
    1582             : 
    1583       30136 : void MetricFormatter::Reformat()
    1584             : {
    1585       30136 :     if ( !GetField() )
    1586           0 :         return;
    1587             : 
    1588       30136 :     OUString aText = GetField()->GetText();
    1589       30136 :     if ( meUnit == FUNIT_CUSTOM )
    1590       10140 :         maCurUnitText = ImplMetricGetUnitText( aText );
    1591             : 
    1592       60272 :     OUString aStr;
    1593             :     // caution: precision loss in double cast
    1594       30136 :     double nTemp = (double)mnLastValue;
    1595       30136 :     bool bOK = ImplMetricReformat( aText, nTemp, aStr );
    1596       30136 :     mnLastValue = (sal_Int64)nTemp;
    1597             : 
    1598       30136 :     if ( !bOK )
    1599           0 :         return;
    1600             : 
    1601       30136 :     if ( !aStr.isEmpty() )
    1602             :     {
    1603       27150 :         ImplSetText( aStr );
    1604       27150 :         if ( meUnit == FUNIT_CUSTOM )
    1605       10140 :             CustomConvert();
    1606             :     }
    1607             :     else
    1608        2986 :         SetValue( mnLastValue );
    1609       60272 :     maCurUnitText.clear();
    1610             : }
    1611             : 
    1612           0 : sal_Int64 MetricFormatter::GetCorrectedValue( FieldUnit eOutUnit ) const
    1613             : {
    1614             :     // convert to requested units
    1615           0 :     return MetricField::ConvertValue( mnCorrectedValue, mnBaseValue, GetDecimalDigits(),
    1616           0 :                                       meUnit, eOutUnit );
    1617             : }
    1618             : 
    1619        1848 : MetricField::MetricField( vcl::Window* pParent, WinBits nWinStyle ) :
    1620        1848 :     SpinField( pParent, nWinStyle )
    1621             : {
    1622        1848 :     SetField( this );
    1623        1848 :     Reformat();
    1624        1848 : }
    1625             : 
    1626           0 : MetricField::MetricField( vcl::Window* pParent, const ResId& rResId ) :
    1627           0 :     SpinField( WINDOW_METRICFIELD )
    1628             : {
    1629           0 :     rResId.SetRT( RSC_METRICFIELD );
    1630           0 :     WinBits nStyle = ImplInitRes( rResId ) ;
    1631           0 :     SpinField::ImplInit( pParent, nStyle );
    1632           0 :     SetField( this );
    1633           0 :     ImplLoadRes( rResId );
    1634             : 
    1635           0 :     if ( !(nStyle & WB_HIDE ) )
    1636           0 :         Show();
    1637           0 : }
    1638             : 
    1639        3536 : Size MetricField::CalcMinimumSize() const
    1640             : {
    1641        3536 :     return calcMinimumSize(*this, *this);
    1642             : }
    1643             : 
    1644       13466 : bool MetricField::set_property(const OString &rKey, const OString &rValue)
    1645             : {
    1646       13466 :     if (rKey == "digits")
    1647           0 :         SetDecimalDigits(rValue.toInt32());
    1648       13466 :     else if (rKey == "spin-size")
    1649           0 :         SetSpinSize(rValue.toInt32());
    1650             :     else
    1651       13466 :         return SpinField::set_property(rKey, rValue);
    1652           0 :     return true;
    1653             : }
    1654             : 
    1655           0 : void MetricField::ImplLoadRes( const ResId& rResId )
    1656             : {
    1657           0 :     SpinField::ImplLoadRes( rResId );
    1658           0 :     MetricFormatter::ImplLoadRes( ResId( static_cast<RSHEADER_TYPE *>(GetClassRes()), *rResId.GetResMgr() ) );
    1659             : 
    1660           0 :     sal_uLong      nMask = ReadLongRes();
    1661             : 
    1662           0 :     if ( METRICFIELD_FIRST & nMask )
    1663           0 :         mnFirst = ReadLongRes();
    1664             : 
    1665           0 :     if ( METRICFIELD_LAST & nMask )
    1666           0 :         mnLast = ReadLongRes();
    1667             : 
    1668           0 :     if ( METRICFIELD_SPINSIZE & nMask )
    1669           0 :         mnSpinSize = ReadLongRes();
    1670             : 
    1671           0 :     Reformat();
    1672           0 : }
    1673             : 
    1674        3547 : void MetricField::SetUnit( FieldUnit nNewUnit )
    1675             : {
    1676        3547 :     sal_Int64 nRawMax = GetMax( nNewUnit );
    1677        3547 :     sal_Int64 nMax = Denormalize( nRawMax );
    1678        3547 :     sal_Int64 nMin = Denormalize( GetMin( nNewUnit ) );
    1679        3547 :     sal_Int64 nFirst = Denormalize( GetFirst( nNewUnit ) );
    1680        3547 :     sal_Int64 nLast = Denormalize( GetLast( nNewUnit ) );
    1681             : 
    1682        3547 :     MetricFormatter::SetUnit( nNewUnit );
    1683             : 
    1684        3547 :     SetMax( Normalize( nMax ), nNewUnit );
    1685        3547 :     SetMin( Normalize( nMin ), nNewUnit );
    1686        3547 :     SetFirst( Normalize( nFirst ), nNewUnit );
    1687        3547 :     SetLast( Normalize( nLast ), nNewUnit );
    1688        3547 : }
    1689             : 
    1690        5241 : void MetricField::SetFirst( sal_Int64 nNewFirst, FieldUnit eInUnit )
    1691             : {
    1692             :     // convert
    1693        5241 :     nNewFirst = MetricField::ConvertValue( nNewFirst, mnBaseValue, GetDecimalDigits(),
    1694       10482 :                                            eInUnit, meUnit );
    1695        5241 :     mnFirst = nNewFirst;
    1696        5241 : }
    1697             : 
    1698        5247 : sal_Int64 MetricField::GetFirst( FieldUnit eOutUnit ) const
    1699             : {
    1700             :     // convert
    1701        5247 :     return MetricField::ConvertValue( mnFirst, mnBaseValue, GetDecimalDigits(),
    1702       10494 :                                       meUnit, eOutUnit );
    1703             : }
    1704             : 
    1705        5241 : void MetricField::SetLast( sal_Int64 nNewLast, FieldUnit eInUnit )
    1706             : {
    1707             :     // convert
    1708        5241 :     nNewLast = MetricField::ConvertValue( nNewLast, mnBaseValue, GetDecimalDigits(),
    1709       10482 :                                           eInUnit, meUnit );
    1710        5241 :     mnLast = nNewLast;
    1711        5241 : }
    1712             : 
    1713        5247 : sal_Int64 MetricField::GetLast( FieldUnit eOutUnit ) const
    1714             : {
    1715             :     // conver
    1716        5247 :     return MetricField::ConvertValue( mnLast, mnBaseValue, GetDecimalDigits(),
    1717       10494 :                                       meUnit, eOutUnit );
    1718             : }
    1719             : 
    1720           0 : bool MetricField::PreNotify( NotifyEvent& rNEvt )
    1721             : {
    1722           0 :     if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
    1723             :     {
    1724           0 :         if ( ImplMetricProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
    1725           0 :             return true;
    1726             :     }
    1727             : 
    1728           0 :     return SpinField::PreNotify( rNEvt );
    1729             : }
    1730             : 
    1731        1847 : bool MetricField::Notify( NotifyEvent& rNEvt )
    1732             : {
    1733        1847 :     if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
    1734           0 :         MarkToBeReformatted( false );
    1735        1847 :     else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
    1736             :     {
    1737           0 :         if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
    1738           0 :             Reformat();
    1739             :     }
    1740             : 
    1741        1847 :     return SpinField::Notify( rNEvt );
    1742             : }
    1743             : 
    1744           0 : void MetricField::DataChanged( const DataChangedEvent& rDCEvt )
    1745             : {
    1746           0 :     SpinField::DataChanged( rDCEvt );
    1747             : 
    1748           0 :     if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
    1749             :     {
    1750           0 :         OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
    1751           0 :         OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
    1752           0 :         if ( IsDefaultLocale() )
    1753           0 :             ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
    1754           0 :         OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
    1755           0 :         OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
    1756           0 :         ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
    1757           0 :         ReformatAll();
    1758             :     }
    1759           0 : }
    1760             : 
    1761           0 : void MetricField::Modify()
    1762             : {
    1763           0 :     MarkToBeReformatted( true );
    1764           0 :     SpinField::Modify();
    1765           0 : }
    1766             : 
    1767           0 : void MetricField::Up()
    1768             : {
    1769           0 :     FieldUp();
    1770           0 :     SpinField::Up();
    1771           0 : }
    1772             : 
    1773           0 : void MetricField::Down()
    1774             : {
    1775           0 :     FieldDown();
    1776           0 :     SpinField::Down();
    1777           0 : }
    1778             : 
    1779           0 : void MetricField::First()
    1780             : {
    1781           0 :     FieldFirst();
    1782           0 :     SpinField::First();
    1783           0 : }
    1784             : 
    1785           0 : void MetricField::Last()
    1786             : {
    1787           0 :     FieldLast();
    1788           0 :     SpinField::Last();
    1789           0 : }
    1790             : 
    1791       10140 : void MetricField::CustomConvert()
    1792             : {
    1793       10140 :     maCustomConvertLink.Call( this );
    1794       10140 : }
    1795             : 
    1796        1138 : MetricBox::MetricBox( vcl::Window* pParent, WinBits nWinStyle ) :
    1797        1138 :     ComboBox( pParent, nWinStyle )
    1798             : {
    1799        1138 :     SetField( this );
    1800        1138 :     Reformat();
    1801        1138 : }
    1802             : 
    1803        1137 : Size MetricBox::CalcMinimumSize() const
    1804             : {
    1805        1137 :     Size aRet(calcMinimumSize(*this, *this));
    1806             : 
    1807        1137 :     if (IsDropDownBox())
    1808             :     {
    1809        1137 :         Size aComboSugg(ComboBox::CalcMinimumSize());
    1810        1137 :         aRet.Width() = std::max(aRet.Width(), aComboSugg.Width());
    1811        1137 :         aRet.Height() = std::max(aRet.Height(), aComboSugg.Height());
    1812             :     }
    1813             : 
    1814        1137 :     return aRet;
    1815             : }
    1816             : 
    1817           0 : bool MetricBox::PreNotify( NotifyEvent& rNEvt )
    1818             : {
    1819           0 :     if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2()  )
    1820             :     {
    1821           0 :         if ( ImplMetricProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
    1822           0 :             return true;
    1823             :     }
    1824             : 
    1825           0 :     return ComboBox::PreNotify( rNEvt );
    1826             : }
    1827             : 
    1828        2276 : bool MetricBox::Notify( NotifyEvent& rNEvt )
    1829             : {
    1830        2276 :     if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
    1831           0 :         MarkToBeReformatted( false );
    1832        2276 :     else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
    1833             :     {
    1834           0 :         if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
    1835           0 :             Reformat();
    1836             :     }
    1837             : 
    1838        2276 :     return ComboBox::Notify( rNEvt );
    1839             : }
    1840             : 
    1841           0 : void MetricBox::DataChanged( const DataChangedEvent& rDCEvt )
    1842             : {
    1843           0 :     ComboBox::DataChanged( rDCEvt );
    1844             : 
    1845           0 :     if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
    1846             :     {
    1847           0 :         OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
    1848           0 :         OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
    1849           0 :         if ( IsDefaultLocale() )
    1850           0 :             ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
    1851           0 :         OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
    1852           0 :         OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
    1853           0 :         ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
    1854           0 :         ReformatAll();
    1855             :     }
    1856           0 : }
    1857             : 
    1858           0 : void MetricBox::Modify()
    1859             : {
    1860           0 :     MarkToBeReformatted( true );
    1861           0 :     ComboBox::Modify();
    1862           0 : }
    1863             : 
    1864        4250 : void MetricBox::ReformatAll()
    1865             : {
    1866             :     double nValue;
    1867        4250 :     OUString aStr;
    1868        4250 :     SetUpdateMode( false );
    1869        4250 :     sal_Int32 nEntryCount = GetEntryCount();
    1870        4250 :     for ( sal_Int32 i=0; i < nEntryCount; i++ )
    1871             :     {
    1872           0 :         ImplMetricReformat( GetEntry( i ), nValue, aStr );
    1873           0 :         RemoveEntryAt(i);
    1874           0 :         InsertEntry( aStr, i );
    1875             :     }
    1876        4250 :     MetricFormatter::Reformat();
    1877        4250 :     SetUpdateMode( true );
    1878        4250 : }
    1879             : 
    1880           0 : void MetricBox::CustomConvert()
    1881             : {
    1882           0 :     maCustomConvertLink.Call( this );
    1883           0 : }
    1884             : 
    1885       30796 : void MetricBox::InsertValue( sal_Int64 nValue, FieldUnit eInUnit, sal_Int32 nPos )
    1886             : {
    1887             :     // convert to previously configured units
    1888       30796 :     nValue = MetricField::ConvertValue( nValue, mnBaseValue, GetDecimalDigits(),
    1889       61592 :                                         eInUnit, meUnit );
    1890       30796 :     ComboBox::InsertEntry( CreateFieldText( nValue ), nPos );
    1891       30796 : }
    1892             : 
    1893           0 : sal_Int64 MetricBox::GetValue( sal_Int32 nPos, FieldUnit eOutUnit ) const
    1894             : {
    1895           0 :     double nValue = 0;
    1896             :     ImplMetricGetValue( ComboBox::GetEntry( nPos ), nValue, mnBaseValue,
    1897           0 :                         GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit );
    1898             : 
    1899             :     // convert to previously configured units
    1900           0 :     sal_Int64 nRetValue = MetricField::ConvertValue( (sal_Int64)nValue, mnBaseValue, GetDecimalDigits(),
    1901           0 :                                                      meUnit, eOutUnit );
    1902             : 
    1903           0 :     return nRetValue;
    1904             : }
    1905             : 
    1906           0 : sal_Int32 MetricBox::GetValuePos( sal_Int64 nValue, FieldUnit eInUnit ) const
    1907             : {
    1908             :     // convert to previously configured units
    1909           0 :     nValue = MetricField::ConvertValue( nValue, mnBaseValue, GetDecimalDigits(),
    1910           0 :                                         eInUnit, meUnit );
    1911           0 :     return ComboBox::GetEntryPos( CreateFieldText( nValue ) );
    1912             : }
    1913             : 
    1914        4338 : sal_Int64 MetricBox::GetValue( FieldUnit eOutUnit ) const
    1915             : {
    1916             :     // Implementation not inline, because it is a virtual Function
    1917        4338 :     return MetricFormatter::GetValue( eOutUnit );
    1918             : }
    1919             : 
    1920           0 : sal_Int64 MetricBox::GetValue() const
    1921             : {
    1922             :     // Implementation not inline, because it is a virtual Function
    1923           0 :     return GetValue( FUNIT_NONE );
    1924             : }
    1925             : 
    1926           0 : static bool ImplCurrencyProcessKeyInput( Edit* pEdit, const KeyEvent& rKEvt,
    1927             :                                          bool, bool bUseThousandSep, const LocaleDataWrapper& rWrapper )
    1928             : {
    1929             :     // no strict format set; therefore allow all characters
    1930           0 :     return ImplNumericProcessKeyInput( pEdit, rKEvt, false, bUseThousandSep, rWrapper );
    1931             : }
    1932             : 
    1933           0 : inline bool ImplCurrencyGetValue( const OUString& rStr, sal_Int64& rValue,
    1934             :                                   sal_uInt16 nDecDigits, const LocaleDataWrapper& rWrapper )
    1935             : {
    1936             :     // fetch number
    1937           0 :     return ImplNumericGetValue( rStr, rValue, nDecDigits, rWrapper, true );
    1938             : }
    1939             : 
    1940           0 : bool CurrencyFormatter::ImplCurrencyReformat( const OUString& rStr, OUString& rOutStr )
    1941             : {
    1942             :     sal_Int64 nValue;
    1943           0 :     if ( !ImplNumericGetValue( rStr, nValue, GetDecimalDigits(), ImplGetLocaleDataWrapper(), true ) )
    1944           0 :         return true;
    1945             :     else
    1946             :     {
    1947           0 :         sal_Int64 nTempVal = nValue;
    1948           0 :         if ( nTempVal > GetMax() )
    1949           0 :             nTempVal = GetMax();
    1950           0 :         else if ( nTempVal < GetMin())
    1951           0 :             nTempVal = GetMin();
    1952             : 
    1953           0 :         if ( GetErrorHdl().IsSet() && (nValue != nTempVal) )
    1954             :         {
    1955           0 :             mnCorrectedValue = nTempVal;
    1956           0 :             if ( !GetErrorHdl().Call( this ) )
    1957             :             {
    1958           0 :                 mnCorrectedValue = 0;
    1959           0 :                 return false;
    1960             :             }
    1961             :             else
    1962           0 :                 mnCorrectedValue = 0;
    1963             :         }
    1964             : 
    1965           0 :         rOutStr = CreateFieldText( nTempVal );
    1966           0 :         return true;
    1967             :     }
    1968             : }
    1969             : 
    1970           0 : inline void CurrencyFormatter::ImplInit()
    1971             : {
    1972           0 :     mnType = FORMAT_CURRENCY;
    1973           0 : }
    1974             : 
    1975           0 : CurrencyFormatter::CurrencyFormatter()
    1976             : {
    1977           0 :     ImplInit();
    1978           0 : }
    1979             : 
    1980           0 : CurrencyFormatter::~CurrencyFormatter()
    1981             : {
    1982           0 : }
    1983             : 
    1984           0 : OUString CurrencyFormatter::GetCurrencySymbol() const
    1985             : {
    1986           0 :     return ImplGetLocaleDataWrapper().getCurrSymbol();
    1987             : }
    1988             : 
    1989           0 : void CurrencyFormatter::SetValue( sal_Int64 nNewValue )
    1990             : {
    1991           0 :     SetUserValue( nNewValue );
    1992           0 :     mnFieldValue = mnLastValue;
    1993           0 :     SetEmptyFieldValueData( false );
    1994           0 : }
    1995             : 
    1996           0 : OUString CurrencyFormatter::CreateFieldText( sal_Int64 nValue ) const
    1997             : {
    1998           0 :     return ImplGetLocaleDataWrapper().getCurr( nValue, GetDecimalDigits(), GetCurrencySymbol(), IsUseThousandSep() );
    1999             : }
    2000             : 
    2001           0 : sal_Int64 CurrencyFormatter::GetValue() const
    2002             : {
    2003           0 :     if ( !GetField() )
    2004           0 :         return 0;
    2005             : 
    2006             :     sal_Int64 nTempValue;
    2007           0 :     if ( ImplCurrencyGetValue( GetField()->GetText(), nTempValue, GetDecimalDigits(), ImplGetLocaleDataWrapper() ) )
    2008             :     {
    2009           0 :         return ClipAgainstMinMax(nTempValue);
    2010             :     }
    2011             :     else
    2012           0 :         return mnLastValue;
    2013             : }
    2014             : 
    2015           0 : void CurrencyFormatter::Reformat()
    2016             : {
    2017           0 :     if ( !GetField() )
    2018           0 :         return;
    2019             : 
    2020           0 :     OUString aStr;
    2021           0 :     bool bOK = ImplCurrencyReformat( GetField()->GetText(), aStr );
    2022           0 :     if ( !bOK )
    2023           0 :         return;
    2024             : 
    2025           0 :     if ( !aStr.isEmpty() )
    2026             :     {
    2027           0 :         ImplSetText( aStr  );
    2028           0 :         sal_Int64 nTemp = mnLastValue;
    2029           0 :         ImplCurrencyGetValue( aStr, nTemp, GetDecimalDigits(), ImplGetLocaleDataWrapper() );
    2030           0 :         mnLastValue = nTemp;
    2031             :     }
    2032             :     else
    2033           0 :         SetValue( mnLastValue );
    2034             : }
    2035             : 
    2036           0 : CurrencyField::CurrencyField( vcl::Window* pParent, WinBits nWinStyle ) :
    2037           0 :     SpinField( pParent, nWinStyle )
    2038             : {
    2039           0 :     SetField( this );
    2040           0 :     Reformat();
    2041           0 : }
    2042             : 
    2043           0 : bool CurrencyField::PreNotify( NotifyEvent& rNEvt )
    2044             : {
    2045           0 :     if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
    2046             :     {
    2047           0 :         if ( ImplCurrencyProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
    2048           0 :             return true;
    2049             :     }
    2050             : 
    2051           0 :     return SpinField::PreNotify( rNEvt );
    2052             : }
    2053             : 
    2054           0 : bool CurrencyField::Notify( NotifyEvent& rNEvt )
    2055             : {
    2056           0 :     if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
    2057           0 :         MarkToBeReformatted( false );
    2058           0 :     else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
    2059             :     {
    2060           0 :         if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
    2061           0 :             Reformat();
    2062             :     }
    2063             : 
    2064           0 :     return SpinField::Notify( rNEvt );
    2065             : }
    2066             : 
    2067           0 : void CurrencyField::DataChanged( const DataChangedEvent& rDCEvt )
    2068             : {
    2069           0 :     SpinField::DataChanged( rDCEvt );
    2070             : 
    2071           0 :     if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
    2072             :     {
    2073           0 :         OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
    2074           0 :         OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
    2075           0 :         if ( IsDefaultLocale() )
    2076           0 :             ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
    2077           0 :         OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
    2078           0 :         OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
    2079           0 :         ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
    2080           0 :         ReformatAll();
    2081             :     }
    2082           0 : }
    2083             : 
    2084           0 : void CurrencyField::Modify()
    2085             : {
    2086           0 :     MarkToBeReformatted( true );
    2087           0 :     SpinField::Modify();
    2088           0 : }
    2089             : 
    2090           0 : void CurrencyField::Up()
    2091             : {
    2092           0 :     FieldUp();
    2093           0 :     SpinField::Up();
    2094           0 : }
    2095             : 
    2096           0 : void CurrencyField::Down()
    2097             : {
    2098           0 :     FieldDown();
    2099           0 :     SpinField::Down();
    2100           0 : }
    2101             : 
    2102           0 : void CurrencyField::First()
    2103             : {
    2104           0 :     FieldFirst();
    2105           0 :     SpinField::First();
    2106           0 : }
    2107             : 
    2108           0 : void CurrencyField::Last()
    2109             : {
    2110           0 :     FieldLast();
    2111           0 :     SpinField::Last();
    2112           0 : }
    2113             : 
    2114           0 : CurrencyBox::CurrencyBox( vcl::Window* pParent, WinBits nWinStyle ) :
    2115           0 :     ComboBox( pParent, nWinStyle )
    2116             : {
    2117           0 :     SetField( this );
    2118           0 :     Reformat();
    2119           0 : }
    2120             : 
    2121           0 : bool CurrencyBox::PreNotify( NotifyEvent& rNEvt )
    2122             : {
    2123           0 :     if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
    2124             :     {
    2125           0 :         if ( ImplCurrencyProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
    2126           0 :             return true;
    2127             :     }
    2128             : 
    2129           0 :     return ComboBox::PreNotify( rNEvt );
    2130             : }
    2131             : 
    2132           0 : bool CurrencyBox::Notify( NotifyEvent& rNEvt )
    2133             : {
    2134           0 :     if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
    2135           0 :         MarkToBeReformatted( false );
    2136           0 :     else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
    2137             :     {
    2138           0 :         if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
    2139           0 :             Reformat();
    2140             :     }
    2141             : 
    2142           0 :     return ComboBox::Notify( rNEvt );
    2143             : }
    2144             : 
    2145           0 : void CurrencyBox::DataChanged( const DataChangedEvent& rDCEvt )
    2146             : {
    2147           0 :     ComboBox::DataChanged( rDCEvt );
    2148             : 
    2149           0 :     if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
    2150             :     {
    2151           0 :         OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
    2152           0 :         OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
    2153           0 :         if ( IsDefaultLocale() )
    2154           0 :             ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
    2155           0 :         OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
    2156           0 :         OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
    2157           0 :         ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
    2158           0 :         ReformatAll();
    2159             :     }
    2160           0 : }
    2161             : 
    2162           0 : void CurrencyBox::Modify()
    2163             : {
    2164           0 :     MarkToBeReformatted( true );
    2165           0 :     ComboBox::Modify();
    2166           0 : }
    2167             : 
    2168           0 : void CurrencyBox::ReformatAll()
    2169             : {
    2170           0 :     OUString aStr;
    2171           0 :     SetUpdateMode( false );
    2172           0 :     sal_Int32 nEntryCount = GetEntryCount();
    2173           0 :     for ( sal_Int32 i=0; i < nEntryCount; i++ )
    2174             :     {
    2175           0 :         ImplCurrencyReformat( GetEntry( i ), aStr );
    2176           0 :         RemoveEntryAt(i);
    2177           0 :         InsertEntry( aStr, i );
    2178             :     }
    2179           0 :     CurrencyFormatter::Reformat();
    2180           0 :     SetUpdateMode( true );
    2181           0 : }
    2182             : 
    2183           0 : sal_Int64 CurrencyBox::GetValue() const
    2184             : {
    2185             :     // Implementation not inline, because it is a virtual Function
    2186           0 :     return CurrencyFormatter::GetValue();
    2187         801 : }
    2188             : 
    2189             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11