~ubuntu-branches/ubuntu/raring/qtwebkit-source/raring-proposed

« back to all changes in this revision

Viewing changes to Source/WebCore/platform/text/win/LocaleWin.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-02-18 14:24:18 UTC
  • Revision ID: package-import@ubuntu.com-20130218142418-eon0jmjg3nj438uy
Tags: upstream-2.3
ImportĀ upstreamĀ versionĀ 2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2012 Google Inc. All rights reserved.
 
3
 *
 
4
 * Redistribution and use in source and binary forms, with or without
 
5
 * modification, are permitted provided that the following conditions are
 
6
 * met:
 
7
 *
 
8
 *     * Redistributions of source code must retain the above copyright
 
9
 * notice, this list of conditions and the following disclaimer.
 
10
 *     * Redistributions in binary form must reproduce the above
 
11
 * copyright notice, this list of conditions and the following disclaimer
 
12
 * in the documentation and/or other materials provided with the
 
13
 * distribution.
 
14
 *     * Neither the name of Google Inc. nor the names of its
 
15
 * contributors may be used to endorse or promote products derived from
 
16
 * this software without specific prior written permission.
 
17
 *
 
18
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
19
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
20
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
21
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 
22
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
23
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
24
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
25
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
26
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
27
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
28
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
29
 */
 
30
 
 
31
#include "config.h"
 
32
#include "LocaleWin.h"
 
33
 
 
34
#include "DateComponents.h"
 
35
#include "DateTimeFormat.h"
 
36
#include "Language.h"
 
37
#include "LocalizedStrings.h"
 
38
#include <limits>
 
39
#include <windows.h>
 
40
#include <wtf/CurrentTime.h>
 
41
#include <wtf/DateMath.h>
 
42
#include <wtf/OwnPtr.h>
 
43
#include <wtf/PassOwnPtr.h>
 
44
#include <wtf/text/StringBuilder.h>
 
45
 
 
46
using namespace std;
 
47
 
 
48
namespace WebCore {
 
49
 
 
50
typedef LCID (WINAPI* LocaleNameToLCIDPtr)(LPCWSTR, DWORD);
 
51
 
 
52
static String extractLanguageCode(const String& locale)
 
53
{
 
54
    size_t dashPosition = locale.find('-');
 
55
    if (dashPosition == notFound)
 
56
        return locale;
 
57
    return locale.left(dashPosition);
 
58
}
 
59
 
 
60
static LCID LCIDFromLocaleInternal(LCID userDefaultLCID, const String& userDefaultLanguageCode, LocaleNameToLCIDPtr localeNameToLCID, String& locale)
 
61
{
 
62
    String localeLanguageCode = extractLanguageCode(locale);
 
63
    if (equalIgnoringCase(localeLanguageCode, userDefaultLanguageCode))
 
64
        return userDefaultLCID;
 
65
    return localeNameToLCID(locale.charactersWithNullTermination(), 0);
 
66
}
 
67
 
 
68
static LCID LCIDFromLocale(const AtomicString& locale)
 
69
{
 
70
    // LocaleNameToLCID() is available since Windows Vista.
 
71
    LocaleNameToLCIDPtr localeNameToLCID = reinterpret_cast<LocaleNameToLCIDPtr>(::GetProcAddress(::GetModuleHandle(L"kernel32"), "LocaleNameToLCID"));
 
72
    if (!localeNameToLCID)
 
73
        return LOCALE_USER_DEFAULT;
 
74
 
 
75
    // According to MSDN, 9 is enough for LOCALE_SISO639LANGNAME.
 
76
    const size_t languageCodeBufferSize = 9;
 
77
    WCHAR lowercaseLanguageCode[languageCodeBufferSize];
 
78
    ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, lowercaseLanguageCode, languageCodeBufferSize);
 
79
    String userDefaultLanguageCode = String(lowercaseLanguageCode);
 
80
 
 
81
    LCID lcid = LCIDFromLocaleInternal(LOCALE_USER_DEFAULT, userDefaultLanguageCode, localeNameToLCID, String(locale));
 
82
    if (!lcid)
 
83
        lcid = LCIDFromLocaleInternal(LOCALE_USER_DEFAULT, userDefaultLanguageCode, localeNameToLCID, defaultLanguage());
 
84
    return lcid;
 
85
}
 
