/**
NSNumberFormatter class
 Copyright (C) 2000 Free Software Foundation, Inc.
 
 Written by: Fred Kiefer <FredKiefer@gmx.de>
 Created: July 2000
 Updated by: Richard Frith-Macdonald <rfm@gnu.org> Sept 2001
 
 This file is part of the GNUstep Base Library.
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
 License as published by the Free Software Foundation; either
 version 2 of the License, or (at your option) any later version.
 
 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Library General Public License for more details.
 
 You should have received a copy of the GNU Library General Public
 License along with this library; if not, write to the Free
 Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 Boston, MA 02111 USA.
 
 <title>NSNumberFormatter class reference</title>
 $Date: 2006-12-29 18:37:07 +0100 (Fri, 29 Dec 2006) $ $Revision: 24293 $
 */

#include "Foundation/NSAttributedString.h"
#include "Foundation/NSDecimalNumber.h"
#include "Foundation/NSDictionary.h"
#include "Foundation/NSException.h"
#include "Foundation/NSNumberFormatter.h"
#include "Foundation/NSString.h"
#include "Foundation/NSUserDefaults.h"
#include "Foundation/NSCharacterSet.h"
#include "Foundation/NSKeyedArchiver.h"

@implementation NSNumberFormatter

- (BOOL) allowsFloats
{
	return _allowsFloats;
}

- (NSAttributedString*) attributedStringForObjectValue: (id)anObject
								 withDefaultAttributes: (NSDictionary*)attr
{
	NSDecimalNumber *zeroNumber = [NSDecimalNumber zero];
	NSDecimalNumber *nanNumber = [NSDecimalNumber notANumber];
	
	if (anObject == nil)
		{
		return [self attributedStringForNil];
		}
	else if (![anObject isKindOfClass: [NSNumber class]])
		{
		return [self attributedStringForNotANumber];
		}
	else if ([anObject isEqual: nanNumber])
		{
		return [self attributedStringForNotANumber];
		}
	else if ([anObject isEqual: zeroNumber])
		{
		return [self attributedStringForZero];
		}
	
	if (([anObject compare: zeroNumber] == NSOrderedDescending)
		&& (_attributesForPositiveValues))
		{
		attr = _attributesForPositiveValues;
		}
	else if (([anObject compare: zeroNumber] == NSOrderedAscending)
			 && (_attributesForNegativeValues))
		{
		attr = _attributesForNegativeValues;
		}
	
	return AUTORELEASE([[NSAttributedString alloc] initWithString:
				 [self stringForObjectValue: anObject] attributes: attr]);
}

- (NSAttributedString*) attributedStringForNil
{
	return _attributedStringForNil;
}

- (NSAttributedString*) attributedStringForNotANumber
{
	return _attributedStringForNotANumber;
}

- (NSAttributedString*) attributedStringForZero
{
	return _attributedStringForZero;
}

- (id) copyWithZone: (NSZone *)zone
{
	NSNumberFormatter	*c = (NSNumberFormatter*) NSCopyObject(self, 0, zone);
	
	RETAIN(c->_negativeFormat);
	RETAIN(c->_positiveFormat);
	RETAIN(c->_attributesForPositiveValues);
	RETAIN(c->_attributesForNegativeValues);
	RETAIN(c->_maximum);
	RETAIN(c->_minimum);
	RETAIN(c->_roundingBehavior);
	RETAIN(c->_roundingBehavior);
	RETAIN(c->_attributedStringForNil);
	RETAIN(c->_attributedStringForNotANumber);
	RETAIN(c->_attributedStringForZero);
	
	return c;
}

- (void) dealloc
{
	RELEASE(_negativeFormat);
	RELEASE(_positiveFormat);
	RELEASE(_attributesForPositiveValues);
	RELEASE(_attributesForNegativeValues);
	RELEASE(_maximum);
	RELEASE(_minimum);
	RELEASE(_roundingBehavior);
	RELEASE(_roundingBehavior);
	RELEASE(_attributedStringForNil);
	RELEASE(_attributedStringForNotANumber);
	RELEASE(_attributedStringForZero);
	[super dealloc];
}

- (NSString*) decimalSeparator
{
	if (_decimalSeparator == 0)
		return @"";
	else
		return [NSString stringWithCharacters: &_decimalSeparator length: 1];
}

