1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru********************************************************************************
359d709d503bab6e2b61931737e662dd293b40578ccornelius*   Copyright (C) 2005-2013, International Business Machines
4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*   Corporation and others.  All Rights Reserved.
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru********************************************************************************
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* File WINNMFMT.CPP
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru********************************************************************************
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/utypes.h"
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1483a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius#if U_PLATFORM_USES_ONLY_WIN32_API
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "winnmfmt.h"
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/format.h"
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/numfmt.h"
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/locid.h"
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ustring.h"
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cmemory.h"
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "uassert.h"
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "locmap.h"
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#   define WIN32_LEAN_AND_MEAN
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#   define VC_EXTRALEAN
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#   define NOUSER
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#   define NOSERVICE
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#   define NOIME
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#   define NOMCX
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <windows.h>
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <stdio.h>
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_BEGIN
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruunion FormatInfo
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NUMBERFMTW   number;
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    CURRENCYFMTW currency;
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(Win32NumberFormat)
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define NEW_ARRAY(type,count) (type *) uprv_malloc((count) * sizeof(type))
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define DELETE_ARRAY(array) uprv_free((void *) (array))
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define STACK_BUFFER_SIZE 32
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Turns a string of the form "3;2;0" into the grouping UINT
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * needed for NUMBERFMT and CURRENCYFMT. If the string does not
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * end in ";0" then the return value should be multiplied by 10.
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * (e.g. "3" => 30, "3;2" => 320)
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UINT getGrouping(const char *grouping)
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UINT g = 0;
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	const char *s;
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (s = grouping; *s != '\0'; s += 1) {
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (*s > '0' && *s < '9') {
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            g = g * 10 + (*s - '0');
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if (*s != ';') {
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (*s != '0') {
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        g *= 10;
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return g;
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void getNumberFormat(NUMBERFMTW *fmt, int32_t lcid)
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char buf[10];
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    GetLocaleInfoW(lcid, LOCALE_RETURN_NUMBER|LOCALE_IDIGITS, (LPWSTR) &fmt->NumDigits, sizeof(UINT));
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    GetLocaleInfoW(lcid, LOCALE_RETURN_NUMBER|LOCALE_ILZERO,  (LPWSTR) &fmt->LeadingZero, sizeof(UINT));
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    GetLocaleInfoA(lcid, LOCALE_SGROUPING, buf, 10);
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fmt->Grouping = getGrouping(buf);
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fmt->lpDecimalSep = NEW_ARRAY(UChar, 6);
90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    GetLocaleInfoW(lcid, LOCALE_SDECIMAL,  fmt->lpDecimalSep,  6);
91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fmt->lpThousandSep = NEW_ARRAY(UChar, 6);
93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    GetLocaleInfoW(lcid, LOCALE_STHOUSAND, fmt->lpThousandSep, 6);
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    GetLocaleInfoW(lcid, LOCALE_RETURN_NUMBER|LOCALE_INEGNUMBER, (LPWSTR) &fmt->NegativeOrder, sizeof(UINT));
96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void freeNumberFormat(NUMBERFMTW *fmt)
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (fmt != NULL) {
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        DELETE_ARRAY(fmt->lpThousandSep);
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        DELETE_ARRAY(fmt->lpDecimalSep);
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void getCurrencyFormat(CURRENCYFMTW *fmt, int32_t lcid)
107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char buf[10];
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    GetLocaleInfoW(lcid, LOCALE_RETURN_NUMBER|LOCALE_ICURRDIGITS, (LPWSTR) &fmt->NumDigits, sizeof(UINT));
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    GetLocaleInfoW(lcid, LOCALE_RETURN_NUMBER|LOCALE_ILZERO, (LPWSTR) &fmt->LeadingZero, sizeof(UINT));
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    GetLocaleInfoA(lcid, LOCALE_SMONGROUPING, buf, sizeof(buf));
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fmt->Grouping = getGrouping(buf);
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fmt->lpDecimalSep = NEW_ARRAY(UChar, 6);
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    GetLocaleInfoW(lcid, LOCALE_SMONDECIMALSEP,  fmt->lpDecimalSep,  6);
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fmt->lpThousandSep = NEW_ARRAY(UChar, 6);
120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    GetLocaleInfoW(lcid, LOCALE_SMONTHOUSANDSEP, fmt->lpThousandSep, 6);
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    GetLocaleInfoW(lcid, LOCALE_RETURN_NUMBER|LOCALE_INEGCURR,  (LPWSTR) &fmt->NegativeOrder, sizeof(UINT));
123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    GetLocaleInfoW(lcid, LOCALE_RETURN_NUMBER|LOCALE_ICURRENCY, (LPWSTR) &fmt->PositiveOrder, sizeof(UINT));
124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fmt->lpCurrencySymbol = NEW_ARRAY(UChar, 8);
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    GetLocaleInfoW(lcid, LOCALE_SCURRENCY, (LPWSTR) fmt->lpCurrencySymbol, 8);
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void freeCurrencyFormat(CURRENCYFMTW *fmt)
130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (fmt != NULL) {
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        DELETE_ARRAY(fmt->lpCurrencySymbol);
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        DELETE_ARRAY(fmt->lpThousandSep);
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        DELETE_ARRAY(fmt->lpDecimalSep);
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruWin32NumberFormat::Win32NumberFormat(const Locale &locale, UBool currency, UErrorCode &status)
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  : NumberFormat(), fCurrency(currency), fFractionDigitsSet(FALSE), fFormatInfo(NULL)
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!U_FAILURE(status)) {
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fLCID = locale.getLCID();
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
14459d709d503bab6e2b61931737e662dd293b40578ccornelius        // Resolve actual locale to be used later
14559d709d503bab6e2b61931737e662dd293b40578ccornelius        UErrorCode tmpsts = U_ZERO_ERROR;
14659d709d503bab6e2b61931737e662dd293b40578ccornelius        char tmpLocID[ULOC_FULLNAME_CAPACITY];
14759d709d503bab6e2b61931737e662dd293b40578ccornelius        int32_t len = uloc_getLocaleForLCID(fLCID, tmpLocID, sizeof(tmpLocID)/sizeof(tmpLocID[0]) - 1, &tmpsts);
14859d709d503bab6e2b61931737e662dd293b40578ccornelius        if (U_SUCCESS(tmpsts)) {
14959d709d503bab6e2b61931737e662dd293b40578ccornelius            tmpLocID[len] = 0;
15059d709d503bab6e2b61931737e662dd293b40578ccornelius            fLocale = Locale((const char*)tmpLocID);
15159d709d503bab6e2b61931737e662dd293b40578ccornelius        }
15259d709d503bab6e2b61931737e662dd293b40578ccornelius
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        fFormatInfo = (FormatInfo*)uprv_malloc(sizeof(FormatInfo));
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (fCurrency) {
156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            getCurrencyFormat(&fFormatInfo->currency, fLCID);
157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            getNumberFormat(&fFormatInfo->number, fLCID);
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruWin32NumberFormat::Win32NumberFormat(const Win32NumberFormat &other)
164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  : NumberFormat(other), fFormatInfo((FormatInfo*)uprv_malloc(sizeof(FormatInfo)))
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (fFormatInfo != NULL) {
167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_memset(fFormatInfo, 0, sizeof(*fFormatInfo));
168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    *this = other;
170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruWin32NumberFormat::~Win32NumberFormat()
173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (fFormatInfo != NULL) {
175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (fCurrency) {
176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            freeCurrencyFormat(&fFormatInfo->currency);
177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            freeNumberFormat(&fFormatInfo->number);
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_free(fFormatInfo);
182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruWin32NumberFormat &Win32NumberFormat::operator=(const Win32NumberFormat &other)
186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NumberFormat::operator=(other);
188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    this->fCurrency          = other.fCurrency;
19059d709d503bab6e2b61931737e662dd293b40578ccornelius    this->fLocale            = other.fLocale;
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    this->fLCID              = other.fLCID;
192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    this->fFractionDigitsSet = other.fFractionDigitsSet;
193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (fCurrency) {
195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        freeCurrencyFormat(&fFormatInfo->currency);
196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        getCurrencyFormat(&fFormatInfo->currency, fLCID);
197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        freeNumberFormat(&fFormatInfo->number);
199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        getNumberFormat(&fFormatInfo->number, fLCID);
200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return *this;
203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruFormat *Win32NumberFormat::clone(void) const
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return new Win32NumberFormat(*this);
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString& Win32NumberFormat::format(double number, UnicodeString& appendTo, FieldPosition& pos) const
211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return format(getMaximumFractionDigits(), appendTo, L"%.16f", number);
213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString& Win32NumberFormat::format(int32_t number, UnicodeString& appendTo, FieldPosition& pos) const
216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return format(getMinimumFractionDigits(), appendTo, L"%I32d", number);
218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString& Win32NumberFormat::format(int64_t number, UnicodeString& appendTo, FieldPosition& pos) const
221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return format(getMinimumFractionDigits(), appendTo, L"%I64d", number);
223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid Win32NumberFormat::parse(const UnicodeString& text, Formattable& result, ParsePosition& parsePosition) const
226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
22859d709d503bab6e2b61931737e662dd293b40578ccornelius    NumberFormat *nf = fCurrency? NumberFormat::createCurrencyInstance(fLocale, status) : NumberFormat::createInstance(fLocale, status);
229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    nf->parse(text, result, parsePosition);
231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete nf;
232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid Win32NumberFormat::setMaximumFractionDigits(int32_t newValue)
234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fFractionDigitsSet = TRUE;
236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NumberFormat::setMaximumFractionDigits(newValue);
237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid Win32NumberFormat::setMinimumFractionDigits(int32_t newValue)
240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fFractionDigitsSet = TRUE;
242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NumberFormat::setMinimumFractionDigits(newValue);
243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString &Win32NumberFormat::format(int32_t numDigits, UnicodeString &appendTo, wchar_t *fmt, ...) const
246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    wchar_t nStackBuffer[STACK_BUFFER_SIZE];
248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    wchar_t *nBuffer = nStackBuffer;
249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    va_list args;
250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int result;
251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    nBuffer[0] = 0x0000;
253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Due to the arguments causing a result to be <= 23 characters (+2 for NULL and minus),
255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    we don't need to reallocate the buffer. */
256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    va_start(args, fmt);
257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    result = _vsnwprintf(nBuffer, STACK_BUFFER_SIZE, fmt, args);
258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    va_end(args);
259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* Just to make sure of the above statement, we add this assert */
261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    U_ASSERT(result >=0);
262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // The following code is not used because _vscwprintf isn't available on MinGW at the moment.
263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*if (result < 0) {
264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int newLength;
265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        va_start(args, fmt);
267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        newLength = _vscwprintf(fmt, args);
268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        va_end(args);
269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        nBuffer = NEW_ARRAY(UChar, newLength + 1);
271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        va_start(args, fmt);
273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        result = _vsnwprintf(nBuffer, newLength + 1, fmt, args);
274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        va_end(args);
275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }*/
276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // vswprintf is sensitive to the locale set by setlocale. For some locales
278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // it doesn't use "." as the decimal separator, which is what GetNumberFormatW
279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // and GetCurrencyFormatW both expect to see.
280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //
281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // To fix this, we scan over the string and replace the first non-digits, except
282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // for a leading "-", with a "."
283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //
284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // Note: (nBuffer[0] == L'-') will evaluate to 1 if there is a leading '-' in the
285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // number, and 0 otherwise.
286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (wchar_t *p = &nBuffer[nBuffer[0] == L'-']; *p != L'\0'; p += 1) {
287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (*p < L'0' || *p > L'9') {
288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *p = L'.';
289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar stackBuffer[STACK_BUFFER_SIZE];
294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar *buffer = stackBuffer;
295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    FormatInfo formatInfo;
296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    formatInfo = *fFormatInfo;
298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    buffer[0] = 0x0000;
299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (fCurrency) {
301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (fFractionDigitsSet) {
302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            formatInfo.currency.NumDigits = (UINT) numDigits;
303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (!isGroupingUsed()) {
306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            formatInfo.currency.Grouping = 0;
307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        result = GetCurrencyFormatW(fLCID, 0, nBuffer, &formatInfo.currency, buffer, STACK_BUFFER_SIZE);
310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (result == 0) {
312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            DWORD lastError = GetLastError();
313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (lastError == ERROR_INSUFFICIENT_BUFFER) {
315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                int newLength = GetCurrencyFormatW(fLCID, 0, nBuffer, &formatInfo.currency, NULL, 0);
316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                buffer = NEW_ARRAY(UChar, newLength);
318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                buffer[0] = 0x0000;
319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                GetCurrencyFormatW(fLCID, 0, nBuffer,  &formatInfo.currency, buffer, newLength);
320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (fFractionDigitsSet) {
324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            formatInfo.number.NumDigits = (UINT) numDigits;
325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (!isGroupingUsed()) {
328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            formatInfo.number.Grouping = 0;
329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        result = GetNumberFormatW(fLCID, 0, nBuffer, &formatInfo.number, buffer, STACK_BUFFER_SIZE);
332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (result == 0) {
334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                int newLength = GetNumberFormatW(fLCID, 0, nBuffer, &formatInfo.number, NULL, 0);
336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                buffer = NEW_ARRAY(UChar, newLength);
338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                buffer[0] = 0x0000;
339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                GetNumberFormatW(fLCID, 0, nBuffer, &formatInfo.number, buffer, newLength);
340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    appendTo.append(buffer, (int32_t) wcslen(buffer));
345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (buffer != stackBuffer) {
347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        DELETE_ARRAY(buffer);
348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*if (nBuffer != nStackBuffer) {
351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        DELETE_ARRAY(nBuffer);
352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }*/
353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return appendTo;
355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_END
358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */
360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
36183a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius#endif // U_PLATFORM_USES_ONLY_WIN32_API
362