86
 
 
87
PassOwnPtr<Locale> Locale::create(const AtomicString& locale)
 
88
{
 
89
    return LocaleWin::create(LCIDFromLocale(locale));
 
90
}
 
91
 
 
92
inline LocaleWin::LocaleWin(LCID lcid)
 
93
    : m_lcid(lcid)
 
94
    , m_didInitializeNumberData(false)
 
95
{
 
96
#if ENABLE(CALENDAR_PICKER)
 
97
    DWORD value = 0;
 
98
    getLocaleInfo(LOCALE_IFIRSTDAYOFWEEK, value);
 
99
    // 0:Monday, ..., 6:Sunday.
 
100
    // We need 1 for Monday, 0 for Sunday.
 
101
    m_firstDayOfWeek = (value + 1) % 7;
 
102
#endif
 
103
}
 
104
 
 
105
PassOwnPtr<LocaleWin> LocaleWin::create(LCID lcid)
 
106
{
 
107
    return adoptPtr(new LocaleWin(lcid));
 
108
}
 
109
 
 
110
LocaleWin::~LocaleWin()
 
111
{
 
112
}
 
113
 
 
114
String LocaleWin::getLocaleInfoString(LCTYPE type)
 
115
{
 
116
    int bufferSizeWithNUL = ::GetLocaleInfo(m_lcid, type, 0, 0);
 
117
    if (bufferSizeWithNUL <= 0)
 
118
        return String();
 
119
    Vector<UChar> buffer(bufferSizeWithNUL);
 
120
    ::GetLocaleInfo(m_lcid, type, buffer.data(), bufferSizeWithNUL);
 
121
    buffer.shrink(bufferSizeWithNUL - 1);
 
122
    return String::adopt(buffer);
 
123
}
 
124
 
 
125
void LocaleWin::getLocaleInfo(LCTYPE type, DWORD& result)
 
126
{
 
127
    ::GetLocaleInfo(m_lcid, type | LOCALE_RETURN_NUMBER, reinterpret_cast<LPWSTR>(&result), sizeof(DWORD) / sizeof(TCHAR));
 
128
}
 
129
 
 
130
void LocaleWin::ensureShortMonthLabels()
 
131
{
 
132
    if (!m_shortMonthLabels.isEmpty())
 
133
        return;
 
134
    const LCTYPE types[12] = {
 
135
        LOCALE_SABBREVMONTHNAME1,
 
136
        LOCALE_SABBREVMONTHNAME2,
 
137
        LOCALE_SABBREVMONTHNAME3,
 
138
        LOCALE_SABBREVMONTHNAME4,
 
139
        LOCALE_SABBREVMONTHNAME5,
 
140
        LOCALE_SABBREVMONTHNAME6,
 
141
        LOCALE_SABBREVMONTHNAME7,
 
142
        LOCALE_SABBREVMONTHNAME8,
 
143
        LOCALE_SABBREVMONTHNAME9,
 
144
        LOCALE_SABBREVMONTHNAME10,
 
145
        LOCALE_SABBREVMONTHNAME11,
 
146
        LOCALE_SABBREVMONTHNAME12,
 
147
    };
 
148
    m_shortMonthLabels.reserveCapacity(WTF_ARRAY_LENGTH(types));
 
149
    for (unsigned i = 0; i < WTF_ARRAY_LENGTH(types); ++i) {
 
150
        m_shortMonthLabels.append(getLocaleInfoString(types[i]));
 
151
        if (m_shortMonthLabels.last().isEmpty()) {
 
152
            m_shortMonthLabels.shrink(0);
 
153
            m_shortMonthLabels.reserveCapacity(WTF_ARRAY_LENGTH(WTF::monthName));
 
154
            for (unsigned m = 0; m < WTF_ARRAY_LENGTH(WTF::monthName); ++m)
 
155
                m_shortMonthLabels.append(WTF::monthName[m]);
 
156
            return;
 
157
        }
 
158
    }
 
159
}
 
160
 
 
161
// -------------------------------- Tokenized date format
 