- (NSString*) editingStringForObjectValue: (id)anObject
{
	return [self stringForObjectValue: anObject];
}

- (void) encodeWithCoder: (NSCoder*)encoder
{
	[encoder encodeValueOfObjCType: @encode(BOOL) at: &_hasThousandSeparators];
	[encoder encodeValueOfObjCType: @encode(BOOL) at: &_allowsFloats];
	[encoder encodeValueOfObjCType: @encode(BOOL) at: &_localizesFormat];
	[encoder encodeValueOfObjCType: @encode(unichar) at: &_thousandSeparator];
	[encoder encodeValueOfObjCType: @encode(unichar) at: &_decimalSeparator];
	
	[encoder encodeObject: _roundingBehavior];
	[encoder encodeObject: _maximum];
	[encoder encodeObject: _minimum];
	[encoder encodeObject: _attributedStringForNil];
	[encoder encodeObject: _attributedStringForNotANumber];
	[encoder encodeObject: _attributedStringForZero];
	[encoder encodeObject: _negativeFormat];
	[encoder encodeObject: _positiveFormat];
	[encoder encodeObject: _attributesForPositiveValues];
	[encoder encodeObject: _attributesForNegativeValues];
}

- (NSString*) format
{
	if (_attributedStringForZero != nil)
		{
		return [NSString stringWithFormat: @"%@;%@;%@",
			_positiveFormat, [_attributedStringForZero string], _negativeFormat];
		}
	else
		{
		return [NSString stringWithFormat: @"%@;%@",
			_positiveFormat, _negativeFormat];
		}
}

- (BOOL) getObjectValue: (id*)anObject
			  forString: (NSString*)string
       errorDescription: (NSString**)error
{
	/* FIXME: This is just a quick hack implementation.  */
	NSLog(@"NSNumberFormatter-getObjectValue:forString:... not fully implemented");
	
	/* Just assume nothing else has been setup and do a simple conversion. */
	if ([self hasThousandSeparators])
		{
		NSRange range;
		
		range = [string rangeOfString: [self thousandSeparator]];
		if (range.length != 0)
			{
			string = AUTORELEASE([string mutableCopy]);
			[(NSMutableString*)string replaceOccurrencesOfString:
				[self thousandSeparator]
													  withString: @""
														 options: 0
														   range: NSMakeRange(0, [string length])];
			}
		}
	
	if (anObject)
		{
		NSDictionary *locale;
		
		locale = [NSDictionary dictionaryWithObject: [self decimalSeparator] 
											 forKey: NSDecimalSeparator];
		*anObject = [NSDecimalNumber decimalNumberWithString: string
													  locale: locale];
		if (*anObject)
			{
			return YES;
			}
		}
	
	return NO;
}

- (BOOL) hasThousandSeparators
{
	return _hasThousandSeparators;
}

- (id) init
{
	id	o;
	if((self=[super init]))
		{
		_allowsFloats = YES;
		_decimalSeparator = '.';
		_thousandSeparator = ',';
		_hasThousandSeparators = YES;
		o = @"";
		[self setAttributedStringForNil: o];
		RELEASE(o);
		o = @"NaN";
		[self setAttributedStringForNotANumber: o];
		RELEASE(o);
		}
	return self;
}

/*
	NS.allowsfloats = 1;
	NS.attributes = "NSCFType (45)";
	NS.decimal = "NSCFType (71)";
	NS.hasthousands = 0;
	NS.localized = 0;
	NS.max = "NSCFType (69)";
	NS.min = "NSCFType (69)";
	NS.nan = "NSCFType (67)";
	NS.negativeattrs = "NSCFType (0)";
	NS.negativeformat = "NSCFType (61)";
	NS.nil = "NSCFType (65)";
	NS.positiveattrs = "NSCFType (0)";
	NS.positiveformat = "NSCFType (53)";
	NS.rounding = "NSCFType (0)";
	NS.thousand = "NSCFType (63)";
	NS.zero = "NSCFType (55)";
 */

