blob: f736dd7d98da73e935834a5b5fd5cc5b1f005519 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"
#include <sot/object.hxx>
#define _TOOLS_BIGINT
#include <sot/factory.hxx>
#include <tools/debug.hxx>
#include <tools/bigint.hxx>
#include <tools/rc.h>
#include <vcl/event.hxx>
#include <vcl/svapp.hxx>
#include <vcl/longcurr.hxx>
#include <svdata.hxx>
#include <unotools/localedatawrapper.hxx>
// =======================================================================
#define FORMAT_LONGCURRENCY 4
// =======================================================================
static BigInt ImplPower10( sal_uInt16 n )
{
sal_uInt16 i;
BigInt nValue = 1;
for ( i=0; i < n; i++ )
nValue *= 10;
return nValue;
}
// -----------------------------------------------------------------------
static XubString ImplGetCurr( const LocaleDataWrapper& rLocaleDataWrapper, const BigInt &rNumber, sal_uInt16 nDigits, const String& rCurrSymbol, sal_Bool bShowThousandSep )
{
DBG_ASSERT( nDigits < 10, "LongCurrency duerfen nur maximal 9 Nachkommastellen haben" );
if ( rNumber.IsZero() || (long)rNumber )
return rLocaleDataWrapper.getCurr( (long)rNumber, nDigits, rCurrSymbol, bShowThousandSep );
BigInt aTmp( ImplPower10( nDigits ) );
BigInt aInteger( rNumber );
aInteger.Abs();
aInteger /= aTmp;
BigInt aFraction( rNumber );
aFraction.Abs();
aFraction %= aTmp;
if ( !aInteger.IsZero() )
{
aFraction += aTmp;
aTmp = 1000000000L;
}
if ( rNumber.IsNeg() )
aFraction *= -1;
XubString aTemplate = rLocaleDataWrapper.getCurr( (long)aFraction, nDigits, rCurrSymbol, bShowThousandSep );
while( !aInteger.IsZero() )
{
aFraction = aInteger;
aFraction %= aTmp;
aInteger /= aTmp;
if( !aInteger.IsZero() )
aFraction += aTmp;
XubString aFractionStr = rLocaleDataWrapper.getNum( (long)aFraction, 0 );
xub_StrLen nSPos = aTemplate.Search( '1' );
if ( aFractionStr.Len() == 1 )
aTemplate.SetChar( nSPos, aFractionStr.GetChar( 0 ) );
else
{
aTemplate.Erase( nSPos, 1 );
aTemplate.Insert( aFractionStr, nSPos );
}
}
return aTemplate;
}
// -----------------------------------------------------------------------
static sal_Bool ImplNumericProcessKeyInput( Edit*, const KeyEvent& rKEvt,
sal_Bool bStrictFormat, sal_Bool bThousandSep,
const LocaleDataWrapper& rLocaleDataWrapper )
{
if ( !bStrictFormat )
return sal_False;
else
{
sal_Unicode cChar = rKEvt.GetCharCode();
sal_uInt16 nGroup = rKEvt.GetKeyCode().GetGroup();
if ( (nGroup == KEYGROUP_FKEYS) || (nGroup == KEYGROUP_CURSOR) ||
(nGroup == KEYGROUP_MISC) ||
((cChar >= '0') && (cChar <= '9')) ||
(bThousandSep && (cChar == rLocaleDataWrapper.getNumThousandSep())) ||
(cChar == rLocaleDataWrapper.getNumDecimalSep() ) ||
(cChar == '-') )
return sal_False;
else
return sal_True;
}
}
// -----------------------------------------------------------------------
static sal_Bool ImplNumericGetValue( const XubString& rStr, BigInt& rValue,
sal_uInt16 nDecDigits, const LocaleDataWrapper& rLocaleDataWrapper,
sal_Bool bCurrency = sal_False )
{
XubString aStr = rStr;
XubString aStr1;
XubString aStr2;
sal_uInt16 nDecPos;
sal_Bool bNegative = sal_False;
xub_StrLen i;
// Reaktion auf leeren String
if ( !rStr.Len() )
return sal_False;
// Fuehrende und nachfolgende Leerzeichen entfernen
aStr.EraseLeadingAndTrailingChars( ' ' );
// Position des Dezimalpunktes suchen
nDecPos = aStr.Search( rLocaleDataWrapper.getNumDecimalSep() );
if ( nDecPos != STRING_NOTFOUND )
{
aStr1 = aStr.Copy( 0, nDecPos );
aStr2 = aStr.Copy( nDecPos+1 );
}
else
aStr1 = aStr;
// Negativ ?
if ( bCurrency )
{
if ( (aStr.GetChar( 0 ) == '(') && (aStr.GetChar( aStr.Len()-1 ) == ')') )
bNegative = sal_True;
if ( !bNegative )
{
for ( i=0; i < aStr.Len(); i++ )
{
if ( (aStr.GetChar( i ) >= '0') && (aStr.GetChar( i ) <= '9') )
break;
else if ( aStr.GetChar( i ) == '-' )
{
bNegative = sal_True;
break;
}
}
}
if ( !bNegative && bCurrency && aStr.Len() )
{
sal_uInt16 nFormat = rLocaleDataWrapper.getCurrNegativeFormat();
if ( (nFormat == 3) || (nFormat == 6) ||
(nFormat == 7) || (nFormat == 10) )
{
for ( i = (sal_uInt16)(aStr.Len()-1); i > 0; i++ )
{
if ( (aStr.GetChar( i ) >= '0') && (aStr.GetChar( i ) <= '9') )
break;
else if ( aStr.GetChar( i ) == '-' )
{
bNegative = sal_True;
break;
}
}
}
}
}
else
{
if ( aStr1.GetChar( 0 ) == '-' )
bNegative = sal_True;
}
// Alle unerwuenschten Zeichen rauswerfen
for ( i=0; i < aStr1.Len(); )
{
if ( (aStr1.GetChar( i ) >= '0') && (aStr1.GetChar( i ) <= '9') )
i++;
else
aStr1.Erase( i, 1 );
}
for ( i=0; i < aStr2.Len(); )
{
if ( (aStr2.GetChar( i ) >= '0') && (aStr2.GetChar( i ) <= '9') )
i++;
else
aStr2.Erase( i, 1 );
}
if ( !aStr1.Len() && !aStr2.Len() )
return sal_False;
if ( !aStr1.Len() )
aStr1.Insert( '0' );
if ( bNegative )
aStr1.Insert( '-', 0 );
// Nachkommateil zurechtstutzen und dabei runden
sal_Bool bRound = sal_False;
if ( aStr2.Len() > nDecDigits )
{
if ( aStr2.GetChar( nDecDigits ) >= '5' )
bRound = sal_True;
aStr2.Erase( nDecDigits );
}
if ( aStr2.Len() < nDecDigits )
aStr2.Expand( nDecDigits, '0' );
aStr = aStr1;
aStr += aStr2;
// Bereichsueberpruefung
BigInt nValue( aStr );
if ( bRound )
{
if ( !bNegative )
nValue+=1;
else
nValue-=1;
}
rValue = nValue;
return sal_True;
}
// =======================================================================
static sal_Bool ImplLongCurrencyProcessKeyInput( Edit* pEdit, const KeyEvent& rKEvt,
sal_Bool, sal_Bool bUseThousandSep, const LocaleDataWrapper& rLocaleDataWrapper )
{
// Es gibt hier kein sinnvolles StrictFormat, also alle
// Zeichen erlauben
return ImplNumericProcessKeyInput( pEdit, rKEvt, sal_False, bUseThousandSep, rLocaleDataWrapper );
}
// -----------------------------------------------------------------------
inline sal_Bool ImplLongCurrencyGetValue( const XubString& rStr, BigInt& rValue,
sal_uInt16 nDecDigits, const LocaleDataWrapper& rLocaleDataWrapper )
{
// Zahlenwert holen
return ImplNumericGetValue( rStr, rValue, nDecDigits, rLocaleDataWrapper, sal_True );
}
// -----------------------------------------------------------------------
sal_Bool ImplLongCurrencyReformat( const XubString& rStr, BigInt nMin, BigInt nMax,
sal_uInt16 nDecDigits,
const LocaleDataWrapper& rLocaleDataWrapper, String& rOutStr,
LongCurrencyFormatter& rFormatter )
{
BigInt nValue;
if ( !ImplNumericGetValue( rStr, nValue, nDecDigits, rLocaleDataWrapper, sal_True ) )
return sal_True;
else
{
BigInt nTempVal = nValue;
if ( nTempVal > nMax )
nTempVal = nMax;
else if ( nTempVal < nMin )
nTempVal = nMin;
if ( rFormatter.GetErrorHdl().IsSet() && (nValue != nTempVal) )
{
rFormatter.mnCorrectedValue = nTempVal;
if ( !rFormatter.GetErrorHdl().Call( &rFormatter ) )
{
rFormatter.mnCorrectedValue = 0;
return sal_False;
}
else
{
rFormatter.mnCorrectedValue = 0;
}
}
rOutStr = ImplGetCurr( rLocaleDataWrapper, nTempVal, nDecDigits, rFormatter.GetCurrencySymbol(), rFormatter.IsUseThousandSep() );
return sal_True;
}
}
// =======================================================================
void LongCurrencyFormatter::ImpInit()
{
mnFieldValue = 0;
mnLastValue = 0;
mnMin = 0;
mnMax = 0x7FFFFFFF;
mnMax *= 0x7FFFFFFF;
mnCorrectedValue = 0;
mnDecimalDigits = 0;
mnType = FORMAT_LONGCURRENCY;
mbThousandSep = sal_True;
SetDecimalDigits( 0 );
}
// -----------------------------------------------------------------------
LongCurrencyFormatter::LongCurrencyFormatter()
{
ImpInit();
}
// -----------------------------------------------------------------------
void LongCurrencyFormatter::ImplLoadRes( const ResId& rResId )
{
ImpInit();
ResMgr* pMgr = rResId.GetResMgr();
if( pMgr )
{
sal_uLong nMask = pMgr->ReadLong();
if ( NUMERICFORMATTER_MIN & nMask )
mnMin = pMgr->ReadLong();
if ( NUMERICFORMATTER_MAX & nMask )
mnMax = pMgr->ReadLong();
if ( NUMERICFORMATTER_STRICTFORMAT & nMask )
SetStrictFormat( (sal_Bool)pMgr->ReadShort() );
if ( NUMERICFORMATTER_DECIMALDIGITS & nMask )
SetDecimalDigits( pMgr->ReadShort() );
if ( NUMERICFORMATTER_VALUE & nMask )
{
mnFieldValue = pMgr->ReadLong();
if ( mnFieldValue > mnMax )
mnFieldValue = mnMax;
else if ( mnFieldValue < mnMin )
mnFieldValue = mnMin;
mnLastValue = mnFieldValue;
}
}
}
// -----------------------------------------------------------------------
LongCurrencyFormatter::~LongCurrencyFormatter()
{
}
// -----------------------------------------------------------------------
void LongCurrencyFormatter::SetCurrencySymbol( const String& rStr )
{
maCurrencySymbol= rStr;
ReformatAll();
}
// -----------------------------------------------------------------------
String LongCurrencyFormatter::GetCurrencySymbol() const
{
return maCurrencySymbol.Len() ? maCurrencySymbol : GetLocaleDataWrapper().getCurrSymbol();
}
// -----------------------------------------------------------------------
void LongCurrencyFormatter::SetValue( BigInt nNewValue )
{
SetUserValue( nNewValue );
mnFieldValue = mnLastValue;
SetEmptyFieldValueData( sal_False );
}
// -----------------------------------------------------------------------
void LongCurrencyFormatter::SetUserValue( BigInt nNewValue )
{
if ( nNewValue > mnMax )
nNewValue = mnMax;
else if ( nNewValue < mnMin )
nNewValue = mnMin;
mnLastValue = nNewValue;
if ( !GetField() )
return;
XubString aStr = ImplGetCurr( GetLocaleDataWrapper(), nNewValue, GetDecimalDigits(), GetCurrencySymbol(), IsUseThousandSep() );
if ( GetField()->HasFocus() )
{
Selection aSelection = GetField()->GetSelection();
GetField()->SetText( aStr );
GetField()->SetSelection( aSelection );
}
else
GetField()->SetText( aStr );
MarkToBeReformatted( sal_False );
}
// -----------------------------------------------------------------------
BigInt LongCurrencyFormatter::GetValue() const
{
if ( !GetField() )
return 0;
BigInt nTempValue;
if ( ImplLongCurrencyGetValue( GetField()->GetText(), nTempValue, GetDecimalDigits(), GetLocaleDataWrapper() ) )
{
if ( nTempValue > mnMax )
nTempValue = mnMax;
else if ( nTempValue < mnMin )
nTempValue = mnMin;
return nTempValue;
}
else
return mnLastValue;
}
// -----------------------------------------------------------------------
void LongCurrencyFormatter::Reformat()
{
if ( !GetField() )
return;
if ( !GetField()->GetText().Len() && ImplGetEmptyFieldValue() )
return;
XubString aStr;
sal_Bool bOK = ImplLongCurrencyReformat( GetField()->GetText(), mnMin, mnMax,
GetDecimalDigits(), GetLocaleDataWrapper(), aStr, *this );
if ( !bOK )
return;
if ( aStr.Len() )
{
GetField()->SetText( aStr );
MarkToBeReformatted( sal_False );
ImplLongCurrencyGetValue( aStr, mnLastValue, GetDecimalDigits(), GetLocaleDataWrapper() );
}
else
SetValue( mnLastValue );
}
// -----------------------------------------------------------------------
void LongCurrencyFormatter::ReformatAll()
{
Reformat();
}
// -----------------------------------------------------------------------
void LongCurrencyFormatter::SetMin( BigInt nNewMin )
{
mnMin = nNewMin;
ReformatAll();
}
// -----------------------------------------------------------------------
void LongCurrencyFormatter::SetMax( BigInt nNewMax )
{
mnMax = nNewMax;
ReformatAll();
}
// -----------------------------------------------------------------------
void LongCurrencyFormatter::SetUseThousandSep( sal_Bool b )
{
mbThousandSep = b;
ReformatAll();
}
// -----------------------------------------------------------------------
void LongCurrencyFormatter::SetDecimalDigits( sal_uInt16 nDigits )
{
// DBG_ASSERT( nDigits < 10, "LongCurrency duerfen nur maximal 9 Nachkommastellen haben" );
if ( nDigits > 9 )
nDigits = 9;
mnDecimalDigits = nDigits;
ReformatAll();
}
// -----------------------------------------------------------------------
sal_uInt16 LongCurrencyFormatter::GetDecimalDigits() const
{
return mnDecimalDigits;
}
// -----------------------------------------------------------------------
sal_Bool LongCurrencyFormatter::IsValueModified() const
{
if ( ImplGetEmptyFieldValue() )
return !IsEmptyValue();
else if ( GetValue() != mnFieldValue )
return sal_True;
else
return sal_False;
}
// -----------------------------------------------------------------------
void LongCurrencyFormatter::SetEmptyValue()
{
GetField()->SetText( ImplGetSVEmptyStr() );
SetEmptyFieldValueData( sal_True );
}
// -----------------------------------------------------------------------
BigInt LongCurrencyFormatter::Normalize( BigInt nValue ) const
{
return (nValue * ImplPower10( GetDecimalDigits() ) );
}
// -----------------------------------------------------------------------
BigInt LongCurrencyFormatter::Denormalize( BigInt nValue ) const
{
BigInt nFactor = ImplPower10( GetDecimalDigits() );
BigInt nTmp = nFactor;
nTmp /= 2;
nTmp += nValue;
nTmp /= nFactor;
return nTmp;
}
// =======================================================================
void ImplNewLongCurrencyFieldValue( LongCurrencyField* pField, BigInt nNewValue )
{
Selection aSelect = pField->GetSelection();
aSelect.Justify();
XubString aText = pField->GetText();
sal_Bool bLastSelected = ((xub_StrLen)aSelect.Max() == aText.Len()) ? sal_True : sal_False;
BigInt nOldLastValue = pField->mnLastValue;
pField->SetUserValue( nNewValue );
pField->mnLastValue = nOldLastValue;
if ( bLastSelected )
{
if ( !aSelect.Len() )
aSelect.Min() = SELECTION_MAX;
aSelect.Max() = SELECTION_MAX;
}
pField->SetSelection( aSelect );
pField->SetModifyFlag();
pField->Modify();
}
// =======================================================================
LongCurrencyField::LongCurrencyField( Window* pParent, WinBits nWinStyle ) :
SpinField( pParent, nWinStyle )
{
SetField( this );
mnSpinSize = 1;
mnFirst = mnMin;
mnLast = mnMax;
Reformat();
}
// -----------------------------------------------------------------------
LongCurrencyField::LongCurrencyField( Window* pParent, const ResId& rResId ) :
SpinField( WINDOW_NUMERICFIELD )
{
rResId.SetRT( RSC_NUMERICFIELD );
WinBits nStyle = ImplInitRes( rResId ) ;
SpinField::ImplInit( pParent, nStyle );
SetField( this );
mnSpinSize = 1;
mnFirst = mnMin;
mnLast = mnMax;
Reformat();
if ( !(nStyle & WB_HIDE) )
Show();
}
// -----------------------------------------------------------------------
void LongCurrencyField::ImplLoadRes( const ResId& rResId )
{
SpinField::ImplLoadRes( rResId );
LongCurrencyFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) );
sal_uLong nMask = ReadLongRes();
if ( CURRENCYFIELD_FIRST & nMask )
mnFirst = ReadLongRes();
if ( CURRENCYFIELD_LAST & nMask )
mnLast = ReadLongRes();
if ( CURRENCYFIELD_SPINSIZE & nMask )
mnSpinSize = ReadLongRes();
}
// -----------------------------------------------------------------------
LongCurrencyField::~LongCurrencyField()
{
}
// -----------------------------------------------------------------------
long LongCurrencyField::PreNotify( NotifyEvent& rNEvt )
{
if( rNEvt.GetType() == EVENT_KEYINPUT )
{
if ( ImplLongCurrencyProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), GetLocaleDataWrapper() ) )
return 1;
}
return SpinField::PreNotify( rNEvt );
}
// -----------------------------------------------------------------------
long LongCurrencyField::Notify( NotifyEvent& rNEvt )
{
if( rNEvt.GetType() == EVENT_GETFOCUS )
{
MarkToBeReformatted( sal_False );
}
else if( rNEvt.GetType() == EVENT_LOSEFOCUS )
{
if ( MustBeReformatted() )
{
Reformat();
SpinField::Modify();
}
}
return SpinField::Notify( rNEvt );
}
// -----------------------------------------------------------------------
void LongCurrencyField::Modify()
{
MarkToBeReformatted( sal_True );
SpinField::Modify();
}
// -----------------------------------------------------------------------
void LongCurrencyField::Up()
{
BigInt nValue = GetValue();
nValue += mnSpinSize;
if ( nValue > mnMax )
nValue = mnMax;
ImplNewLongCurrencyFieldValue( this, nValue );
SpinField::Up();
}
// -----------------------------------------------------------------------
void LongCurrencyField::Down()
{
BigInt nValue = GetValue();
nValue -= mnSpinSize;
if ( nValue < mnMin )
nValue = mnMin;
ImplNewLongCurrencyFieldValue( this, nValue );
SpinField::Down();
}
// -----------------------------------------------------------------------
void LongCurrencyField::First()
{
ImplNewLongCurrencyFieldValue( this, mnFirst );
SpinField::First();
}
// -----------------------------------------------------------------------
void LongCurrencyField::Last()
{
ImplNewLongCurrencyFieldValue( this, mnLast );
SpinField::Last();
}
// =======================================================================
LongCurrencyBox::LongCurrencyBox( Window* pParent, WinBits nWinStyle ) :
ComboBox( pParent, nWinStyle )
{
SetField( this );
Reformat();
}
// -----------------------------------------------------------------------
LongCurrencyBox::LongCurrencyBox( Window* pParent, const ResId& rResId ) :
ComboBox( WINDOW_NUMERICFIELD )
{
SetField( this );
WinBits nStyle = ImplInitRes( rResId ) ;
ComboBox::ImplLoadRes( rResId );
ImplInit( pParent, nStyle );
LongCurrencyFormatter::ImplLoadRes( rResId );
Reformat();
if ( !(nStyle & WB_HIDE) )
Show();
}
// -----------------------------------------------------------------------
LongCurrencyBox::~LongCurrencyBox()
{
}
// -----------------------------------------------------------------------
long LongCurrencyBox::PreNotify( NotifyEvent& rNEvt )
{
if( rNEvt.GetType() == EVENT_KEYINPUT )
{
if ( ImplLongCurrencyProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), GetLocaleDataWrapper() ) )
return 1;
}
return ComboBox::PreNotify( rNEvt );
}
// -----------------------------------------------------------------------
long LongCurrencyBox::Notify( NotifyEvent& rNEvt )
{
if( rNEvt.GetType() == EVENT_GETFOCUS )
{
MarkToBeReformatted( sal_False );
}
else if( rNEvt.GetType() == EVENT_LOSEFOCUS )
{
if ( MustBeReformatted() )
{
Reformat();
ComboBox::Modify();
}
}
return ComboBox::Notify( rNEvt );
}
// -----------------------------------------------------------------------
void LongCurrencyBox::Modify()
{
MarkToBeReformatted( sal_True );
ComboBox::Modify();
}
// -----------------------------------------------------------------------
void LongCurrencyBox::ReformatAll()
{
XubString aStr;
SetUpdateMode( sal_False );
sal_uInt16 nEntryCount = GetEntryCount();
for ( sal_uInt16 i=0; i < nEntryCount; i++ )
{
ImplLongCurrencyReformat( GetEntry( i ), mnMin, mnMax,
GetDecimalDigits(), GetLocaleDataWrapper(),
aStr, *this );
RemoveEntry( i );
InsertEntry( aStr, i );
}
LongCurrencyFormatter::Reformat();
SetUpdateMode( sal_True );
}
// -----------------------------------------------------------------------
void LongCurrencyBox::InsertValue( BigInt nValue, sal_uInt16 nPos )
{
XubString aStr = ImplGetCurr( GetLocaleDataWrapper(), nValue, GetDecimalDigits(), GetCurrencySymbol(), IsUseThousandSep() );
ComboBox::InsertEntry( aStr, nPos );
}
// -----------------------------------------------------------------------
void LongCurrencyBox::RemoveValue( BigInt nValue )
{
XubString aStr = ImplGetCurr( GetLocaleDataWrapper(), nValue, GetDecimalDigits(), GetCurrencySymbol(), IsUseThousandSep() );
ComboBox::RemoveEntry( aStr );
}
// -----------------------------------------------------------------------
BigInt LongCurrencyBox::GetValue( sal_uInt16 nPos ) const
{
BigInt nValue = 0;
ImplLongCurrencyGetValue( ComboBox::GetEntry( nPos ), nValue,
GetDecimalDigits(), GetLocaleDataWrapper() );
return nValue;
}
// -----------------------------------------------------------------------
sal_uInt16 LongCurrencyBox::GetValuePos( BigInt nValue ) const
{
XubString aStr = ImplGetCurr( GetLocaleDataWrapper(), nValue, GetDecimalDigits(), GetCurrencySymbol(), IsUseThousandSep() );
return ComboBox::GetEntryPos( aStr );
}
// =======================================================================