162
 
 
163
static unsigned countContinuousLetters(const String& format, unsigned index)
 
164
{
 
165
    unsigned count = 1;
 
166
    UChar reference = format[index];
 
167
    while (index + 1 < format.length()) {
 
168
        if (format[++index] != reference)
 
169
            break;
 
170
        ++count;
 
171
    }
 
172
    return count;
 
173
}
 
174
 
 
175
static void commitLiteralToken(StringBuilder& literalBuffer, StringBuilder& converted)
 
176
{
 
177
    if (literalBuffer.length() <= 0)
 
178
        return;
 
179
    DateTimeFormat::quoteAndAppendLiteral(literalBuffer.toString(), converted);
 
180
    literalBuffer.clear();
 
181
}
 
182
 
 
183
// This function converts Windows date/time pattern format [1][2] into LDML date
 
184
// format pattern [3].
 
185
//
 
186
// i.e.
 
187
//   We set h, H, m, s, d, dd, M, or y as is. They have same meaning in both of
 
188
//   Windows and LDML.
 
189
//   We need to convert the following patterns:
 
190
//     t -> a
 
191
//     tt -> a
 
192
//     ddd -> EEE
 
193
//     dddd -> EEEE
 
194
//     g -> G
 
195
//     gg -> ignore
 
196
//
 
197
// [1] http://msdn.microsoft.com/en-us/library/dd317787(v=vs.85).aspx
 
198
// [2] http://msdn.microsoft.com/en-us/library/dd318148(v=vs.85).aspx
 
199
// [3] LDML http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns
 
200
static String convertWindowsDateTimeFormat(const String& format)
 
201
{
 
202
    StringBuilder converted;
 
203
    StringBuilder literalBuffer;
 
204
    bool inQuote = false;
 
205
    bool lastQuoteCanBeLiteral = false;
 
206
    for (unsigned i = 0; i < format.length(); ++i) {
 
207
        UChar ch = format[i];
 
208
        if (inQuote) {
 
209
            if (ch == '\'') {
 
210
                inQuote = false;
 
211
                ASSERT(i);
 
212
                if (lastQuoteCanBeLiteral && format[i - 1] == '\'') {
 
213
                    literalBuffer.append('\'');
 
214
                    lastQuoteCanBeLiteral = false;
 
215
                } else
 
216
                    lastQuoteCanBeLiteral = true;
 
217
            } else
 
218
                literalBuffer.append(ch);
 
219
            continue;
 
220
        }
 
221
 
 
222
        if (ch == '\'') {
 
223
            inQuote = true;
 
224
            if (lastQuoteCanBeLiteral && i > 0 && format[i - 1] == '\'') {
 
225
                literalBuffer.append(ch);
 
226
                lastQuoteCanBeLiteral = false;
 
227
            } else
 
228
                lastQuoteCanBeLiteral = true;
 
229
        } else if (isASCIIAlpha(ch)) {
 
230
            commitLiteralToken(literalBuffer, converted);
 
231
            unsigned symbolStart = i;
 
232
            unsigned count = countContinuousLetters(format, i);
 
233
            i += count - 1;
 
234
            if (ch == 'h' || ch == 'H' || ch == 'm' || ch == 's' || ch == 'M' || ch == 'y')
 
235
                converted.append(format, symbolStart, count);
 
236
            else if (ch == 'd') {
 
237
                if (count <= 2)
 
238
                    converted.append(format, symbolStart, count);
 
239
                else if (count == 3)
 
240
                    converted.append("EEE");
 
241
                else
 
242
                    converted.append("EEEE");
 
243
            } else if (ch == 'g') {
 
244
                if (count == 1)
 
245
                    converted.append('G');
 
246
                else {
 
247
                    // gg means imperial era in Windows.
 
248
                    // Just ignore it.
 
249
                }
 
250
            } else if (ch == 't')
 
251
                converted.append('a');
 
252
            else
 
253
                literalBuffer.append(format, symbolStart, count);
 
254
        } else
 
255
            literalBuffer.append(ch);
 
256
    }
 
257
    commitLiteralToken(literalBuffer, converted);
 
258
    return converted.toString();
 
259
}
 