- (id) initWithCoder: (NSCoder*)decoder
{
	if ([decoder allowsKeyedCoding])
		{
		if ([decoder containsValueForKey: @"NS.allowsfloats"])
			{
			[self setAllowsFloats:
				[decoder decodeBoolForKey: @"NS.allowsfloats"]];
			}
		if ([decoder containsValueForKey: @"NS.decimal"])
			{
			[self setDecimalSeparator:
				[decoder decodeObjectForKey: @"NS.decimal"]];
			}
		if ([decoder containsValueForKey: @"NS.hasthousands"])
			{
			[self setHasThousandSeparators:
				[decoder decodeBoolForKey: @"NS.hasthousands"]];
			}
		if ([decoder containsValueForKey: @"NS.localized"])
			{
			[self setLocalizesFormat:
				[decoder decodeBoolForKey: @"NS.localized"]];
			}
		if ([decoder containsValueForKey: @"NS.max"])
			{
			[self setMaximum: [decoder decodeObjectForKey: @"NS.max"]];
			}
		if ([decoder containsValueForKey: @"NS.min"])
			{
			[self setMinimum: [decoder decodeObjectForKey: @"NS.min"]];
			}
		if ([decoder containsValueForKey: @"NS.nan"])
			{
			[self setAttributedStringForNotANumber:
				[decoder decodeObjectForKey: @"NS.nan"]];
			}
		if ([decoder containsValueForKey: @"NS.negativeattrs"])
			{
			[self setTextAttributesForNegativeValues:
				[decoder decodeObjectForKey: @"NS.negativeattrs"]];
			}
		if ([decoder containsValueForKey: @"NS.negativeformat"])
			{
			[self setNegativeFormat:
				[decoder decodeObjectForKey: @"NS.negativeformat"]];
			}
		if ([decoder containsValueForKey: @"NS.nil"])
			{
			[self setAttributedStringForNil:
				[decoder decodeObjectForKey: @"NS.nil"]];
			}
		if ([decoder containsValueForKey: @"NS.positiveattrs"])
			{
			[self setTextAttributesForPositiveValues:
				[decoder decodeObjectForKey: @"NS.positiveattrs"]];
			}
		if ([decoder containsValueForKey: @"NS.positiveformat"])
			{
			[self setPositiveFormat:
				[decoder decodeObjectForKey: @"NS.positiveformat"]];
			}
		if ([decoder containsValueForKey: @"NS.rounding"])
			{
			[self setRoundingBehavior:
				[decoder decodeObjectForKey: @"NS.rounding"]];
			}
		if ([decoder containsValueForKey: @"NS.thousand"])
			{
			[self setThousandSeparator:
				[decoder decodeObjectForKey: @"NS.thousand"]];
			}
		if ([decoder containsValueForKey: @"NS.zero"])
			{
			[self setAttributedStringForZero:
				[decoder decodeObjectForKey: @"NS.zero"]];
			}
		}
	else
		{
		[decoder decodeValueOfObjCType: @encode(BOOL)
									at: &_hasThousandSeparators];
		[decoder decodeValueOfObjCType: @encode(BOOL) at: &_allowsFloats];
		[decoder decodeValueOfObjCType: @encode(BOOL) at: &_localizesFormat];
		[decoder decodeValueOfObjCType: @encode(unichar) at: &_thousandSeparator];
		[decoder decodeValueOfObjCType: @encode(unichar) at: &_decimalSeparator];
		
		[decoder decodeValueOfObjCType: @encode(id) at: &_roundingBehavior];
		[decoder decodeValueOfObjCType: @encode(id) at: &_maximum];
		[decoder decodeValueOfObjCType: @encode(id) at: &_minimum];
		[decoder decodeValueOfObjCType: @encode(id) at: &_attributedStringForNil];
		[decoder decodeValueOfObjCType: @encode(id)
									at: &_attributedStringForNotANumber];
		[decoder decodeValueOfObjCType: @encode(id)
									at: &_attributedStringForZero];
		[decoder decodeValueOfObjCType: @encode(id) at: &_negativeFormat];
		[decoder decodeValueOfObjCType: @encode(id) at: &_positiveFormat];
		[decoder decodeValueOfObjCType: @encode(id)
									at: &_attributesForPositiveValues];
		[decoder decodeValueOfObjCType: @encode(id)
									at: &_attributesForNegativeValues];
		}
	return self;
}

- (BOOL) isPartialStringValid: (NSString*)partialString
			 newEditingString: (NSString**)newString
			 errorDescription: (NSString**)error
{
	// FIXME
	if (newString != NULL)
		{
		*newString = partialString;
		}
	if (error)
		{
		*error = nil;
		}
	
	return YES;
}

