16f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
26f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org********************************************************************************
36f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Copyright (C) 2005-2013, International Business Machines
46f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*   Corporation and others.  All Rights Reserved.
56f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org********************************************************************************
66f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
76f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* File WINNMFMT.CPP
86f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*
96f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org********************************************************************************
106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/utypes.h"
136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if U_PLATFORM_USES_ONLY_WIN32_API
156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if !UCONFIG_NO_FORMATTING
176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "winnmfmt.h"
196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/format.h"
216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/numfmt.h"
226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/locid.h"
236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/ustring.h"
246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "cmemory.h"
266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "uassert.h"
276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "locmap.h"
286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#   define WIN32_LEAN_AND_MEAN
306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#   define VC_EXTRALEAN
316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#   define NOUSER
326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#   define NOSERVICE
336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#   define NOIME
346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#   define NOMCX
356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include <windows.h>
366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include <stdio.h>
376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_NAMESPACE_BEGIN
396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgunion FormatInfo
416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    NUMBERFMTW   number;
436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    CURRENCYFMTW currency;
446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUOBJECT_DEFINE_RTTI_IMPLEMENTATION(Win32NumberFormat)
476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define NEW_ARRAY(type,count) (type *) uprv_malloc((count) * sizeof(type))
496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define DELETE_ARRAY(array) uprv_free((void *) (array))
506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define STACK_BUFFER_SIZE 32
526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Turns a string of the form "3;2;0" into the grouping UINT
556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * needed for NUMBERFMT and CURRENCYFMT. If the string does not
566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * end in ";0" then the return value should be multiplied by 10.
576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * (e.g. "3" => 30, "3;2" => 320)
586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UINT getGrouping(const char *grouping)
606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UINT g = 0;
626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org	const char *s;
636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for (s = grouping; *s != '\0'; s += 1) {
656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (*s > '0' && *s < '9') {
666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            g = g * 10 + (*s - '0');
676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if (*s != ';') {
686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (*s != '0') {
736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        g *= 10;
746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return g;
776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic void getNumberFormat(NUMBERFMTW *fmt, int32_t lcid)
806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char buf[10];
826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    GetLocaleInfoW(lcid, LOCALE_RETURN_NUMBER|LOCALE_IDIGITS, (LPWSTR) &fmt->NumDigits, sizeof(UINT));
846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    GetLocaleInfoW(lcid, LOCALE_RETURN_NUMBER|LOCALE_ILZERO,  (LPWSTR) &fmt->LeadingZero, sizeof(UINT));
856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    GetLocaleInfoA(lcid, LOCALE_SGROUPING, buf, 10);
876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fmt->Grouping = getGrouping(buf);
886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fmt->lpDecimalSep = NEW_ARRAY(UChar, 6);
906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    GetLocaleInfoW(lcid, LOCALE_SDECIMAL,  fmt->lpDecimalSep,  6);
916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fmt->lpThousandSep = NEW_ARRAY(UChar, 6);
936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    GetLocaleInfoW(lcid, LOCALE_STHOUSAND, fmt->lpThousandSep, 6);
946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    GetLocaleInfoW(lcid, LOCALE_RETURN_NUMBER|LOCALE_INEGNUMBER, (LPWSTR) &fmt->NegativeOrder, sizeof(UINT));
966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic void freeNumberFormat(NUMBERFMTW *fmt)
996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
1006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (fmt != NULL) {
1016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        DELETE_ARRAY(fmt->lpThousandSep);
1026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        DELETE_ARRAY(fmt->lpDecimalSep);
1036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic void getCurrencyFormat(CURRENCYFMTW *fmt, int32_t lcid)
1076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
1086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char buf[10];
1096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    GetLocaleInfoW(lcid, LOCALE_RETURN_NUMBER|LOCALE_ICURRDIGITS, (LPWSTR) &fmt->NumDigits, sizeof(UINT));
1116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    GetLocaleInfoW(lcid, LOCALE_RETURN_NUMBER|LOCALE_ILZERO, (LPWSTR) &fmt->LeadingZero, sizeof(UINT));
1126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    GetLocaleInfoA(lcid, LOCALE_SMONGROUPING, buf, sizeof(buf));
1146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fmt->Grouping = getGrouping(buf);
1156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fmt->lpDecimalSep = NEW_ARRAY(UChar, 6);
1176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    GetLocaleInfoW(lcid, LOCALE_SMONDECIMALSEP,  fmt->lpDecimalSep,  6);
1186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fmt->lpThousandSep = NEW_ARRAY(UChar, 6);
1206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    GetLocaleInfoW(lcid, LOCALE_SMONTHOUSANDSEP, fmt->lpThousandSep, 6);
1216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    GetLocaleInfoW(lcid, LOCALE_RETURN_NUMBER|LOCALE_INEGCURR,  (LPWSTR) &fmt->NegativeOrder, sizeof(UINT));
1236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    GetLocaleInfoW(lcid, LOCALE_RETURN_NUMBER|LOCALE_ICURRENCY, (LPWSTR) &fmt->PositiveOrder, sizeof(UINT));
1246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fmt->lpCurrencySymbol = NEW_ARRAY(UChar, 8);
1266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    GetLocaleInfoW(lcid, LOCALE_SCURRENCY, (LPWSTR) fmt->lpCurrencySymbol, 8);
1276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic void freeCurrencyFormat(CURRENCYFMTW *fmt)
1306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
1316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (fmt != NULL) {
1326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        DELETE_ARRAY(fmt->lpCurrencySymbol);
1336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        DELETE_ARRAY(fmt->lpThousandSep);
1346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        DELETE_ARRAY(fmt->lpDecimalSep);
1356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgWin32NumberFormat::Win32NumberFormat(const Locale &locale, UBool currency, UErrorCode &status)
1396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  : NumberFormat(), fCurrency(currency), fFractionDigitsSet(FALSE), fFormatInfo(NULL)
1406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
1416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (!U_FAILURE(status)) {
1426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fLCID = locale.getLCID();
1436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // Resolve actual locale to be used later
1456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UErrorCode tmpsts = U_ZERO_ERROR;
1466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        char tmpLocID[ULOC_FULLNAME_CAPACITY];
1476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t len = uloc_getLocaleForLCID(fLCID, tmpLocID, sizeof(tmpLocID)/sizeof(tmpLocID[0]) - 1, &tmpsts);
1486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (U_SUCCESS(tmpsts)) {
1496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            tmpLocID[len] = 0;
1506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            fLocale = Locale((const char*)tmpLocID);
1516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        fFormatInfo = (FormatInfo*)uprv_malloc(sizeof(FormatInfo));
1546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (fCurrency) {
1566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            getCurrencyFormat(&fFormatInfo->currency, fLCID);
1576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
1586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            getNumberFormat(&fFormatInfo->number, fLCID);
1596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgWin32NumberFormat::Win32NumberFormat(const Win32NumberFormat &other)
1646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  : NumberFormat(other), fFormatInfo((FormatInfo*)uprv_malloc(sizeof(FormatInfo)))
1656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
1666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (fFormatInfo != NULL) {
1676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_memset(fFormatInfo, 0, sizeof(*fFormatInfo));
1686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    *this = other;
1706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgWin32NumberFormat::~Win32NumberFormat()
1736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
1746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (fFormatInfo != NULL) {
1756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (fCurrency) {
1766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            freeCurrencyFormat(&fFormatInfo->currency);
1776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
1786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            freeNumberFormat(&fFormatInfo->number);
1796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_free(fFormatInfo);
1826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgWin32NumberFormat &Win32NumberFormat::operator=(const Win32NumberFormat &other)
1866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
1876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    NumberFormat::operator=(other);
1886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    this->fCurrency          = other.fCurrency;
1906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    this->fLocale            = other.fLocale;
1916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    this->fLCID              = other.fLCID;
1926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    this->fFractionDigitsSet = other.fFractionDigitsSet;
1936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (fCurrency) {
1956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        freeCurrencyFormat(&fFormatInfo->currency);
1966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        getCurrencyFormat(&fFormatInfo->currency, fLCID);
1976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
1986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        freeNumberFormat(&fFormatInfo->number);
1996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        getNumberFormat(&fFormatInfo->number, fLCID);
2006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return *this;
2036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgFormat *Win32NumberFormat::clone(void) const
2066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
2076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return new Win32NumberFormat(*this);
2086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUnicodeString& Win32NumberFormat::format(double number, UnicodeString& appendTo, FieldPosition& pos) const
2116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
2126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return format(getMaximumFractionDigits(), appendTo, L"%.16f", number);
2136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUnicodeString& Win32NumberFormat::format(int32_t number, UnicodeString& appendTo, FieldPosition& pos) const
2166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
2176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return format(getMinimumFractionDigits(), appendTo, L"%I32d", number);
2186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUnicodeString& Win32NumberFormat::format(int64_t number, UnicodeString& appendTo, FieldPosition& pos) const
2216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
2226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return format(getMinimumFractionDigits(), appendTo, L"%I64d", number);
2236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid Win32NumberFormat::parse(const UnicodeString& text, Formattable& result, ParsePosition& parsePosition) const
2266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
2276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UErrorCode status = U_ZERO_ERROR;
2286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    NumberFormat *nf = fCurrency? NumberFormat::createCurrencyInstance(fLocale, status) : NumberFormat::createInstance(fLocale, status);
2296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    nf->parse(text, result, parsePosition);
2316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    delete nf;
2326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid Win32NumberFormat::setMaximumFractionDigits(int32_t newValue)
2346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
2356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fFractionDigitsSet = TRUE;
2366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    NumberFormat::setMaximumFractionDigits(newValue);
2376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid Win32NumberFormat::setMinimumFractionDigits(int32_t newValue)
2406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
2416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fFractionDigitsSet = TRUE;
2426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    NumberFormat::setMinimumFractionDigits(newValue);
2436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
245a4ce5bf56788dbb4835a5ef6143384266bbff5f5jshin@chromium.orgUnicodeString &Win32NumberFormat::format(int32_t numDigits, UnicodeString &appendTo, const wchar_t *fmt, ...) const
2466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
2476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    wchar_t nStackBuffer[STACK_BUFFER_SIZE];
2486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    wchar_t *nBuffer = nStackBuffer;
2496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    va_list args;
2506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int result;
2516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    nBuffer[0] = 0x0000;
2536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* Due to the arguments causing a result to be <= 23 characters (+2 for NULL and minus),
2556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    we don't need to reallocate the buffer. */
2566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    va_start(args, fmt);
2576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    result = _vsnwprintf(nBuffer, STACK_BUFFER_SIZE, fmt, args);
2586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    va_end(args);
2596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* Just to make sure of the above statement, we add this assert */
2616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    U_ASSERT(result >=0);
2626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // The following code is not used because _vscwprintf isn't available on MinGW at the moment.
2636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*if (result < 0) {
2646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int newLength;
2656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        va_start(args, fmt);
2676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        newLength = _vscwprintf(fmt, args);
2686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        va_end(args);
2696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        nBuffer = NEW_ARRAY(UChar, newLength + 1);
2716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        va_start(args, fmt);
2736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        result = _vsnwprintf(nBuffer, newLength + 1, fmt, args);
2746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        va_end(args);
2756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }*/
2766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // vswprintf is sensitive to the locale set by setlocale. For some locales
2786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // it doesn't use "." as the decimal separator, which is what GetNumberFormatW
2796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // and GetCurrencyFormatW both expect to see.
2806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    //
2816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // To fix this, we scan over the string and replace the first non-digits, except
2826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // for a leading "-", with a "."
2836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    //
2846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Note: (nBuffer[0] == L'-') will evaluate to 1 if there is a leading '-' in the
2856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // number, and 0 otherwise.
2866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for (wchar_t *p = &nBuffer[nBuffer[0] == L'-']; *p != L'\0'; p += 1) {
2876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (*p < L'0' || *p > L'9') {
2886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *p = L'.';
2896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
2906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar stackBuffer[STACK_BUFFER_SIZE];
2946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar *buffer = stackBuffer;
2956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    FormatInfo formatInfo;
2966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    formatInfo = *fFormatInfo;
2986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    buffer[0] = 0x0000;
2996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (fCurrency) {
3016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (fFractionDigitsSet) {
3026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            formatInfo.currency.NumDigits = (UINT) numDigits;
3036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (!isGroupingUsed()) {
3066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            formatInfo.currency.Grouping = 0;
3076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        result = GetCurrencyFormatW(fLCID, 0, nBuffer, &formatInfo.currency, buffer, STACK_BUFFER_SIZE);
3106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (result == 0) {
3126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            DWORD lastError = GetLastError();
3136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (lastError == ERROR_INSUFFICIENT_BUFFER) {
3156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                int newLength = GetCurrencyFormatW(fLCID, 0, nBuffer, &formatInfo.currency, NULL, 0);
3166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                buffer = NEW_ARRAY(UChar, newLength);
3186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                buffer[0] = 0x0000;
3196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                GetCurrencyFormatW(fLCID, 0, nBuffer,  &formatInfo.currency, buffer, newLength);
3206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
3216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
3236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (fFractionDigitsSet) {
3246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            formatInfo.number.NumDigits = (UINT) numDigits;
3256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (!isGroupingUsed()) {
3286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            formatInfo.number.Grouping = 0;
3296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        result = GetNumberFormatW(fLCID, 0, nBuffer, &formatInfo.number, buffer, STACK_BUFFER_SIZE);
3326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (result == 0) {
3346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
3356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                int newLength = GetNumberFormatW(fLCID, 0, nBuffer, &formatInfo.number, NULL, 0);
3366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                buffer = NEW_ARRAY(UChar, newLength);
3386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                buffer[0] = 0x0000;
3396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                GetNumberFormatW(fLCID, 0, nBuffer, &formatInfo.number, buffer, newLength);
3406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
3416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
3426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    appendTo.append(buffer, (int32_t) wcslen(buffer));
3456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (buffer != stackBuffer) {
3476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        DELETE_ARRAY(buffer);
3486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*if (nBuffer != nStackBuffer) {
3516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        DELETE_ARRAY(nBuffer);
3526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }*/
3536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return appendTo;
3556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_NAMESPACE_END
3586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif /* #if !UCONFIG_NO_FORMATTING */
3606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif // U_PLATFORM_USES_ONLY_WIN32_API
362