260
 
 
261
void LocaleWin::ensureMonthLabels()
 
262
{
 
263
    if (!m_monthLabels.isEmpty())
 
264
        return;
 
265
    const LCTYPE types[12] = {
 
266
        LOCALE_SMONTHNAME1,
 
267
        LOCALE_SMONTHNAME2,
 
268
        LOCALE_SMONTHNAME3,
 
269
        LOCALE_SMONTHNAME4,
 
270
        LOCALE_SMONTHNAME5,
 
271
        LOCALE_SMONTHNAME6,
 
272
        LOCALE_SMONTHNAME7,
 
273
        LOCALE_SMONTHNAME8,
 
274
        LOCALE_SMONTHNAME9,
 
275
        LOCALE_SMONTHNAME10,
 
276
        LOCALE_SMONTHNAME11,
 
277
        LOCALE_SMONTHNAME12,
 
278
    };
 
279
    m_monthLabels.reserveCapacity(WTF_ARRAY_LENGTH(types));
 
280
    for (unsigned i = 0; i < WTF_ARRAY_LENGTH(types); ++i) {
 
281
        m_monthLabels.append(getLocaleInfoString(types[i]));
 
282
        if (m_monthLabels.last().isEmpty()) {
 
283
            m_monthLabels.shrink(0);
 
284
            m_monthLabels.reserveCapacity(WTF_ARRAY_LENGTH(WTF::monthFullName));
 
285
            for (unsigned m = 0; m < WTF_ARRAY_LENGTH(WTF::monthFullName); ++m)
 
286
                m_monthLabels.append(WTF::monthFullName[m]);
 
287
            return;
 
288
        }
 
289
    }
 
290
}
 
291
 
 
292
void LocaleWin::ensureWeekDayShortLabels()
 
293
{
 
294
    if (!m_weekDayShortLabels.isEmpty())
 
295
        return;
 
296
    const LCTYPE types[7] = {
 
297
        LOCALE_SABBREVDAYNAME7, // Sunday
 
298
        LOCALE_SABBREVDAYNAME1, // Monday
 
299
        LOCALE_SABBREVDAYNAME2,
 
300
        LOCALE_SABBREVDAYNAME3,
 
301
        LOCALE_SABBREVDAYNAME4,
 
302
        LOCALE_SABBREVDAYNAME5,
 
303
        LOCALE_SABBREVDAYNAME6
 
304
    };
 
305
    m_weekDayShortLabels.reserveCapacity(WTF_ARRAY_LENGTH(types));
 
306
    for (unsigned i = 0; i < WTF_ARRAY_LENGTH(types); ++i) {
 
307
        m_weekDayShortLabels.append(getLocaleInfoString(types[i]));
 
308
        if (m_weekDayShortLabels.last().isEmpty()) {
 
309
            m_weekDayShortLabels.shrink(0);
 
310
            m_weekDayShortLabels.reserveCapacity(WTF_ARRAY_LENGTH(WTF::weekdayName));
 
311
            for (unsigned w = 0; w < WTF_ARRAY_LENGTH(WTF::weekdayName); ++w) {
 
312
                // weekdayName starts with Monday.
 
313
                m_weekDayShortLabels.append(WTF::weekdayName[(w + 6) % 7]);
 
314
            }
 
315
            return;
 
316
        }
 
317
    }
 
318
}
 
319
 
 
320
#if ENABLE(DATE_AND_TIME_INPUT_TYPES)
 
321
const Vector<String>& LocaleWin::monthLabels()
 
322
{
 
323
    ensureMonthLabels();
 
324
    return m_monthLabels;
 
325
}
 
326
#endif
 
327
 
 
328
#if ENABLE(CALENDAR_PICKER)
 
329
const Vector<String>& LocaleWin::weekDayShortLabels()
 
330
{
 
331
    ensureWeekDayShortLabels();
 
332
    return m_weekDayShortLabels;
 
333
}
 
334
 
 
335
unsigned LocaleWin::firstDayOfWeek()
 
336
{
 
337
    return m_firstDayOfWeek;
 
338
}
 
339
 
 
340
bool LocaleWin::isRTL()
 