- (BOOL) localizesFormat
{
	return _localizesFormat;
}

- (NSNumber*) maximum
{
	return _maximum;
}

- (NSNumber*) minimum
{
	return _minimum;
}

- (NSString*) negativeFormat
{
	return _negativeFormat;
}

- (NSString*) positiveFormat
{
	return _positiveFormat;
}

- (NSDecimalNumberHandler*) roundingBehavior
{
	return _roundingBehavior;
}

- (void) setAllowsFloats: (BOOL)flag
{
	_allowsFloats = flag;
}

- (void) setAttributedStringForNil: (NSAttributedString*)newAttributedString
{
	ASSIGN(_attributedStringForNil, newAttributedString);
}

- (void) setAttributedStringForNotANumber:
	(NSAttributedString*)newAttributedString
{
	ASSIGN(_attributedStringForNotANumber, newAttributedString);
}

- (void) setAttributedStringForZero: (NSAttributedString*)newAttributedString
{
	ASSIGN(_attributedStringForZero, newAttributedString);
}

- (void) setDecimalSeparator: (NSString*)newSeparator
{
	if ([newSeparator length] > 0)
		_decimalSeparator = [newSeparator characterAtIndex: 0];
	else
		_decimalSeparator = 0;
}

- (void) setFormat: (NSString*)aFormat
{
	NSRange	r;
	
	r = [aFormat rangeOfString: @";"];
	if (r.length == 0)
		{
		[self setPositiveFormat: aFormat];
		[self setNegativeFormat: [@"-" stringByAppendingString: aFormat]];
		}
	else
		{
		[self setPositiveFormat: [aFormat substringToIndex: r.location]];
		aFormat = [aFormat substringFromIndex: NSMaxRange(r)];
		r = [aFormat rangeOfString: @";"];
		if (r.length == 0)
			{
			[self setNegativeFormat: aFormat];
			}
		else
			{
			RELEASE(_attributedStringForZero);
			_attributedStringForZero = [[NSAttributedString alloc] initWithString:
				[aFormat substringToIndex: r.location]];
			[self setNegativeFormat: [aFormat substringFromIndex: NSMaxRange(r)]];
			}
		}
}

- (void) setHasThousandSeparators: (BOOL)flag
{
	_hasThousandSeparators = flag;
}

- (void) setLocalizesFormat: (BOOL)flag
{
	_localizesFormat = flag;
}

- (void) setMaximum: (NSNumber*)aMaximum
{
	ASSIGN(_maximum, aMaximum);
}

- (void) setMinimum: (NSNumber*)aMinimum
{
	ASSIGN(_minimum, aMinimum);
}

- (void) setNegativeFormat: (NSString*)aFormat
{
	// FIXME: Should extract separators and attributes
	ASSIGN(_negativeFormat, aFormat);
}

- (void) setPositiveFormat: (NSString*)aFormat
{
	// FIXME: Should extract separators and attributes
	ASSIGN(_positiveFormat, aFormat);
}

- (void) setRoundingBehavior: (NSDecimalNumberHandler*)newRoundingBehavior
{
	ASSIGN(_roundingBehavior, newRoundingBehavior);
}

- (void) setTextAttributesForNegativeValues: (NSDictionary*)newAttributes
{
	ASSIGN(_attributesForNegativeValues, newAttributes);
}

- (void) setTextAttributesForPositiveValues: (NSDictionary*)newAttributes
{
	ASSIGN(_attributesForPositiveValues, newAttributes);
}

- (void) setThousandSeparator: (NSString*)newSeparator
{
	if ([newSeparator length] > 0)
		_thousandSeparator = [newSeparator characterAtIndex: 0];
	else
		_thousandSeparator = 0;
}