341
{
 
342
    WTF::Unicode::Direction dir = WTF::Unicode::direction(monthLabels()[0][0]);
 
343
    return dir == WTF::Unicode::RightToLeft || dir == WTF::Unicode::RightToLeftArabic;
 
344
}
 
345
#endif
 
346
 
 
347
#if ENABLE(DATE_AND_TIME_INPUT_TYPES)
 
348
String LocaleWin::dateFormat()
 
349
{
 
350
    if (m_dateFormat.isNull())
 
351
        m_dateFormat = convertWindowsDateTimeFormat(getLocaleInfoString(LOCALE_SSHORTDATE));
 
352
    return m_dateFormat;
 
353
}
 
354
 
 
355
String LocaleWin::dateFormat(const String& windowsFormat)
 
356
{
 
357
    return convertWindowsDateTimeFormat(windowsFormat);
 
358
}
 
359
 
 
360
String LocaleWin::monthFormat()
 
361
{
 
362
    if (m_monthFormat.isNull())
 
363
        m_monthFormat = convertWindowsDateTimeFormat(getLocaleInfoString(LOCALE_SYEARMONTH));
 
364
    return m_monthFormat;
 
365
}
 
366
 
 
367
String LocaleWin::timeFormat()
 
368
{
 
369
    if (m_timeFormatWithSeconds.isNull())
 
370
        m_timeFormatWithSeconds = convertWindowsDateTimeFormat(getLocaleInfoString(LOCALE_STIMEFORMAT));
 
371
    return m_timeFormatWithSeconds;
 
372
}
 
373
 
 
374
String LocaleWin::shortTimeFormat()
 
375
{
 
376
    if (!m_timeFormatWithoutSeconds.isNull())
 
377
        return m_timeFormatWithoutSeconds;
 
378
    String format = getLocaleInfoString(LOCALE_SSHORTTIME);
 
379
    // Vista or older Windows doesn't support LOCALE_SSHORTTIME.
 
380
    if (format.isEmpty()) {
 
381
        format = getLocaleInfoString(LOCALE_STIMEFORMAT);
 
382
        StringBuilder builder;
 
383
        builder.append(getLocaleInfoString(LOCALE_STIME));
 
384
        builder.append("ss");
 
385
        size_t pos = format.reverseFind(builder.toString());
 
386
        if (pos != notFound)
 
387
            format.remove(pos, builder.length());
 
388
    }
 
389
    m_timeFormatWithoutSeconds = convertWindowsDateTimeFormat(format);
 
390
    return m_timeFormatWithoutSeconds;
 
391
}
 
392
 
 
393
String LocaleWin::dateTimeFormatWithSeconds()
 
394
{
 
395
    if (!m_dateTimeFormatWithSeconds.isNull())
 
396
        return m_dateTimeFormatWithSeconds;
 
397
    StringBuilder builder;
 
398
    builder.append(dateFormat());
 
399
    builder.append(' ');
 
400
    builder.append(timeFormat());
 
401
    m_dateTimeFormatWithSeconds = builder.toString();
 
402
    return m_dateTimeFormatWithSeconds;
 
403
}
 
404
 
 
405
String LocaleWin::dateTimeFormatWithoutSeconds()
 
406
{
 
407
    if (!m_dateTimeFormatWithoutSeconds.isNull())
 
408
        return m_dateTimeFormatWithoutSeconds;
 
409
    StringBuilder builder;
 
410
    builder.append(dateFormat());
 
411
    builder.append(' ');
 
412
    builder.append(shortTimeFormat());
 
413
    m_dateTimeFormatWithoutSeconds = builder.toString();
 
414
    return m_dateTimeFormatWithoutSeconds;
 
415
}
 
416
 
 
417
const Vector<String>& LocaleWin::shortMonthLabels()
 
418
{
 
419
    ensureShortMonthLabels();
 
420
    return m_shortMonthLabels;
 
421
}
 
422
 
 
423
const Vector<String>& LocaleWin::standAloneMonthLabels()
 
424
{
 
425
    // Windows doesn't provide a way to get stand-alone month labels.
 
426
    return monthLabels();
 
427
}
 
428
 
 
429
const Vector<String>& LocaleWin::shortStandAloneMonthLabels()
 
430
{
 
431
    // Windows doesn't provide a way to get stand-alone month labels.
 
432
    return shortMonthLabels();
 
433
}
 
434
 
 
435
const Vector<String>& LocaleWin::timeAMPMLabels()
 
436
{
 
437
    if (m_timeAMPMLabels.isEmpty()) {
 
438
        m_timeAMPMLabels.append(getLocaleInfoString(LOCALE_S1159));
 
439
        m_timeAMPMLabels.append(getLocaleInfoString(LOCALE_S2359));
 
440
    }
 
441
    return m_timeAMPMLabels;
 
442
}
 
443
#endif
 
444
 
 
445
void LocaleWin::initializeLocaleData()
 
446
{
 
447
    if (m_didInitializeNumberData)
 
448
        return;
 
449
 
 
450
    Vector<String, DecimalSymbolsSize> symbols;
 
451
    enum DigitSubstitution {
 
452
        DigitSubstitutionContext = 0,
 
453
        DigitSubstitution0to9 = 1,
 
454
        DigitSubstitutionNative = 2,
 
455
    };
 
456
    DWORD digitSubstitution = DigitSubstitution0to9;
 
457
    getLocaleInfo(LOCALE_IDIGITSUBSTITUTION, digitSubstitution);
 
458
    if (digitSubstitution == DigitSubstitution0to9) {
 
459
        symbols.append("0");
 
460
        symbols.append("1");
 
461
        symbols.append("2");
 
462
        symbols.append("3");
 
463
        symbols.append("4");
 
464
        symbols.append("5");
 
465
        symbols.append("6");
 
466
        symbols.append("7");
 
467
        symbols.append("8");
 
468
        symbols.append("9");
 
469
    } else {
 
470
        String digits = getLocaleInfoString(LOCALE_SNATIVEDIGITS);
 
471
        ASSERT(digits.length() >= 10);
 
472
        for (unsigned i = 0; i < 10; ++i)
 
473
            symbols.append(digits.substring(i, 1));
 
474
    }
 
475
    ASSERT(symbols.size() == DecimalSeparatorIndex);
 
476
    symbols.append(getLocaleInfoString(LOCALE_SDECIMAL));
 
477
    ASSERT(symbols.size() == GroupSeparatorIndex);
 
478
    symbols.append(getLocaleInfoString(LOCALE_STHOUSAND));
 
479
    ASSERT(symbols.size() == DecimalSymbolsSize);
 
480
 
 
481
    String negativeSign = getLocaleInfoString(LOCALE_SNEGATIVESIGN);
 
482
    enum NegativeFormat {
 
483
        NegativeFormatParenthesis = 0,
 
484
        NegativeFormatSignPrefix = 1,
 
485
        NegativeFormatSignSpacePrefix = 2,
 
486
        NegativeFormatSignSuffix = 3,
 
487
        NegativeFormatSpaceSignSuffix = 4,
 
488
    };
 
489
    DWORD negativeFormat = NegativeFormatSignPrefix;
 
490
    getLocaleInfo(LOCALE_INEGNUMBER, negativeFormat);
 
491
    String negativePrefix = emptyString();
 
492
    String negativeSuffix = emptyString();
 
493
    switch (negativeFormat) {
 
494
    case NegativeFormatParenthesis:
 
495
        negativePrefix = "(";
 
496
        negativeSuffix = ")";
 
497
        break;
 
498
    case NegativeFormatSignSpacePrefix:
 
499
        negativePrefix = negativeSign + " ";
 
500
        break;
 
501
    case NegativeFormatSignSuffix:
 
502
        negativeSuffix = negativeSign;
 
503
        break;
 
504
    case NegativeFormatSpaceSignSuffix:
 
505
        negativeSuffix = " " + negativeSign;
 
506
        break;
 
507
    case NegativeFormatSignPrefix: // Fall through.
 
508
    default:
 
509
        negativePrefix = negativeSign;
 
510
        break;
 
511
    }
 
512
    m_didInitializeNumberData = true;
 
513
    setLocaleData(symbols, emptyString(), emptyString(), negativePrefix, negativeSuffix);
 
514
}
 
515
 
 
516
}