- (NSString*) stringForObjectValue: (id)anObject
{
	NSMutableDictionary	*locale;
	NSCharacterSet	*formattingCharacters;
	NSCharacterSet	*placeHolders;
	NSString		*prefix;
	NSString		*suffix;
	NSString		*wholeString;
	NSString		*fracPad=@"";
	NSString		*fracPartString;
	NSMutableString	*intPartString;
	NSMutableString	*formattedNumber;
	NSMutableString	*intPad;
	NSRange		prefixRange;
	NSRange		decimalPlaceRange;
	NSRange		suffixRange;
	NSRange		intPartRange;
	NSDecimal		representativeDecimal;
	NSDecimal		roundedDecimal;
	NSDecimalNumber	*roundedNumber;
	NSDecimalNumber	*intPart;
	NSDecimalNumber	*fracPart;
	int			decimalPlaces = 0;
	BOOL			displayThousandsSeparators = NO;
	BOOL			displayFractionalPart = NO;
	BOOL			negativeNumber = NO;
	NSString		*useFormat;
	
	formattingCharacters = [NSCharacterSet
    characterSetWithCharactersInString: @"0123456789#.,_"];
	placeHolders = [NSCharacterSet 
    characterSetWithCharactersInString: @"0123456789#_"];
	
	if (nil == anObject)
		return [[self attributedStringForNil] string];
	if (![anObject isKindOfClass: [NSNumber class]])
		return [[self attributedStringForNotANumber] string];
	if ([anObject isEqual: [NSDecimalNumber notANumber]])
		return [[self attributedStringForNotANumber] string];
	if ([anObject isEqual: [NSDecimalNumber zero]])
		return [[self attributedStringForZero] string];
	
	useFormat = _positiveFormat;
	if ([anObject compare: [NSDecimalNumber zero]] == NSOrderedAscending)
		{
		useFormat = _negativeFormat;
		negativeNumber = YES;
		}
	
	// if no format specified, use the same default that Cocoa does
	if (nil == useFormat)
		{
		useFormat = negativeNumber ? @"-#,###.##" : @"#,###.##";
		}
	
	prefixRange = [useFormat rangeOfCharacterFromSet: formattingCharacters];
	if (NSNotFound != prefixRange.location)
		{
		prefix = [useFormat substringToIndex: prefixRange.location];
		}
	else
		{
		prefix = @"";
		}
	
	locale = [NSMutableDictionary dictionaryWithCapacity: 3];
	[locale setObject: @"" forKey: NSThousandsSeparator];
	[locale setObject: @"" forKey: NSDecimalSeparator];
	
	//should also set NSDecimalDigits?
	
	if ([self hasThousandSeparators]
		&& (0 != [useFormat rangeOfString:@","].length))
		{
		displayThousandsSeparators = YES;
		}
	
	if ([self allowsFloats]
		&& (NSNotFound != [useFormat rangeOfString:@"." ].location))
		{
		decimalPlaceRange = [useFormat rangeOfString: @"."
											 options: NSBackwardsSearch];
		if (NSMaxRange(decimalPlaceRange) == [useFormat length])
			{
			decimalPlaces = 0;
			}
		else
			{
			while ([placeHolders characterIsMember:
				[useFormat characterAtIndex: NSMaxRange(decimalPlaceRange)]])
				{
				decimalPlaceRange.length++;
				if (NSMaxRange(decimalPlaceRange) == [useFormat length])
					break;
				}
			decimalPlaces=decimalPlaceRange.length -= 1;
			decimalPlaceRange.location += 1;
			fracPad = [useFormat substringWithRange:decimalPlaceRange];
			} 
		if (0 != decimalPlaces)
			displayFractionalPart = YES;
		}
	
	representativeDecimal = [anObject decimalValue];
	NSDecimalRound(&roundedDecimal, &representativeDecimal, decimalPlaces,
				   NSRoundPlain);
	roundedNumber = [NSDecimalNumber decimalNumberWithDecimal: roundedDecimal];
	
	/* Arguably this fiddling could be done by GSDecimalString() but I
		* thought better to leave that behaviour as it is and provide the
		* desired prettification here
		*/
	if (negativeNumber)
		roundedNumber = [roundedNumber decimalNumberByMultiplyingBy:
			(NSDecimalNumber*)[NSDecimalNumber numberWithInt: -1]];
	intPart = (NSDecimalNumber*)
		[NSDecimalNumber numberWithInt: [roundedNumber intValue]];
	fracPart = [roundedNumber decimalNumberBySubtracting: intPart];
	intPartString
		= AUTORELEASE([[intPart descriptionWithLocale: locale] mutableCopy]);
	
	//sort out the padding for the integer part
	intPartRange = [useFormat rangeOfCharacterFromSet: placeHolders];
	if (NSMaxRange(intPartRange) < ([useFormat length] - 1))
		{
		while (([placeHolders characterIsMember:
			[useFormat characterAtIndex: NSMaxRange(intPartRange)]]
				|| [[useFormat substringWithRange:
					NSMakeRange(NSMaxRange(intPartRange), 1)] isEqual: @","])
			   && NSMaxRange(intPartRange) < [useFormat length] - 1)
			{
			intPartRange.length++;
			}
		}
	intPad = [[useFormat substringWithRange: intPartRange] mutableCopy];
	[intPad replaceOccurrencesOfString: @","
							withString: @""
							   options: 0
								 range: NSMakeRange(0, [intPad length])];
	[intPad replaceOccurrencesOfString: @"#"
							withString: @""
							   options: NSAnchoredSearch
								 range: NSMakeRange(0, [intPad length])];
	if ([intPad length] > [intPartString length])
		{
		NSRange		ipRange;
		
		ipRange = NSMakeRange(0, [intPad length] - [intPartString length] + 1);
		[intPartString insertString:
        [intPad substringWithRange: ipRange] atIndex: 0];
		[intPartString replaceOccurrencesOfString: @"_"
									   withString: @" "
										  options: 0
											range: NSMakeRange(0, [intPartString length])];
		[intPartString replaceOccurrencesOfString: @"#"
									   withString: @"0"
										  options: 0
											range: NSMakeRange(0, [intPartString length])];
		}
	// fix the thousands separators up
	if (displayThousandsSeparators && [intPartString length] > 3)
		{
		int index = [intPartString length];
		
		while (0 < (index -= 3))
			{
			[intPartString insertString: [self thousandSeparator] atIndex: index];
			}
		}
	
	formattedNumber = [intPartString mutableCopy];
	
	//fix up the fractional part
	if (displayFractionalPart)
		{
		if (0 != decimalPlaces)
			{
			NSMutableString	*ms;
			
			fracPart = [fracPart decimalNumberByMultiplyingByPowerOf10:
				decimalPlaces];
			ms = [[fracPart descriptionWithLocale: locale] mutableCopy];
			[ms replaceOccurrencesOfString: @"0"
								withString: @""
								   options: (NSBackwardsSearch | NSAnchoredSearch)
									 range: NSMakeRange(0, [ms length])];
			if ([fracPad length] > [ms length])
				{
				NSRange fpRange;
				
				fpRange = NSMakeRange([ms length],
									  ([fracPad length] - [ms length]));
				[ms appendString:
					[fracPad substringWithRange: fpRange]];
				[ms replaceOccurrencesOfString: @"#"
									withString: @""
									   options: (NSBackwardsSearch | NSAnchoredSearch)
										 range: NSMakeRange(0, [ms length])];
				[ms replaceOccurrencesOfString: @"#"
									withString: @"0"
									   options: 0
										 range: NSMakeRange(0, [ms length])];
				[ms replaceOccurrencesOfString: @"_"
									withString: @" "
									   options: 0
										 range: NSMakeRange(0, [ms length])];
				}
			fracPartString = AUTORELEASE(ms);
			}
		else
			{
			fracPartString = @"0";
			}
		[formattedNumber appendString: [self decimalSeparator]];
		[formattedNumber appendString: fracPartString];
		}
	/*FIXME - the suffix doesn't behave the same as on Mac OS X.
		* Our suffix is everything which follows the final formatting
		* character.  Cocoa's suffix is everything which isn't a
		* formatting character nor in the prefix
		*/
	suffixRange = [useFormat rangeOfCharacterFromSet: formattingCharacters
											 options: NSBackwardsSearch];
	suffix = [useFormat substringFromIndex: NSMaxRange(suffixRange)];
	wholeString = [[prefix stringByAppendingString: formattedNumber]
    stringByAppendingString: suffix];
	[formattedNumber release];
	return wholeString;
}

- (NSDictionary*) textAttributesForNegativeValues
{
	return _attributesForNegativeValues;
}

- (NSDictionary*) textAttributesForPositiveValues
{
	return _attributesForPositiveValues;
}

- (NSString*) thousandSeparator
{
	if (!_thousandSeparator)
		return @"";
	else
		return [NSString stringWithCharacters: &_thousandSeparator length: 1];
}

@end
