build/stlport/src/c_locale_win32/c_locale_win32.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /*
michael@0 2 * Copyright (c) 1999
michael@0 3 * Silicon Graphics Computer Systems, Inc.
michael@0 4 *
michael@0 5 * Copyright (c) 1999
michael@0 6 * Boris Fomitchev
michael@0 7 *
michael@0 8 * Written 2000
michael@0 9 * Anton Lapach
michael@0 10 *
michael@0 11 * This material is provided "as is", with absolutely no warranty expressed
michael@0 12 * or implied. Any use is at your own risk.
michael@0 13 *
michael@0 14 * Permission to use or copy this software for any purpose is hereby granted
michael@0 15 * without fee, provided the above notices are retained on all copies.
michael@0 16 * Permission to modify the code and to distribute modified code is granted,
michael@0 17 * provided the above notices are retained, and a notice that the code was
michael@0 18 * modified is included with the above copyright notice.
michael@0 19 *
michael@0 20 */
michael@0 21
michael@0 22 #include <limits.h>
michael@0 23 #if defined (_STLP_MSVC) || defined (__ICL)
michael@0 24 # include <memory.h>
michael@0 25 #endif
michael@0 26 #include <string.h>
michael@0 27 #include <locale.h>
michael@0 28 #include <stdlib.h>
michael@0 29 #include <stdio.h>
michael@0 30
michael@0 31 #if defined (_STLP_USE_SAFE_STRING_FUNCTIONS)
michael@0 32 # define _STLP_STRCPY(D, DS, S) strcpy_s(D, DS, S)
michael@0 33 # define _STLP_STRNCPY(D, DS, S, C) strncpy_s(D, DS, S, C)
michael@0 34 # define _STLP_STRCAT(D, DS, S) strcat_s(D, DS, S)
michael@0 35 #else
michael@0 36 # define _STLP_STRCPY(D, DS, S) strcpy(D, S)
michael@0 37 # define _STLP_STRNCPY(D, DS, S, C) strncpy(D, S, C)
michael@0 38 # define _STLP_STRCAT(D, DS, S) strcat(D, S)
michael@0 39 #endif
michael@0 40
michael@0 41 #if defined (__cplusplus)
michael@0 42 extern "C" {
michael@0 43 #endif
michael@0 44
michael@0 45 /* Framework functions */
michael@0 46 /*
michael@0 47 locale :: "lang[_country[.code_page]]"
michael@0 48 | ".code_page"
michael@0 49 | ""
michael@0 50 | NULL
michael@0 51
michael@0 52 */
michael@0 53
michael@0 54 typedef struct _LOCALECONV {
michael@0 55 const char* name;
michael@0 56 const char* abbrev;
michael@0 57 } LOCALECONV;
michael@0 58
michael@0 59 #define MAX_LANG_LEN 64 /* max language name length */
michael@0 60 #define MAX_CTRY_LEN 64 /* max country name length */
michael@0 61 #define MAX_MODIFIER_LEN 0 /* max modifier name length - n/a */
michael@0 62 #define MAX_LC_LEN (MAX_LANG_LEN+MAX_CTRY_LEN+MAX_MODIFIER_LEN+3)
michael@0 63 /* max entire locale string length */
michael@0 64 #define MAX_CP_LEN 5 /* max code page name length */
michael@0 65
michael@0 66 #if !defined (LANG_INVARIANT)
michael@0 67 # define LANG_INVARIANT 0x7f
michael@0 68 # define _STLP_LANG_INVARIANT_DEFINED
michael@0 69 #endif
michael@0 70
michael@0 71 #ifndef CP_UTF7
michael@0 72 # define CP_UTF7 65000
michael@0 73 #endif
michael@0 74
michael@0 75 #ifndef CP_UTF8
michael@0 76 # define CP_UTF8 65001
michael@0 77 #endif
michael@0 78
michael@0 79 #define INVARIANT_LCID MAKELCID(MAKELANGID(LANG_INVARIANT, SUBLANG_NEUTRAL), SORT_DEFAULT)
michael@0 80
michael@0 81 static const char *_C_name = "C";
michael@0 82
michael@0 83 /* non-NLS language string table */
michael@0 84 static LOCALECONV __rg_language[] = {
michael@0 85 {"american", "ENU"},
michael@0 86 {"american english", "ENU"},
michael@0 87 {"american-english", "ENU"},
michael@0 88 {"australian", "ENA"},
michael@0 89 {"belgian", "NLB"},
michael@0 90 {"canadian", "ENC"},
michael@0 91 {"chh", "ZHH"},
michael@0 92 {"chi", "ZHI"},
michael@0 93 {"chinese", "CHS"},
michael@0 94 {"chinese-hongkong", "ZHH"},
michael@0 95 {"chinese-simplified", "CHS"},
michael@0 96 {"chinese-singapore", "ZHI"},
michael@0 97 {"chinese-traditional", "CHT"},
michael@0 98 {"dutch-belgian", "NLB"},
michael@0 99 {"english-american", "ENU"},
michael@0 100 {"english-aus", "ENA"},
michael@0 101 {"english-belize", "ENL"},
michael@0 102 {"english-can", "ENC"},
michael@0 103 {"english-caribbean", "ENB"},
michael@0 104 {"english-ire", "ENI"},
michael@0 105 {"english-jamaica", "ENJ"},
michael@0 106 {"english-nz", "ENZ"},
michael@0 107 {"english-south africa", "ENS"},
michael@0 108 {"english-trinidad y tobago", "ENT"},
michael@0 109 {"english-uk", "ENG"},
michael@0 110 {"english-us", "ENU"},
michael@0 111 {"english-usa", "ENU"},
michael@0 112 {"french-belgian", "FRB"},
michael@0 113 {"french-canadian", "FRC"},
michael@0 114 {"french-luxembourg", "FRL"},
michael@0 115 {"french-swiss", "FRS"},
michael@0 116 {"german-austrian", "DEA"},
michael@0 117 {"german-lichtenstein", "DEC"},
michael@0 118 {"german-luxembourg", "DEL"},
michael@0 119 {"german-swiss", "DES"},
michael@0 120 {"irish-english", "ENI"},
michael@0 121 {"italian-swiss", "ITS"},
michael@0 122 {"norwegian", "NOR"},
michael@0 123 {"norwegian-bokmal", "NOR"},
michael@0 124 {"norwegian-nynorsk", "NON"},
michael@0 125 {"portuguese-brazilian", "PTB"},
michael@0 126 {"spanish-argentina", "ESS"},
michael@0 127 {"spanish-bolivia", "ESB"},
michael@0 128 {"spanish-chile", "ESL"},
michael@0 129 {"spanish-colombia", "ESO"},
michael@0 130 {"spanish-costa rica", "ESC"},
michael@0 131 {"spanish-dominican republic", "ESD"},
michael@0 132 {"spanish-ecuador", "ESF"},
michael@0 133 {"spanish-el salvador", "ESE"},
michael@0 134 {"spanish-guatemala", "ESG"},
michael@0 135 {"spanish-honduras", "ESH"},
michael@0 136 {"spanish-mexican", "ESM"},
michael@0 137 {"spanish-modern", "ESN"},
michael@0 138 {"spanish-nicaragua", "ESI"},
michael@0 139 {"spanish-panama", "ESA"},
michael@0 140 {"spanish-paraguay", "ESZ"},
michael@0 141 {"spanish-peru", "ESR"},
michael@0 142 {"spanish-puerto rico", "ESU"},
michael@0 143 {"spanish-uruguay", "ESY"},
michael@0 144 {"spanish-venezuela", "ESV"},
michael@0 145 {"swedish-finland", "SVF"},
michael@0 146 {"swiss", "DES"},
michael@0 147 {"uk", "ENG"},
michael@0 148 {"us", "ENU"},
michael@0 149 {"usa", "ENU"}
michael@0 150 };
michael@0 151
michael@0 152 /* non-NLS country string table */
michael@0 153 static LOCALECONV __rg_country[] = {
michael@0 154 {"america", "USA"},
michael@0 155 {"britain", "GBR"},
michael@0 156 {"china", "CHN"},
michael@0 157 {"czech", "CZE"},
michael@0 158 {"england", "GBR"},
michael@0 159 {"great britain", "GBR"},
michael@0 160 {"holland", "NLD"},
michael@0 161 {"hong-kong", "HKG"},
michael@0 162 {"new-zealand", "NZL"},
michael@0 163 {"nz", "NZL"},
michael@0 164 {"pr china", "CHN"},
michael@0 165 {"pr-china", "CHN"},
michael@0 166 {"puerto-rico", "PRI"},
michael@0 167 {"slovak", "SVK"},
michael@0 168 {"south africa", "ZAF"},
michael@0 169 {"south korea", "KOR"},
michael@0 170 {"south-africa", "ZAF"},
michael@0 171 {"south-korea", "KOR"},
michael@0 172 {"trinidad & tobago", "TTO"},
michael@0 173 {"uk", "GBR"},
michael@0 174 {"united-kingdom", "GBR"},
michael@0 175 {"united-states", "USA"},
michael@0 176 {"us", "USA"},
michael@0 177 };
michael@0 178
michael@0 179 typedef struct _Locale_name_hint {
michael@0 180 LCID id;
michael@0 181 } _Locale_lcid_t;
michael@0 182
michael@0 183 typedef struct _Locale_ctype {
michael@0 184 _Locale_lcid_t lc;
michael@0 185 UINT cp;
michael@0 186 unsigned short ctable[256];
michael@0 187 } _Locale_ctype_t;
michael@0 188
michael@0 189 typedef struct _Locale_numeric {
michael@0 190 _Locale_lcid_t lc;
michael@0 191 char cp[MAX_CP_LEN + 1];
michael@0 192 char decimal_point[4];
michael@0 193 char thousands_sep[4];
michael@0 194 char *grouping;
michael@0 195 } _Locale_numeric_t;
michael@0 196
michael@0 197 typedef struct _Locale_time {
michael@0 198 _Locale_lcid_t lc;
michael@0 199 char cp[MAX_CP_LEN + 1];
michael@0 200 char *month[12];
michael@0 201 char *abbrev_month[12];
michael@0 202 char *dayofweek[7];
michael@0 203 char *abbrev_dayofweek[7];
michael@0 204 char *date_time_format;
michael@0 205 char *long_date_time_format;
michael@0 206 char *date_format;
michael@0 207 char *long_date_format;
michael@0 208 char *time_format;
michael@0 209 char am[9];
michael@0 210 char pm[9];
michael@0 211 } _Locale_time_t;
michael@0 212
michael@0 213 typedef struct _Locale_collate {
michael@0 214 _Locale_lcid_t lc;
michael@0 215 char cp[MAX_CP_LEN + 1];
michael@0 216 } _Locale_collate_t;
michael@0 217
michael@0 218 typedef struct _Locale_monetary {
michael@0 219 _Locale_lcid_t lc;
michael@0 220 char cp[MAX_CP_LEN + 1];
michael@0 221 char decimal_point[4];
michael@0 222 char thousands_sep[4];
michael@0 223 char *grouping;
michael@0 224 char int_curr_symbol[5]; /* 3 + 1 + 1 */
michael@0 225 char curr_symbol[6];
michael@0 226 char negative_sign[5];
michael@0 227 char positive_sign[5];
michael@0 228 int frac_digits;
michael@0 229 int int_frac_digits;
michael@0 230 } _Locale_monetary_t;
michael@0 231
michael@0 232 /* Internal function */
michael@0 233 static void __FixGrouping(char *grouping);
michael@0 234 static const char* __ConvertName(const char* lname, LOCALECONV* ConvTable, int TableSize);
michael@0 235 static int __ParseLocaleString(const char* lname, char* lang, char* ctry, char* page);
michael@0 236 static int __GetLCID(const char* lang, const char* ctry, LCID* lcid);
michael@0 237 static int __GetLCIDFromName(const char* lname, LCID* lcid, char *cp, _Locale_lcid_t *hint);
michael@0 238 static char const* __GetLocaleName(LCID lcid, const char* cp, char* buf);
michael@0 239 static char const* __Extract_locale_name(const char* loc, const char* category, char* buf);
michael@0 240 static char const* __TranslateToSystem(const char* lname, char* buf, _Locale_lcid_t* hint, int *__err_code);
michael@0 241 static void __GetLocaleInfoUsingACP(LCID lcid, const char* cp, LCTYPE lctype, char* buf, int buf_size, wchar_t* wbuf, int wbuf_size);
michael@0 242 static int __intGetACP(LCID lcid);
michael@0 243 static int __intGetOCP(LCID lcid);
michael@0 244 static int __GetDefaultCP(LCID lcid);
michael@0 245 static char* __ConvertToCP(int from_cp, int to_cp, const char *from, size_t size, size_t *ret_buf_size);
michael@0 246 static void my_ltoa(long __x, char* buf);
michael@0 247
michael@0 248 void my_ltoa(long __x, char* buf) {
michael@0 249 char rbuf[64];
michael@0 250 char* ptr = rbuf;
michael@0 251
michael@0 252 if (__x == 0)
michael@0 253 *ptr++ = '0';
michael@0 254 else {
michael@0 255 for (; __x != 0; __x /= 10)
michael@0 256 *ptr++ = (char)(__x % 10) + '0';
michael@0 257 }
michael@0 258 while(ptr > rbuf) *buf++ = *--ptr;
michael@0 259 /* psw */
michael@0 260 *buf = '\0';
michael@0 261 }
michael@0 262
michael@0 263 #if defined (__cplusplus)
michael@0 264 _STLP_BEGIN_NAMESPACE
michael@0 265 extern "C" {
michael@0 266 #endif
michael@0 267
michael@0 268 _Locale_lcid_t* _Locale_get_ctype_hint(_Locale_ctype_t* ltype)
michael@0 269 { return (ltype != 0) ? &ltype->lc : 0; }
michael@0 270 _Locale_lcid_t* _Locale_get_numeric_hint(_Locale_numeric_t* lnumeric)
michael@0 271 { return (lnumeric != 0) ? &lnumeric->lc : 0; }
michael@0 272 _Locale_lcid_t* _Locale_get_time_hint(_Locale_time_t* ltime)
michael@0 273 { return (ltime != 0) ? &ltime->lc : 0; }
michael@0 274 _Locale_lcid_t* _Locale_get_collate_hint(_Locale_collate_t* lcollate)
michael@0 275 { return (lcollate != 0) ? &lcollate->lc : 0; }
michael@0 276 _Locale_lcid_t* _Locale_get_monetary_hint(_Locale_monetary_t* lmonetary)
michael@0 277 { return (lmonetary != 0) ? &lmonetary->lc : 0; }
michael@0 278 _Locale_lcid_t* _Locale_get_messages_hint(struct _Locale_messages* lmessages) {
michael@0 279 _STLP_MARK_PARAMETER_AS_UNUSED(lmessages)
michael@0 280 return 0;
michael@0 281 }
michael@0 282
michael@0 283 #define MAP(x, y) if ((mask & x) != 0) ret |= (y)
michael@0 284 unsigned short MapCtypeMask(unsigned short mask) {
michael@0 285 unsigned short ret = 0;
michael@0 286 MAP(C1_UPPER, _Locale_UPPER | _Locale_PRINT);
michael@0 287 MAP(C1_LOWER, _Locale_LOWER | _Locale_PRINT);
michael@0 288 MAP(C1_DIGIT, _Locale_DIGIT | _Locale_PRINT);
michael@0 289 MAP(C1_SPACE, _Locale_SPACE | _Locale_PRINT);
michael@0 290 MAP(C1_PUNCT, _Locale_PUNCT | _Locale_PRINT);
michael@0 291 /* MAP(C1_BLANK, ?); */
michael@0 292 MAP(C1_XDIGIT, _Locale_XDIGIT | _Locale_PRINT);
michael@0 293 MAP(C1_ALPHA, _Locale_ALPHA | _Locale_PRINT);
michael@0 294 if ((mask & C1_CNTRL) != 0) { ret |= _Locale_CNTRL; ret &= ~_Locale_PRINT; }
michael@0 295 return ret;
michael@0 296 }
michael@0 297
michael@0 298 static void MapCtypeMasks(unsigned short *cur, unsigned short *end) {
michael@0 299 for (; cur != end; ++cur) {
michael@0 300 *cur = MapCtypeMask(*cur);
michael@0 301 }
michael@0 302 }
michael@0 303
michael@0 304 _Locale_ctype_t* _Locale_ctype_create(const char * name, _Locale_lcid_t* lc_hint, int *__err_code) {
michael@0 305 char cp_name[MAX_CP_LEN + 1];
michael@0 306 int NativeCP;
michael@0 307 unsigned char Buffer[256];
michael@0 308 unsigned char *ptr;
michael@0 309 CPINFO CPInfo;
michael@0 310 int i;
michael@0 311 wchar_t *wbuffer;
michael@0 312 int BufferSize;
michael@0 313
michael@0 314 _Locale_ctype_t *ltype = (_Locale_ctype_t*)malloc(sizeof(_Locale_ctype_t));
michael@0 315
michael@0 316 if (!ltype) { *__err_code = _STLP_LOC_NO_MEMORY; return ltype; }
michael@0 317 memset(ltype, 0, sizeof(_Locale_ctype_t));
michael@0 318
michael@0 319 if (__GetLCIDFromName(name, &ltype->lc.id, cp_name, lc_hint) == -1)
michael@0 320 { free(ltype); *__err_code = _STLP_LOC_UNKNOWN_NAME; return NULL; }
michael@0 321
michael@0 322 #if defined (__BORLANDC__)
michael@0 323 if ( ltype->lc.id == INVARIANT_LCID && name[0] == 'C' && name[1] == 0 )
michael@0 324 { ltype->lc.id = 0x409; }
michael@0 325 #endif
michael@0 326
michael@0 327 ltype->cp = atoi(cp_name);
michael@0 328
michael@0 329 NativeCP = __GetDefaultCP(ltype->lc.id);
michael@0 330
michael@0 331 /* Make table with all characters. */
michael@0 332 for (i = 0; i < 256; ++i) Buffer[i] = (unsigned char)i;
michael@0 333
michael@0 334 if (!GetCPInfo(NativeCP, &CPInfo)) { free(ltype); return NULL; }
michael@0 335
michael@0 336 if (CPInfo.MaxCharSize > 1) {
michael@0 337 for (ptr = (unsigned char*)CPInfo.LeadByte; *ptr && *(ptr + 1); ptr+=2)
michael@0 338 for (i = *ptr; i <= *(ptr + 1); ++i) Buffer[i] = 0;
michael@0 339 }
michael@0 340
michael@0 341 if ((UINT)NativeCP != ltype->cp) {
michael@0 342 OSVERSIONINFO ver_info;
michael@0 343 ver_info.dwOSVersionInfoSize = sizeof(ver_info);
michael@0 344 GetVersionEx(&ver_info);
michael@0 345 if (ver_info.dwPlatformId == VER_PLATFORM_WIN32_NT) {
michael@0 346 /* Convert character sequence to Unicode. */
michael@0 347 BufferSize = MultiByteToWideChar(ltype->cp, MB_PRECOMPOSED, (const char*)Buffer, 256, NULL, 0);
michael@0 348 if (!BufferSize) { free(ltype); *__err_code = _STLP_LOC_UNKNOWN_NAME; return NULL; }
michael@0 349 wbuffer = (wchar_t*)malloc(BufferSize * sizeof(wchar_t));
michael@0 350 if (!wbuffer) { free(ltype); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }
michael@0 351 MultiByteToWideChar(ltype->cp, MB_PRECOMPOSED, (const char*)Buffer, 256, wbuffer, BufferSize);
michael@0 352
michael@0 353 GetStringTypeW(CT_CTYPE1, wbuffer, 256, ltype->ctable);
michael@0 354 MapCtypeMasks(ltype->ctable, ltype->ctable + 256);
michael@0 355 free(wbuffer);
michael@0 356 }
michael@0 357 else {
michael@0 358 unsigned short ctable[256];
michael@0 359 unsigned char TargetBuffer[256];
michael@0 360 GetStringTypeA(ltype->lc.id, CT_CTYPE1, (const char*)Buffer, 256, ctable);
michael@0 361
michael@0 362 /* Convert character sequence to target code page. */
michael@0 363 BufferSize = MultiByteToWideChar(NativeCP, MB_PRECOMPOSED, (const char*)Buffer, 256, NULL, 0);
michael@0 364 if (!BufferSize) { free(ltype); *__err_code = _STLP_LOC_UNKNOWN_NAME; return NULL; }
michael@0 365 wbuffer = (wchar_t*)malloc(BufferSize * sizeof(wchar_t));
michael@0 366 if (!wbuffer) { free(ltype); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }
michael@0 367 MultiByteToWideChar(NativeCP, MB_PRECOMPOSED, (const char*)Buffer, 256, wbuffer, BufferSize);
michael@0 368 if (!WideCharToMultiByte(ltype->cp, WC_COMPOSITECHECK | WC_SEPCHARS, wbuffer, BufferSize, (char*)TargetBuffer, 256, NULL, FALSE))
michael@0 369 { free(wbuffer); free(ltype); *__err_code = _STLP_LOC_UNKNOWN_NAME; return NULL; }
michael@0 370
michael@0 371 free(wbuffer);
michael@0 372
michael@0 373 /* Translate ctype table. */
michael@0 374 for (i = 0; i < 256; ++i) {
michael@0 375 if (!TargetBuffer[i]) continue;
michael@0 376 ltype->ctable[TargetBuffer[i]] = MapCtypeMask(ctable[i]);
michael@0 377 }
michael@0 378 }
michael@0 379 }
michael@0 380 else {
michael@0 381 GetStringTypeA(ltype->lc.id, CT_CTYPE1, (const char*)Buffer, 256, ltype->ctable);
michael@0 382 MapCtypeMasks(ltype->ctable, ltype->ctable + 256);
michael@0 383 }
michael@0 384 return ltype;
michael@0 385 }
michael@0 386
michael@0 387 _Locale_numeric_t* _Locale_numeric_create(const char * name, _Locale_lcid_t* lc_hint, int *__err_code) {
michael@0 388 wchar_t wbuf[4];
michael@0 389 char *GroupingBuffer;
michael@0 390 int BufferSize;
michael@0 391
michael@0 392 _Locale_numeric_t *lnum = (_Locale_numeric_t*)malloc(sizeof(_Locale_numeric_t));
michael@0 393 if (!lnum) { *__err_code = _STLP_LOC_NO_MEMORY; return lnum; }
michael@0 394 memset(lnum, 0, sizeof(_Locale_numeric_t));
michael@0 395
michael@0 396 if (__GetLCIDFromName(name, &lnum->lc.id, lnum->cp, lc_hint) == -1)
michael@0 397 { free(lnum); *__err_code = _STLP_LOC_UNKNOWN_NAME; return NULL; }
michael@0 398
michael@0 399 #if defined (__BORLANDC__)
michael@0 400 if (lnum->lc.id != INVARIANT_LCID) {
michael@0 401 #endif
michael@0 402 __GetLocaleInfoUsingACP(lnum->lc.id, lnum->cp, LOCALE_SDECIMAL, lnum->decimal_point, 4, wbuf, 4);
michael@0 403 __GetLocaleInfoUsingACP(lnum->lc.id, lnum->cp, LOCALE_STHOUSAND, lnum->thousands_sep, 4, wbuf, 4);
michael@0 404 #if defined (__BORLANDC__)
michael@0 405 }
michael@0 406 else
michael@0 407 lnum->decimal_point[0] = '.';
michael@0 408 #endif
michael@0 409
michael@0 410 if (lnum->lc.id != INVARIANT_LCID) {
michael@0 411 BufferSize = GetLocaleInfoA(lnum->lc.id, LOCALE_SGROUPING, NULL, 0);
michael@0 412 GroupingBuffer = (char*)malloc(BufferSize);
michael@0 413 if (!GroupingBuffer) { free(lnum); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }
michael@0 414 GetLocaleInfoA(lnum->lc.id, LOCALE_SGROUPING, GroupingBuffer, BufferSize);
michael@0 415 __FixGrouping(GroupingBuffer);
michael@0 416 lnum->grouping = GroupingBuffer;
michael@0 417 }
michael@0 418 else {
michael@0 419 lnum->grouping = (char*)malloc(1);
michael@0 420 if (!lnum->grouping) { free(lnum); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }
michael@0 421 lnum->grouping[0] = 0;
michael@0 422 }
michael@0 423
michael@0 424 return lnum;
michael@0 425 }
michael@0 426
michael@0 427 static int __ConvertDate(const char *NTDate, char *buffer, int buf_size) {
michael@0 428 /* This function will return an incomplete buffer if buffer is not long enough */
michael@0 429 const char *cur_char;
michael@0 430 char *cur_output, *end_output;
michael@0 431
michael@0 432 /* Correct time format. */
michael@0 433 cur_char = NTDate;
michael@0 434 cur_output = buffer;
michael@0 435 end_output = cur_output + buf_size;
michael@0 436 buf_size = 0;
michael@0 437 while (*cur_char) {
michael@0 438 if (cur_output && (cur_output == end_output)) break;
michael@0 439 switch (*cur_char) {
michael@0 440 case 'd':
michael@0 441 {
michael@0 442 if (*(cur_char + 1) == 'd') {
michael@0 443 if (cur_output && (cur_output + 2 > end_output)) {
michael@0 444 *cur_output = 0;
michael@0 445 return ++buf_size;
michael@0 446 }
michael@0 447 if (*(cur_char + 2) == 'd') {
michael@0 448 if (*(cur_char + 3) == 'd') {
michael@0 449 if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = 'A'; }
michael@0 450 buf_size += 2;
michael@0 451 cur_char += 3;
michael@0 452 }
michael@0 453 else {
michael@0 454 if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = 'a'; }
michael@0 455 buf_size += 2;
michael@0 456 cur_char += 2;
michael@0 457 }
michael@0 458 }
michael@0 459 else {
michael@0 460 if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = 'd'; }
michael@0 461 buf_size += 2;
michael@0 462 cur_char++;
michael@0 463 }
michael@0 464 }
michael@0 465 else {
michael@0 466 if (cur_output && (cur_output + 3 > end_output)) {
michael@0 467 *cur_output = 0;
michael@0 468 return ++buf_size;
michael@0 469 }
michael@0 470 if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = '#'; *(cur_output++) = 'd'; }
michael@0 471 buf_size += 3;
michael@0 472 }
michael@0 473 }
michael@0 474 break;
michael@0 475 case 'M':
michael@0 476 {
michael@0 477 if (*(cur_char + 1) == 'M') {
michael@0 478 if (cur_output && (cur_output + 2 > end_output)) {
michael@0 479 *cur_output = 0;
michael@0 480 return ++buf_size;
michael@0 481 }
michael@0 482 if (*(cur_char + 2) == 'M') {
michael@0 483 if (*(cur_char + 3) == 'M') {
michael@0 484 if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = 'B'; }
michael@0 485 buf_size += 2;
michael@0 486 cur_char += 3;
michael@0 487 }
michael@0 488 else {
michael@0 489 if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = 'b'; }
michael@0 490 buf_size += 2;
michael@0 491 cur_char += 2;
michael@0 492 }
michael@0 493 }
michael@0 494 else {
michael@0 495 if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = 'm'; }
michael@0 496 buf_size += 2;
michael@0 497 cur_char++;
michael@0 498 }
michael@0 499 }
michael@0 500 else {
michael@0 501 if (cur_output && (cur_output + 3 > end_output)) {
michael@0 502 *cur_output = 0;
michael@0 503 return ++buf_size;
michael@0 504 }
michael@0 505 if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = '#'; *(cur_output++) = 'm'; }
michael@0 506 buf_size += 3;
michael@0 507 }
michael@0 508 }
michael@0 509 break;
michael@0 510 case 'y':
michael@0 511 {
michael@0 512 if (*(cur_char + 1) == 'y') {
michael@0 513 if (cur_output && (cur_output + 2 > end_output)) {
michael@0 514 *cur_output = 0;
michael@0 515 return ++buf_size;
michael@0 516 }
michael@0 517 if (*(cur_char + 2) == 'y' && *(cur_char + 3) == 'y') {
michael@0 518 if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = 'Y'; }
michael@0 519 buf_size += 2;
michael@0 520 cur_char += 3;
michael@0 521 }
michael@0 522 else {
michael@0 523 if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = 'y'; }
michael@0 524 buf_size += 2;
michael@0 525 cur_char++;
michael@0 526 }
michael@0 527 }
michael@0 528 else {
michael@0 529 if (cur_output && (cur_output + 3 > end_output)) {
michael@0 530 *cur_output = 0;
michael@0 531 return ++buf_size;
michael@0 532 }
michael@0 533 if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = '#'; *(cur_output++) = 'y'; }
michael@0 534 buf_size += 3;
michael@0 535 }
michael@0 536 }
michael@0 537 break;
michael@0 538 case '%':
michael@0 539 {
michael@0 540 if (cur_output && (cur_output + 2 > end_output)) {
michael@0 541 *cur_output = 0;
michael@0 542 return ++buf_size;
michael@0 543 }
michael@0 544 if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = '%'; }
michael@0 545 buf_size += 2;
michael@0 546 }
michael@0 547 break;
michael@0 548 case '\'':
michael@0 549 {
michael@0 550 ++cur_char;
michael@0 551 while (*cur_char != '\'' && *cur_char != 0 && (cur_output == NULL || cur_output != end_output)) {
michael@0 552 if (cur_output) { *cur_output++ = *cur_char; }
michael@0 553 ++cur_char;
michael@0 554 buf_size += 1;
michael@0 555 }
michael@0 556 }
michael@0 557 break;
michael@0 558 default:
michael@0 559 {
michael@0 560 if (cur_output) { *(cur_output++) = *cur_char; }
michael@0 561 buf_size += 1;
michael@0 562 }
michael@0 563 break;
michael@0 564 }
michael@0 565 if (*cur_char == 0) break;
michael@0 566 ++cur_char;
michael@0 567 }
michael@0 568
michael@0 569 if (!cur_output || cur_output != end_output) {
michael@0 570 if (cur_output) *cur_output = 0;
michael@0 571 buf_size += 1;
michael@0 572 }
michael@0 573 else {
michael@0 574 /* We trunc result */
michael@0 575 *(--cur_output) = 0;
michael@0 576 }
michael@0 577
michael@0 578 return buf_size;
michael@0 579 }
michael@0 580
michael@0 581 static int __ConvertTime(const char *NTTime, char *buffer, int buf_size) {
michael@0 582 const char *cur_char;
michael@0 583 char *cur_output, *end_output;
michael@0 584 cur_char = NTTime;
michael@0 585 cur_output = buffer;
michael@0 586 end_output = cur_output + buf_size;
michael@0 587 buf_size = 0;
michael@0 588 while (*cur_char) {
michael@0 589 switch(*cur_char) {
michael@0 590 case 'h':
michael@0 591 if (*(cur_char + 1) == 'h') {
michael@0 592 if (cur_output && (cur_output + 2 > end_output)) {
michael@0 593 *cur_output = 0;
michael@0 594 return ++buf_size;
michael@0 595 }
michael@0 596 if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = 'I'; }
michael@0 597 buf_size += 2;
michael@0 598 ++cur_char;
michael@0 599 }
michael@0 600 else {
michael@0 601 if (cur_output && (cur_output + 3 > end_output)) {
michael@0 602 *cur_output = 0;
michael@0 603 return ++buf_size;
michael@0 604 }
michael@0 605 if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = '#'; *(cur_output++) = 'I'; }
michael@0 606 buf_size += 3;
michael@0 607 }
michael@0 608 break;
michael@0 609 case 'H':
michael@0 610 if (*(cur_char + 1) == 'H') {
michael@0 611 if (cur_output && (cur_output + 2 > end_output)) {
michael@0 612 *cur_output = 0;
michael@0 613 return ++buf_size;
michael@0 614 }
michael@0 615 if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = 'H'; }
michael@0 616 buf_size += 2;
michael@0 617 ++cur_char;
michael@0 618 }
michael@0 619 else {
michael@0 620 if (cur_output && (cur_output + 3 > end_output)) {
michael@0 621 *cur_output = 0;
michael@0 622 return ++buf_size;
michael@0 623 }
michael@0 624 if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = '#'; *(cur_output++) = 'H'; }
michael@0 625 buf_size += 3;
michael@0 626 }
michael@0 627 break;
michael@0 628 case 'm':
michael@0 629 if (*(cur_char + 1) == 'm') {
michael@0 630 if (cur_output && (cur_output + 2 > end_output)) {
michael@0 631 *cur_output = 0;
michael@0 632 return ++buf_size;
michael@0 633 }
michael@0 634 if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = 'M'; }
michael@0 635 buf_size += 2;
michael@0 636 cur_char++;
michael@0 637 }
michael@0 638 else {
michael@0 639 if (cur_output && (cur_output + 3 > end_output)) {
michael@0 640 *cur_output = 0;
michael@0 641 return ++buf_size;
michael@0 642 }
michael@0 643 if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = '#'; *(cur_output++) = 'M'; }
michael@0 644 buf_size += 3;
michael@0 645 }
michael@0 646 break;
michael@0 647 case 's':
michael@0 648 if (*(cur_char + 1) == 's') {
michael@0 649 if (cur_output && (cur_output + 2 > end_output)) {
michael@0 650 *cur_output = 0;
michael@0 651 return ++buf_size;
michael@0 652 }
michael@0 653 if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = 'S'; }
michael@0 654 buf_size += 2;
michael@0 655 ++cur_char;
michael@0 656 }
michael@0 657 else {
michael@0 658 if (cur_output && (cur_output + 3 > end_output)) {
michael@0 659 *cur_output = 0;
michael@0 660 return ++buf_size;
michael@0 661 }
michael@0 662 if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = '#'; *(cur_output++) = 'S'; }
michael@0 663 buf_size += 3;
michael@0 664 }
michael@0 665 break;
michael@0 666 case 't':
michael@0 667 if (*(cur_char + 1) == 't')
michael@0 668 ++cur_char;
michael@0 669 if (cur_output && (cur_output + 2 > end_output)) {
michael@0 670 *cur_output = 0;
michael@0 671 return ++buf_size;
michael@0 672 }
michael@0 673 if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = 'p'; }
michael@0 674 buf_size += 2;
michael@0 675 break;
michael@0 676 case '%':
michael@0 677 if (cur_output && (cur_output + 2 > end_output)) {
michael@0 678 *cur_output = 0;
michael@0 679 return ++buf_size;
michael@0 680 }
michael@0 681 if (cur_output) { *(cur_output++)='%'; *(cur_output++)='%'; }
michael@0 682 buf_size += 2;
michael@0 683 break;
michael@0 684 case '\'':
michael@0 685 ++cur_char;
michael@0 686 while (*cur_char != '\'' && *cur_char != 0 && (!cur_output || (cur_output != end_output))) {
michael@0 687 if (cur_output) *cur_output++ = *cur_char;
michael@0 688 ++cur_char;
michael@0 689 buf_size += 1;
michael@0 690 }
michael@0 691 break;
michael@0 692 default:
michael@0 693 if (cur_output) { *(cur_output++) = *cur_char; }
michael@0 694 buf_size += 1;
michael@0 695 break;
michael@0 696 }
michael@0 697 if (*cur_char == 0) break;
michael@0 698 ++cur_char;
michael@0 699 }
michael@0 700
michael@0 701 if (!cur_output || cur_output != end_output) {
michael@0 702 if (cur_output) *cur_output = 0;
michael@0 703 buf_size += 1;
michael@0 704 }
michael@0 705 else {
michael@0 706 /* We trunc result */
michael@0 707 *(--cur_output) = 0;
michael@0 708 }
michael@0 709
michael@0 710 return buf_size;
michael@0 711 }
michael@0 712
michael@0 713 _Locale_time_t* _Locale_time_create(const char * name, _Locale_lcid_t* lc_hint, int *__err_code) {
michael@0 714 int size, month, dayofweek;
michael@0 715 size_t length;
michael@0 716 char fmt80[80];
michael@0 717 wchar_t wbuf80[80];
michael@0 718
michael@0 719 _Locale_time_t *ltime = (_Locale_time_t*)malloc(sizeof(_Locale_time_t));
michael@0 720
michael@0 721 if (!ltime) { *__err_code = _STLP_LOC_NO_MEMORY; return ltime; }
michael@0 722 memset(ltime, 0, sizeof(_Locale_time_t));
michael@0 723
michael@0 724 if (__GetLCIDFromName(name, &ltime->lc.id, ltime->cp, lc_hint) == -1)
michael@0 725 { free(ltime); *__err_code = _STLP_LOC_UNKNOWN_NAME; return NULL; }
michael@0 726
michael@0 727 #if defined (__BORLANDC__)
michael@0 728 if ( ltime->lc.id == INVARIANT_LCID && name[0] == 'C' && name[1] == 0 )
michael@0 729 { ltime->lc.id = 0x409; }
michael@0 730 #endif
michael@0 731
michael@0 732 for (month = LOCALE_SMONTHNAME1; month <= LOCALE_SMONTHNAME12; ++month) { /* Small hack :-) */
michael@0 733 size = GetLocaleInfoA(ltime->lc.id, month, NULL, 0);
michael@0 734 ltime->month[month - LOCALE_SMONTHNAME1] = (char*)malloc(size);
michael@0 735 if (!ltime->month[month - LOCALE_SMONTHNAME1])
michael@0 736 { _Locale_time_destroy(ltime); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }
michael@0 737 __GetLocaleInfoUsingACP(ltime->lc.id, ltime->cp, month, ltime->month[month - LOCALE_SMONTHNAME1], size, wbuf80, 80);
michael@0 738 }
michael@0 739
michael@0 740 for (month = LOCALE_SABBREVMONTHNAME1; month <= LOCALE_SABBREVMONTHNAME12; ++month) {
michael@0 741 size = GetLocaleInfoA(ltime->lc.id, month, NULL, 0);
michael@0 742 ltime->abbrev_month[month - LOCALE_SABBREVMONTHNAME1] = (char*)malloc(size);
michael@0 743 if (!ltime->abbrev_month[month - LOCALE_SABBREVMONTHNAME1])
michael@0 744 { _Locale_time_destroy(ltime); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }
michael@0 745 __GetLocaleInfoUsingACP(ltime->lc.id, ltime->cp, month, ltime->abbrev_month[month - LOCALE_SABBREVMONTHNAME1], size, wbuf80, 80);
michael@0 746 }
michael@0 747
michael@0 748 for (dayofweek = LOCALE_SDAYNAME1; dayofweek <= LOCALE_SDAYNAME7; ++dayofweek) {
michael@0 749 int dayindex = ( dayofweek != LOCALE_SDAYNAME7 ) ? dayofweek - LOCALE_SDAYNAME1 + 1 : 0;
michael@0 750 size = GetLocaleInfoA(ltime->lc.id, dayofweek, NULL, 0);
michael@0 751 ltime->dayofweek[dayindex] = (char*)malloc(size);
michael@0 752 if (!ltime->dayofweek[dayindex])
michael@0 753 { _Locale_time_destroy(ltime); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }
michael@0 754 __GetLocaleInfoUsingACP(ltime->lc.id, ltime->cp, dayofweek, ltime->dayofweek[dayindex], size, wbuf80, 80);
michael@0 755 }
michael@0 756
michael@0 757 for (dayofweek = LOCALE_SABBREVDAYNAME1; dayofweek <= LOCALE_SABBREVDAYNAME7; ++dayofweek) {
michael@0 758 int dayindex = ( dayofweek != LOCALE_SABBREVDAYNAME7 ) ? dayofweek - LOCALE_SABBREVDAYNAME1 + 1 : 0;
michael@0 759 size = GetLocaleInfoA(ltime->lc.id, dayofweek, NULL, 0);
michael@0 760 ltime->abbrev_dayofweek[dayindex] = (char*)malloc(size);
michael@0 761 if (!ltime->abbrev_dayofweek[dayindex])
michael@0 762 { _Locale_time_destroy(ltime); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }
michael@0 763 __GetLocaleInfoUsingACP(ltime->lc.id, ltime->cp, dayofweek, ltime->abbrev_dayofweek[dayindex], size, wbuf80, 80);
michael@0 764 }
michael@0 765
michael@0 766 __GetLocaleInfoUsingACP(ltime->lc.id, ltime->cp, LOCALE_SSHORTDATE, fmt80, 80, wbuf80, 80);
michael@0 767 size = __ConvertDate(fmt80, NULL, 0);
michael@0 768 ltime->date_format = (char*)malloc(size);
michael@0 769 if (!ltime->date_format)
michael@0 770 { _Locale_time_destroy(ltime); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }
michael@0 771 __ConvertDate(fmt80, ltime->date_format, size);
michael@0 772
michael@0 773 __GetLocaleInfoUsingACP(ltime->lc.id, ltime->cp, LOCALE_SLONGDATE, fmt80, 80, wbuf80, 80);
michael@0 774 size = __ConvertDate(fmt80, NULL, 0);
michael@0 775 ltime->long_date_format = (char*)malloc(size);
michael@0 776 if (!ltime->long_date_format)
michael@0 777 { _Locale_time_destroy(ltime);*__err_code = _STLP_LOC_NO_MEMORY; return NULL; }
michael@0 778 __ConvertDate(fmt80, ltime->long_date_format, size);
michael@0 779
michael@0 780 __GetLocaleInfoUsingACP(ltime->lc.id, ltime->cp, LOCALE_STIMEFORMAT, fmt80, 80, wbuf80, 80);
michael@0 781 size = __ConvertTime(fmt80, NULL, 0);
michael@0 782 ltime->time_format = (char*)malloc(size);
michael@0 783 if (!ltime->time_format)
michael@0 784 { _Locale_time_destroy(ltime); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }
michael@0 785 __ConvertTime(fmt80, ltime->time_format, size);
michael@0 786
michael@0 787 /* NT doesn't provide this information, we must simulate. */
michael@0 788 length = strlen(ltime->date_format) + strlen(ltime->time_format) + 1 /* space */ + 1 /* trailing 0 */;
michael@0 789 ltime->date_time_format = (char*)malloc(length);
michael@0 790 if (!ltime->date_time_format)
michael@0 791 { _Locale_time_destroy(ltime); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }
michael@0 792 _STLP_STRCPY(ltime->date_time_format, length, ltime->date_format);
michael@0 793 _STLP_STRCAT(ltime->date_time_format, length, " ");
michael@0 794 _STLP_STRCAT(ltime->date_time_format, length, ltime->time_format);
michael@0 795
michael@0 796 /* NT doesn't provide this information, we must simulate. */
michael@0 797 length = strlen(ltime->long_date_format) + strlen(ltime->time_format) + 1 /* space */ + 1 /* trailing 0 */;
michael@0 798 ltime->long_date_time_format = (char*)malloc(length);
michael@0 799 if (!ltime->long_date_time_format)
michael@0 800 { _Locale_time_destroy(ltime); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }
michael@0 801 _STLP_STRCPY(ltime->long_date_time_format, length, ltime->long_date_format);
michael@0 802 _STLP_STRCAT(ltime->long_date_time_format, length, " ");
michael@0 803 _STLP_STRCAT(ltime->long_date_time_format, length, ltime->time_format);
michael@0 804
michael@0 805 __GetLocaleInfoUsingACP(ltime->lc.id, ltime->cp, LOCALE_S1159, ltime->am, 9, wbuf80, 80);
michael@0 806 __GetLocaleInfoUsingACP(ltime->lc.id, ltime->cp, LOCALE_S2359, ltime->pm, 9, wbuf80, 80);
michael@0 807
michael@0 808 return ltime;
michael@0 809 }
michael@0 810
michael@0 811 _Locale_collate_t* _Locale_collate_create(const char * name, _Locale_lcid_t* lc_hint, int *__err_code) {
michael@0 812 _Locale_collate_t *lcol = (_Locale_collate_t*)malloc(sizeof(_Locale_collate_t));
michael@0 813 if (!lcol) { *__err_code = _STLP_LOC_NO_MEMORY; return lcol; }
michael@0 814 memset(lcol, 0, sizeof(_Locale_collate_t));
michael@0 815
michael@0 816 if (__GetLCIDFromName(name, &lcol->lc.id, lcol->cp, lc_hint) == -1)
michael@0 817 { free(lcol); *__err_code = _STLP_LOC_UNKNOWN_NAME; return NULL; }
michael@0 818
michael@0 819 #if defined (__BORLANDC__)
michael@0 820 if ( lcol->lc.id == INVARIANT_LCID && name[0] == 'C' && name[1] == 0 )
michael@0 821 { lcol->lc.id = 0x409; }
michael@0 822 #endif
michael@0 823
michael@0 824 return lcol;
michael@0 825 }
michael@0 826
michael@0 827 _Locale_monetary_t* _Locale_monetary_create(const char * name, _Locale_lcid_t* lc_hint, int *__err_code) {
michael@0 828 char *GroupingBuffer;
michael@0 829 int BufferSize;
michael@0 830 char FracDigits[3];
michael@0 831 wchar_t wbuf[6];
michael@0 832
michael@0 833 _Locale_monetary_t *lmon = (_Locale_monetary_t*)malloc(sizeof(_Locale_monetary_t));
michael@0 834 if (!lmon) { *__err_code = _STLP_LOC_NO_MEMORY; return lmon; }
michael@0 835 memset(lmon, 0, sizeof(_Locale_monetary_t));
michael@0 836
michael@0 837 if (__GetLCIDFromName(name, &lmon->lc.id, lmon->cp, lc_hint) == -1)
michael@0 838 { free(lmon); *__err_code = _STLP_LOC_UNKNOWN_NAME; return NULL; }
michael@0 839
michael@0 840 if (lmon->lc.id != INVARIANT_LCID) {
michael@0 841 /* Extract information about monetary system */
michael@0 842 __GetLocaleInfoUsingACP(lmon->lc.id, lmon->cp, LOCALE_SDECIMAL, lmon->decimal_point, 4, wbuf, 6);
michael@0 843 __GetLocaleInfoUsingACP(lmon->lc.id, lmon->cp, LOCALE_STHOUSAND, lmon->thousands_sep, 4, wbuf, 6);
michael@0 844
michael@0 845 BufferSize = GetLocaleInfoA(lmon->lc.id, LOCALE_SGROUPING, NULL, 0);
michael@0 846 GroupingBuffer = (char*)malloc(BufferSize);
michael@0 847 if (!GroupingBuffer)
michael@0 848 { lmon->grouping = NULL; *__err_code = _STLP_LOC_NO_MEMORY; return lmon; }
michael@0 849 GetLocaleInfoA(lmon->lc.id, LOCALE_SGROUPING, GroupingBuffer, BufferSize);
michael@0 850 __FixGrouping(GroupingBuffer);
michael@0 851 lmon->grouping = GroupingBuffer;
michael@0 852
michael@0 853 __GetLocaleInfoUsingACP(lmon->lc.id, lmon->cp, LOCALE_SCURRENCY, lmon->curr_symbol, 6, wbuf, 6);
michael@0 854 __GetLocaleInfoUsingACP(lmon->lc.id, lmon->cp, LOCALE_SNEGATIVESIGN, lmon->negative_sign, 5, wbuf, 6);
michael@0 855 __GetLocaleInfoUsingACP(lmon->lc.id, lmon->cp, LOCALE_SPOSITIVESIGN, lmon->positive_sign, 5, wbuf, 6);
michael@0 856
michael@0 857 GetLocaleInfoA(lmon->lc.id, LOCALE_ICURRDIGITS, FracDigits, 3);
michael@0 858 lmon->frac_digits = atoi(FracDigits);
michael@0 859
michael@0 860 GetLocaleInfoA(lmon->lc.id, LOCALE_IINTLCURRDIGITS, FracDigits, 3);
michael@0 861 lmon->int_frac_digits = atoi(FracDigits);
michael@0 862
michael@0 863 __GetLocaleInfoUsingACP(lmon->lc.id, lmon->cp, LOCALE_SINTLSYMBOL, lmon->int_curr_symbol, 5, wbuf, 6);
michael@0 864 /* Even if Platform SDK documentation says that the returned symbol should
michael@0 865 * be a 3 letters symbol followed by a seperation character, experimentation
michael@0 866 * has shown that no seperation character is ever appended. We are adding it
michael@0 867 * ourself to conform to the POSIX specification.
michael@0 868 */
michael@0 869 if (lmon->int_curr_symbol[3] == 0) {
michael@0 870 lmon->int_curr_symbol[3] = ' ';
michael@0 871 lmon->int_curr_symbol[4] = 0;
michael@0 872 }
michael@0 873 }
michael@0 874 /* else it is already ok */
michael@0 875
michael@0 876 return lmon;
michael@0 877 }
michael@0 878
michael@0 879 struct _Locale_messages* _Locale_messages_create(const char *name, _Locale_lcid_t* lc_hint, int *__err_code) {
michael@0 880 /* The Win32 API has no support for messages facet */
michael@0 881 _STLP_MARK_PARAMETER_AS_UNUSED(name)
michael@0 882 _STLP_MARK_PARAMETER_AS_UNUSED(lc_hint)
michael@0 883 *__err_code = _STLP_LOC_UNSUPPORTED_FACET_CATEGORY;
michael@0 884 return NULL;
michael@0 885 }
michael@0 886
michael@0 887 static const char* _Locale_common_default(char* buf) {
michael@0 888 char cp[MAX_CP_LEN + 1];
michael@0 889 int CodePage = __GetDefaultCP(LOCALE_USER_DEFAULT);
michael@0 890 my_ltoa(CodePage, cp);
michael@0 891 return __GetLocaleName(LOCALE_USER_DEFAULT, cp, buf);
michael@0 892 }
michael@0 893
michael@0 894 const char* _Locale_ctype_default(char* buf)
michael@0 895 { return _Locale_common_default(buf); }
michael@0 896
michael@0 897 const char* _Locale_numeric_default(char * buf)
michael@0 898 { return _Locale_common_default(buf); }
michael@0 899
michael@0 900 const char* _Locale_time_default(char* buf)
michael@0 901 { return _Locale_common_default(buf); }
michael@0 902
michael@0 903 const char* _Locale_collate_default(char* buf)
michael@0 904 { return _Locale_common_default(buf); }
michael@0 905
michael@0 906 const char* _Locale_monetary_default(char* buf)
michael@0 907 { return _Locale_common_default(buf); }
michael@0 908
michael@0 909 const char* _Locale_messages_default(char* buf)
michael@0 910 { return _Locale_common_default(buf); }
michael@0 911
michael@0 912 char const* _Locale_ctype_name(const _Locale_ctype_t* ltype, char* buf) {
michael@0 913 char cp_buf[MAX_CP_LEN + 1];
michael@0 914 my_ltoa(ltype->cp, cp_buf);
michael@0 915 return __GetLocaleName(ltype->lc.id, cp_buf, buf);
michael@0 916 }
michael@0 917
michael@0 918 char const* _Locale_numeric_name(const _Locale_numeric_t* lnum, char* buf)
michael@0 919 { return __GetLocaleName(lnum->lc.id, lnum->cp, buf); }
michael@0 920
michael@0 921 char const* _Locale_time_name(const _Locale_time_t* ltime, char* buf)
michael@0 922 { return __GetLocaleName(ltime->lc.id, ltime->cp, buf); }
michael@0 923
michael@0 924 char const* _Locale_collate_name(const _Locale_collate_t* lcol, char* buf)
michael@0 925 { return __GetLocaleName(lcol->lc.id, lcol->cp, buf); }
michael@0 926
michael@0 927 char const* _Locale_monetary_name(const _Locale_monetary_t* lmon, char* buf)
michael@0 928 { return __GetLocaleName(lmon->lc.id, lmon->cp, buf); }
michael@0 929
michael@0 930 char const* _Locale_messages_name(const struct _Locale_messages* lmes, char* buf) {
michael@0 931 _STLP_MARK_PARAMETER_AS_UNUSED(lmes)
michael@0 932 _STLP_MARK_PARAMETER_AS_UNUSED(buf)
michael@0 933 return NULL;
michael@0 934 }
michael@0 935
michael@0 936 void _Locale_ctype_destroy(_Locale_ctype_t* ltype) {
michael@0 937 if (!ltype) return;
michael@0 938
michael@0 939 free(ltype);
michael@0 940 }
michael@0 941
michael@0 942 void _Locale_numeric_destroy(_Locale_numeric_t* lnum) {
michael@0 943 if (!lnum) return;
michael@0 944
michael@0 945 if (lnum->grouping) free(lnum->grouping);
michael@0 946 free(lnum);
michael@0 947 }
michael@0 948
michael@0 949 void _Locale_time_destroy(_Locale_time_t* ltime) {
michael@0 950 int i;
michael@0 951 if (!ltime) return;
michael@0 952
michael@0 953 for (i = 0; i < 12; ++i) {
michael@0 954 if (ltime->month[i]) free(ltime->month[i]);
michael@0 955 if (ltime->abbrev_month[i]) free(ltime->abbrev_month[i]);
michael@0 956 }
michael@0 957
michael@0 958 for (i = 0; i < 7; ++i) {
michael@0 959 if (ltime->dayofweek[i]) free(ltime->dayofweek[i]);
michael@0 960 if (ltime->abbrev_dayofweek[i]) free(ltime->abbrev_dayofweek[i]);
michael@0 961 }
michael@0 962
michael@0 963 if (ltime->date_format) free(ltime->date_format);
michael@0 964 if (ltime->long_date_format) free(ltime->long_date_format);
michael@0 965 if (ltime->time_format) free(ltime->time_format);
michael@0 966 if (ltime->date_time_format) free(ltime->date_time_format);
michael@0 967 if (ltime->long_date_time_format) free(ltime->long_date_time_format);
michael@0 968
michael@0 969 free(ltime);
michael@0 970 }
michael@0 971
michael@0 972 void _Locale_collate_destroy(_Locale_collate_t* lcol) {
michael@0 973 if (!lcol) return;
michael@0 974
michael@0 975 free(lcol);
michael@0 976 }
michael@0 977
michael@0 978 void _Locale_monetary_destroy(_Locale_monetary_t* lmon) {
michael@0 979 if (!lmon) return;
michael@0 980
michael@0 981 if (lmon->grouping) free(lmon->grouping);
michael@0 982 free(lmon);
michael@0 983 }
michael@0 984
michael@0 985 void _Locale_messages_destroy(struct _Locale_messages* lmes)
michael@0 986 { _STLP_MARK_PARAMETER_AS_UNUSED(lmes) }
michael@0 987
michael@0 988 static char const* _Locale_extract_category_name(const char* name, const char* category, char* buf,
michael@0 989 _Locale_lcid_t* hint, int *__err_code) {
michael@0 990 const char* cname = __Extract_locale_name(name, category, buf);
michael@0 991 if (cname == 0 || (cname[0] == 'C' && cname[1] == 0)) {
michael@0 992 return cname;
michael@0 993 }
michael@0 994 return __TranslateToSystem(cname, buf, hint, __err_code);
michael@0 995 }
michael@0 996
michael@0 997 char const* _Locale_extract_ctype_name(const char* cname, char* buf,
michael@0 998 _Locale_lcid_t* hint, int *__err_code)
michael@0 999 { return _Locale_extract_category_name(cname, "LC_CTYPE", buf, hint, __err_code); }
michael@0 1000
michael@0 1001 char const* _Locale_extract_numeric_name(const char* cname, char* buf,
michael@0 1002 _Locale_lcid_t* hint, int *__err_code)
michael@0 1003 { return _Locale_extract_category_name(cname, "LC_NUMERIC", buf, hint, __err_code); }
michael@0 1004
michael@0 1005 char const* _Locale_extract_time_name(const char* cname, char* buf,
michael@0 1006 _Locale_lcid_t* hint, int *__err_code)
michael@0 1007 { return _Locale_extract_category_name(cname, "LC_TIME", buf, hint, __err_code); }
michael@0 1008
michael@0 1009 char const* _Locale_extract_collate_name(const char* cname, char* buf,
michael@0 1010 _Locale_lcid_t* hint, int *__err_code)
michael@0 1011 { return _Locale_extract_category_name(cname, "LC_COLLATE", buf, hint, __err_code); }
michael@0 1012
michael@0 1013 char const* _Locale_extract_monetary_name(const char* cname, char* buf,
michael@0 1014 _Locale_lcid_t* hint, int *__err_code)
michael@0 1015 { return _Locale_extract_category_name(cname, "LC_MONETARY", buf, hint, __err_code); }
michael@0 1016
michael@0 1017 char const* _Locale_extract_messages_name(const char* cname, char* buf,
michael@0 1018 _Locale_lcid_t* hint, int *__err_code) {
michael@0 1019 if (cname[0] == 'L' && cname[1] == 'C' && cname[2] == '_') {
michael@0 1020 return _C_name;
michael@0 1021 }
michael@0 1022 if (cname[0] == 'C' && cname[1] == 0) {
michael@0 1023 return _C_name;
michael@0 1024 }
michael@0 1025 return __TranslateToSystem(cname, buf, hint, __err_code);
michael@0 1026 }
michael@0 1027
michael@0 1028 /* ctype */
michael@0 1029
michael@0 1030 const _Locale_mask_t* _Locale_ctype_table(_Locale_ctype_t* ltype) {
michael@0 1031 _STLP_STATIC_ASSERT(sizeof(_Locale_mask_t) == sizeof(ltype->ctable[0]))
michael@0 1032 return (const _Locale_mask_t*)ltype->ctable;
michael@0 1033 }
michael@0 1034
michael@0 1035 int _Locale_toupper(_Locale_ctype_t* ltype, int c) {
michael@0 1036 char buf[2], out_buf[2];
michael@0 1037 buf[0] = (char)c; buf[1] = 0;
michael@0 1038 if ((UINT)__GetDefaultCP(ltype->lc.id) == ltype->cp) {
michael@0 1039 LCMapStringA(ltype->lc.id, LCMAP_LINGUISTIC_CASING | LCMAP_UPPERCASE, buf, 2, out_buf, 2);
michael@0 1040 return out_buf[0];
michael@0 1041 }
michael@0 1042 else {
michael@0 1043 wchar_t wbuf[2];
michael@0 1044 MultiByteToWideChar(ltype->cp, MB_PRECOMPOSED, buf, 2, wbuf, 2);
michael@0 1045 WideCharToMultiByte(__GetDefaultCP(ltype->lc.id), WC_COMPOSITECHECK | WC_SEPCHARS, wbuf, 2, buf, 2, NULL, FALSE);
michael@0 1046
michael@0 1047 LCMapStringA(ltype->lc.id, LCMAP_LINGUISTIC_CASING | LCMAP_UPPERCASE, buf, 2, out_buf, 2);
michael@0 1048
michael@0 1049 MultiByteToWideChar(__GetDefaultCP(ltype->lc.id), MB_PRECOMPOSED, out_buf, 2, wbuf, 2);
michael@0 1050 WideCharToMultiByte(ltype->cp, WC_COMPOSITECHECK | WC_SEPCHARS, wbuf, 2, out_buf, 2, NULL, FALSE);
michael@0 1051 return out_buf[0];
michael@0 1052 }
michael@0 1053 }
michael@0 1054
michael@0 1055 int _Locale_tolower(_Locale_ctype_t* ltype, int c) {
michael@0 1056 char buf[2], out_buf[2];
michael@0 1057 buf[0] = (char)c; buf[1] = 0;
michael@0 1058 if ((UINT)__GetDefaultCP(ltype->lc.id) == ltype->cp) {
michael@0 1059 LCMapStringA(ltype->lc.id, LCMAP_LINGUISTIC_CASING | LCMAP_LOWERCASE, buf, 2, out_buf, 2);
michael@0 1060 return out_buf[0];
michael@0 1061 }
michael@0 1062 else {
michael@0 1063 wchar_t wbuf[2];
michael@0 1064 MultiByteToWideChar(ltype->cp, MB_PRECOMPOSED, buf, 2, wbuf, 2);
michael@0 1065 WideCharToMultiByte(__GetDefaultCP(ltype->lc.id), WC_COMPOSITECHECK | WC_SEPCHARS, wbuf, 2, buf, 2, NULL, FALSE);
michael@0 1066
michael@0 1067 LCMapStringA(ltype->lc.id, LCMAP_LINGUISTIC_CASING | LCMAP_LOWERCASE, buf, 2, out_buf, 2);
michael@0 1068
michael@0 1069 MultiByteToWideChar(__GetDefaultCP(ltype->lc.id), MB_PRECOMPOSED, out_buf, 2, wbuf, 2);
michael@0 1070 WideCharToMultiByte(ltype->cp, WC_COMPOSITECHECK | WC_SEPCHARS, wbuf, 2, out_buf, 2, NULL, FALSE);
michael@0 1071 return out_buf[0];
michael@0 1072 }
michael@0 1073 }
michael@0 1074
michael@0 1075 #ifndef CSTR_EQUAL /* VC5SP3*/
michael@0 1076 # define CSTR_EQUAL 2
michael@0 1077 #endif
michael@0 1078 #ifndef CSTR_LESS_THAN /* VC5SP3 */
michael@0 1079 # define CSTR_LESS_THAN 1
michael@0 1080 #endif
michael@0 1081
michael@0 1082 static DWORD max_DWORD = 0xffffffff;
michael@0 1083 static DWORD trim_size_t_to_DWORD(size_t n) { return n < (size_t)max_DWORD ? (DWORD)n : max_DWORD; }
michael@0 1084
michael@0 1085 /* Collate */
michael@0 1086 /* This function takes care of the potential size_t DWORD different size. */
michael@0 1087 static int _Locale_strcmp_auxA(_Locale_collate_t* lcol,
michael@0 1088 const char* s1, size_t n1,
michael@0 1089 const char* s2, size_t n2) {
michael@0 1090 int result = CSTR_EQUAL;
michael@0 1091 while (n1 > 0 || n2 > 0) {
michael@0 1092 DWORD size1 = trim_size_t_to_DWORD(n1);
michael@0 1093 DWORD size2 = trim_size_t_to_DWORD(n2);
michael@0 1094 result = CompareStringA(lcol->lc.id, 0, s1, size1, s2, size2);
michael@0 1095 if (result != CSTR_EQUAL)
michael@0 1096 break;
michael@0 1097 n1 -= size1;
michael@0 1098 n2 -= size2;
michael@0 1099 }
michael@0 1100 return result;
michael@0 1101 }
michael@0 1102
michael@0 1103 int _Locale_strcmp(_Locale_collate_t* lcol,
michael@0 1104 const char* s1, size_t n1,
michael@0 1105 const char* s2, size_t n2) {
michael@0 1106 int result;
michael@0 1107 if (__GetDefaultCP(lcol->lc.id) == atoi(lcol->cp)) {
michael@0 1108 result = _Locale_strcmp_auxA(lcol, s1, n1, s2, n2);
michael@0 1109 }
michael@0 1110 else {
michael@0 1111 char *buf1, *buf2;
michael@0 1112 size_t size1, size2;
michael@0 1113 buf1 = __ConvertToCP(atoi(lcol->cp), __GetDefaultCP(lcol->lc.id), s1, n1, &size1);
michael@0 1114 buf2 = __ConvertToCP(atoi(lcol->cp), __GetDefaultCP(lcol->lc.id), s2, n2, &size2);
michael@0 1115
michael@0 1116 result = _Locale_strcmp_auxA(lcol, buf1, size1, buf2, size2);
michael@0 1117 free(buf1); free(buf2);
michael@0 1118 }
michael@0 1119 return (result == CSTR_EQUAL) ? 0 : (result == CSTR_LESS_THAN) ? -1 : 1;
michael@0 1120 }
michael@0 1121
michael@0 1122 size_t _Locale_strxfrm(_Locale_collate_t* lcol,
michael@0 1123 char* dst, size_t dst_size,
michael@0 1124 const char* src, size_t src_size) {
michael@0 1125 int result;
michael@0 1126
michael@0 1127 /* The Windows API do not support transformation of very long strings (src_size > INT_MAX)
michael@0 1128 * In this case the result will just be the input string:
michael@0 1129 */
michael@0 1130 if (src_size > INT_MAX) {
michael@0 1131 if (dst != 0) {
michael@0 1132 _STLP_STRNCPY(dst, dst_size, src, src_size);
michael@0 1133 }
michael@0 1134 return src_size;
michael@0 1135 }
michael@0 1136 if (dst_size > INT_MAX) {
michael@0 1137 /* now that we know that src_size <= INT_MAX we can safely decrease dst_size to INT_MAX. */
michael@0 1138 dst_size = INT_MAX;
michael@0 1139 }
michael@0 1140
michael@0 1141 if (__GetDefaultCP(lcol->lc.id) == atoi(lcol->cp))
michael@0 1142 result = LCMapStringA(lcol->lc.id, LCMAP_SORTKEY, src, (int)src_size, dst, (int)dst_size);
michael@0 1143 else {
michael@0 1144 char *buf;
michael@0 1145 size_t size;
michael@0 1146 buf = __ConvertToCP(atoi(lcol->cp), __GetDefaultCP(lcol->lc.id), src, src_size, &size);
michael@0 1147
michael@0 1148 result = LCMapStringA(lcol->lc.id, LCMAP_SORTKEY, buf, (int)size, dst, (int)dst_size);
michael@0 1149 free(buf);
michael@0 1150 }
michael@0 1151 return result != 0 ? result - 1 : 0;
michael@0 1152 }
michael@0 1153
michael@0 1154 /* Numeric */
michael@0 1155 static const char* __true_name = "true";
michael@0 1156 static const char* __false_name = "false";
michael@0 1157
michael@0 1158 char _Locale_decimal_point(_Locale_numeric_t* lnum)
michael@0 1159 { return lnum->decimal_point[0]; }
michael@0 1160
michael@0 1161 char _Locale_thousands_sep(_Locale_numeric_t* lnum)
michael@0 1162 { return lnum->thousands_sep[0]; }
michael@0 1163
michael@0 1164 const char* _Locale_grouping(_Locale_numeric_t * lnum) {
michael@0 1165 if (!lnum->grouping) return "";
michael@0 1166 else return lnum->grouping;
michael@0 1167 }
michael@0 1168
michael@0 1169 const char * _Locale_true(_Locale_numeric_t * lnum) {
michael@0 1170 _STLP_MARK_PARAMETER_AS_UNUSED(lnum)
michael@0 1171 return __true_name; /* NT does't provide information about this */
michael@0 1172 }
michael@0 1173
michael@0 1174 const char * _Locale_false(_Locale_numeric_t * lnum) {
michael@0 1175 _STLP_MARK_PARAMETER_AS_UNUSED(lnum)
michael@0 1176 return __false_name; /* NT does't provide information about this */
michael@0 1177 }
michael@0 1178
michael@0 1179 /* Monetary */
michael@0 1180 const char* _Locale_int_curr_symbol(_Locale_monetary_t * lmon)
michael@0 1181 { return lmon->int_curr_symbol; }
michael@0 1182
michael@0 1183 const char* _Locale_currency_symbol(_Locale_monetary_t * lmon)
michael@0 1184 { return lmon->curr_symbol; }
michael@0 1185
michael@0 1186 char _Locale_mon_decimal_point(_Locale_monetary_t * lmon)
michael@0 1187 { return lmon->decimal_point[0]; }
michael@0 1188
michael@0 1189 char _Locale_mon_thousands_sep(_Locale_monetary_t * lmon)
michael@0 1190 { return lmon->thousands_sep[0]; }
michael@0 1191
michael@0 1192 const char* _Locale_mon_grouping(_Locale_monetary_t * lmon) {
michael@0 1193 if (!lmon->grouping) return "";
michael@0 1194 else return lmon->grouping;
michael@0 1195 }
michael@0 1196
michael@0 1197 const char* _Locale_positive_sign(_Locale_monetary_t * lmon)
michael@0 1198 { return lmon->positive_sign; }
michael@0 1199
michael@0 1200 const char* _Locale_negative_sign(_Locale_monetary_t * lmon)
michael@0 1201 { return lmon->negative_sign; }
michael@0 1202
michael@0 1203 char _Locale_int_frac_digits(_Locale_monetary_t * lmon)
michael@0 1204 { return (char)lmon->int_frac_digits; }
michael@0 1205
michael@0 1206 char _Locale_frac_digits(_Locale_monetary_t * lmon)
michael@0 1207 { return (char)lmon->frac_digits; }
michael@0 1208
michael@0 1209 int _Locale_p_cs_precedes(_Locale_monetary_t * lmon) {
michael@0 1210 char loc_data[2];
michael@0 1211 GetLocaleInfoA(lmon->lc.id, LOCALE_IPOSSYMPRECEDES, loc_data, 2);
michael@0 1212 if (loc_data[0] == '0') return 0;
michael@0 1213 else if (loc_data[0] == '1') return 1;
michael@0 1214 else return -1;
michael@0 1215 }
michael@0 1216
michael@0 1217 int _Locale_p_sep_by_space(_Locale_monetary_t * lmon) {
michael@0 1218 char loc_data[2];
michael@0 1219 GetLocaleInfoA(lmon->lc.id, LOCALE_IPOSSEPBYSPACE, loc_data, 2);
michael@0 1220 if (loc_data[0] == '0') return 0;
michael@0 1221 else if (loc_data[0] == '1') return 1;
michael@0 1222 else return -1;
michael@0 1223 }
michael@0 1224
michael@0 1225 int _Locale_p_sign_posn(_Locale_monetary_t * lmon) {
michael@0 1226 char loc_data[2];
michael@0 1227 if (lmon->lc.id != INVARIANT_LCID) {
michael@0 1228 GetLocaleInfoA(lmon->lc.id, LOCALE_IPOSSIGNPOSN, loc_data, 2);
michael@0 1229 return atoi(loc_data);
michael@0 1230 }
michael@0 1231 else {
michael@0 1232 return CHAR_MAX;
michael@0 1233 }
michael@0 1234 }
michael@0 1235
michael@0 1236 int _Locale_n_cs_precedes(_Locale_monetary_t * lmon) {
michael@0 1237 char loc_data[2];
michael@0 1238 GetLocaleInfoA(lmon->lc.id, LOCALE_INEGSYMPRECEDES, loc_data, 2);
michael@0 1239 if (loc_data[0] == '0') return 0;
michael@0 1240 else if (loc_data[0] == '1') return 1;
michael@0 1241 else return -1;
michael@0 1242 }
michael@0 1243
michael@0 1244 int _Locale_n_sep_by_space(_Locale_monetary_t * lmon) {
michael@0 1245 char loc_data[2];
michael@0 1246 GetLocaleInfoA(lmon->lc.id, LOCALE_INEGSEPBYSPACE, loc_data, 2);
michael@0 1247 if (loc_data[0] == '0') return 0;
michael@0 1248 else if (loc_data[0] == '1') return 1;
michael@0 1249 else return -1;
michael@0 1250 }
michael@0 1251
michael@0 1252 int _Locale_n_sign_posn(_Locale_monetary_t * lmon) {
michael@0 1253 char loc_data[2];
michael@0 1254 if (lmon->lc.id != INVARIANT_LCID) {
michael@0 1255 GetLocaleInfoA(lmon->lc.id, LOCALE_INEGSIGNPOSN, loc_data, 2);
michael@0 1256 return atoi(loc_data);
michael@0 1257 }
michael@0 1258 else {
michael@0 1259 return CHAR_MAX;
michael@0 1260 }
michael@0 1261 }
michael@0 1262
michael@0 1263 /* Time */
michael@0 1264 const char * _Locale_full_monthname(_Locale_time_t * ltime, int month) {
michael@0 1265 const char **names = (const char**)ltime->month;
michael@0 1266 return names[month];
michael@0 1267 }
michael@0 1268
michael@0 1269 const char * _Locale_abbrev_monthname(_Locale_time_t * ltime, int month) {
michael@0 1270 const char **names = (const char**)ltime->abbrev_month;
michael@0 1271 return names[month];
michael@0 1272 }
michael@0 1273
michael@0 1274 const char * _Locale_full_dayofweek(_Locale_time_t * ltime, int day) {
michael@0 1275 const char **names = (const char**)ltime->dayofweek;
michael@0 1276 return names[day];
michael@0 1277 }
michael@0 1278
michael@0 1279 const char * _Locale_abbrev_dayofweek(_Locale_time_t * ltime, int day) {
michael@0 1280 const char **names = (const char**)ltime->abbrev_dayofweek;
michael@0 1281 return names[day];
michael@0 1282 }
michael@0 1283
michael@0 1284 const char* _Locale_d_t_fmt(_Locale_time_t* ltime)
michael@0 1285 { return ltime->date_time_format; }
michael@0 1286
michael@0 1287 const char* _Locale_long_d_t_fmt(_Locale_time_t* ltime)
michael@0 1288 { return ltime->long_date_time_format; }
michael@0 1289
michael@0 1290 const char* _Locale_d_fmt(_Locale_time_t* ltime)
michael@0 1291 { return ltime->date_format; }
michael@0 1292
michael@0 1293 const char* _Locale_long_d_fmt(_Locale_time_t* ltime)
michael@0 1294 { return ltime->long_date_format; }
michael@0 1295
michael@0 1296 const char* _Locale_t_fmt(_Locale_time_t* ltime)
michael@0 1297 { return ltime->time_format; }
michael@0 1298
michael@0 1299 const char* _Locale_am_str(_Locale_time_t* ltime)
michael@0 1300 { return ltime->am; }
michael@0 1301
michael@0 1302 const char* _Locale_pm_str(_Locale_time_t* ltime)
michael@0 1303 { return ltime->pm; }
michael@0 1304
michael@0 1305 /* Messages */
michael@0 1306 nl_catd_type _Locale_catopen(struct _Locale_messages* lmes, const char* cat_name) {
michael@0 1307 _STLP_MARK_PARAMETER_AS_UNUSED(lmes)
michael@0 1308 _STLP_MARK_PARAMETER_AS_UNUSED(cat_name)
michael@0 1309 return -1;
michael@0 1310 }
michael@0 1311 void _Locale_catclose(struct _Locale_messages* lmes, nl_catd_type cat) {
michael@0 1312 _STLP_MARK_PARAMETER_AS_UNUSED(lmes)
michael@0 1313 _STLP_MARK_PARAMETER_AS_UNUSED(&cat)
michael@0 1314 }
michael@0 1315 const char* _Locale_catgets(struct _Locale_messages* lmes, nl_catd_type cat,
michael@0 1316 int setid, int msgid, const char *dfault) {
michael@0 1317 _STLP_MARK_PARAMETER_AS_UNUSED(lmes)
michael@0 1318 _STLP_MARK_PARAMETER_AS_UNUSED(&cat)
michael@0 1319 _STLP_MARK_PARAMETER_AS_UNUSED(&setid)
michael@0 1320 _STLP_MARK_PARAMETER_AS_UNUSED(&msgid)
michael@0 1321 return dfault;
michael@0 1322 }
michael@0 1323
michael@0 1324 #ifdef __cplusplus
michael@0 1325 } /* extern C */
michael@0 1326 _STLP_END_NAMESPACE
michael@0 1327 #endif
michael@0 1328
michael@0 1329 void __FixGrouping(char *grouping) {
michael@0 1330 /* This converts NT version which uses '0' instead of 0, etc ; to ANSI */
michael@0 1331 char *g = grouping;
michael@0 1332 char building_group = 0;
michael@0 1333 char repeat_last = 0;
michael@0 1334 /* Check there is a grouping info otherwise we would add a useless CHAR_MAX */
michael@0 1335 if (*g) {
michael@0 1336 for (; *g; ++g) {
michael@0 1337 if (*g > '0' && *g <= '9') {
michael@0 1338 if (!building_group) {
michael@0 1339 *grouping = *g - '0';
michael@0 1340 building_group = 1;
michael@0 1341 }
michael@0 1342 else {
michael@0 1343 /* Known issue: grouping might roll. */
michael@0 1344 *grouping = *grouping * 10 + *g - '0';
michael@0 1345 }
michael@0 1346 }
michael@0 1347 else if (*g == '0') {
michael@0 1348 if (!building_group) {
michael@0 1349 repeat_last = 1;
michael@0 1350 }
michael@0 1351 else
michael@0 1352 /* Known issue: grouping might roll. */
michael@0 1353 *grouping *= 10;
michael@0 1354 }
michael@0 1355 else if (*g == ';') {
michael@0 1356 /* Stop adding to the current group */
michael@0 1357 building_group = 0;
michael@0 1358 ++grouping;
michael@0 1359 }
michael@0 1360 /* else we ignore the character */
michael@0 1361 }
michael@0 1362
michael@0 1363 if (!repeat_last)
michael@0 1364 *grouping++ = CHAR_MAX;
michael@0 1365 *grouping = 0;
michael@0 1366 }
michael@0 1367 }
michael@0 1368
michael@0 1369 const char* __ConvertName(const char* lname, LOCALECONV* ConvTable, int TableSize) {
michael@0 1370 int i;
michael@0 1371 int cmp;
michael@0 1372 int low = 0;
michael@0 1373 int high = TableSize - 1;
michael@0 1374
michael@0 1375 /* typical binary search - do until no more to search or match */
michael@0 1376 while (low <= high) {
michael@0 1377 i = (low + high) / 2;
michael@0 1378
michael@0 1379 if ((cmp = lstrcmpiA(lname, (*(ConvTable + i)).name)) == 0)
michael@0 1380 return (*(ConvTable + i)).abbrev;
michael@0 1381 else if (cmp < 0)
michael@0 1382 high = i - 1;
michael@0 1383 else
michael@0 1384 low = i + 1;
michael@0 1385 }
michael@0 1386 return lname;
michael@0 1387 }
michael@0 1388
michael@0 1389 int __ParseLocaleString(const char* lname,
michael@0 1390 char* lang, char* ctry, char* page) {
michael@0 1391 int param = 0;
michael@0 1392 size_t len;
michael@0 1393 size_t tmpLen;
michael@0 1394
michael@0 1395 if (lname[0] == 0)
michael@0 1396 return 0;
michael@0 1397
michael@0 1398 /* We look for the first country separator '_' */
michael@0 1399 len = strcspn(lname, "_");
michael@0 1400 if (lname[len] == '_') {
michael@0 1401 if (len == 0 || len > MAX_LANG_LEN) return -1; /* empty lang is invalid*/
michael@0 1402 _STLP_STRNCPY(lang, MAX_LANG_LEN + 1, lname, len);
michael@0 1403 lname += len + 1;
michael@0 1404 ++param;
michael@0 1405 }
michael@0 1406
michael@0 1407 /* We look for the last code page separator '.' */
michael@0 1408 len = -1;
michael@0 1409 tmpLen = strcspn(lname, ".");
michael@0 1410 while (lname[tmpLen] == '.') {
michael@0 1411 len = tmpLen; ++tmpLen;
michael@0 1412 tmpLen += strcspn(lname + tmpLen, ".");
michael@0 1413 }
michael@0 1414 if (len != -1) { /* Means that we found a '.' */
michael@0 1415 if (param == 0) {
michael@0 1416 /* We have no lang yet so we have to fill it first, no country */
michael@0 1417 if (len > MAX_LANG_LEN) return -1;
michael@0 1418 if (len == 0) {
michael@0 1419 /* No language nor country, only code page */
michael@0 1420 ++param;
michael@0 1421 }
michael@0 1422 else
michael@0 1423 { _STLP_STRNCPY(lang, MAX_LANG_LEN + 1, lname, len); }
michael@0 1424 ++param;
michael@0 1425 }
michael@0 1426 else {
michael@0 1427 /* We already have a lang so we are now looking for the country: */
michael@0 1428 if (len == 0) return -1; /* We forbid locale name with the "_." motif in it */
michael@0 1429 if (len > MAX_CTRY_LEN) return -1;
michael@0 1430 _STLP_STRNCPY(ctry, MAX_CTRY_LEN + 1, lname, len);
michael@0 1431 }
michael@0 1432 ++param;
michael@0 1433 lname += len + 1;
michael@0 1434 }
michael@0 1435
michael@0 1436 /* We look for ',' for compatibility with POSIX */
michael@0 1437 len = strcspn(lname, ",");
michael@0 1438 switch (param) {
michael@0 1439 case 0:
michael@0 1440 if (len > MAX_LANG_LEN) return -1;
michael@0 1441 _STLP_STRNCPY(lang, MAX_LANG_LEN + 1, lname, len);
michael@0 1442 break;
michael@0 1443 case 1:
michael@0 1444 if (len > MAX_CTRY_LEN) return -1;
michael@0 1445 _STLP_STRNCPY(ctry, MAX_CTRY_LEN + 1, lname, len);
michael@0 1446 break;
michael@0 1447 default:
michael@0 1448 if (len > MAX_CP_LEN) return -1;
michael@0 1449 _STLP_STRNCPY(page, MAX_CP_LEN + 1, lname, len);
michael@0 1450 break;
michael@0 1451 }
michael@0 1452
michael@0 1453 /* ',' POSIX modifier is not used in NT */
michael@0 1454 return 0;
michael@0 1455 }
michael@0 1456
michael@0 1457 /* Data necessary for find LCID*/
michael@0 1458 static CRITICAL_SECTION __criticalSection;
michael@0 1459 static int __FindFlag;
michael@0 1460 static LCID __FndLCID;
michael@0 1461 static const char* __FndLang;
michael@0 1462 static const char* __FndCtry;
michael@0 1463
michael@0 1464 void _Locale_init()
michael@0 1465 { InitializeCriticalSection(&__criticalSection); }
michael@0 1466
michael@0 1467 void _Locale_final()
michael@0 1468 { DeleteCriticalSection(&__criticalSection); }
michael@0 1469
michael@0 1470 static LCID LocaleFromHex(const char* locale) {
michael@0 1471 unsigned long result = 0;
michael@0 1472 int digit;
michael@0 1473 while (*locale) {
michael@0 1474 result <<= 4;
michael@0 1475 digit = (*locale >= '0' && *locale <= '9') ? *locale - '0':
michael@0 1476 (*locale >= 'A' && *locale <= 'F') ? (*locale - 'A') + 10
michael@0 1477 : (*locale - 'a') + 10;
michael@0 1478 result += digit;
michael@0 1479 ++locale;
michael@0 1480 }
michael@0 1481 return (LCID)result;
michael@0 1482 }
michael@0 1483
michael@0 1484 static BOOL CALLBACK EnumLocalesProcA(LPSTR locale) {
michael@0 1485 LCID lcid = LocaleFromHex(locale);
michael@0 1486 int LangFlag = 0, CtryFlag = !__FndCtry;
michael@0 1487 static char Lang[MAX_LANG_LEN], Ctry[MAX_CTRY_LEN];
michael@0 1488
michael@0 1489 GetLocaleInfoA(lcid, LOCALE_SENGLANGUAGE, Lang, MAX_LANG_LEN);
michael@0 1490 if (lstrcmpiA(Lang, __FndLang) != 0) {
michael@0 1491 GetLocaleInfoA(lcid, LOCALE_SABBREVLANGNAME, Lang, MAX_LANG_LEN);
michael@0 1492 if (lstrcmpiA(Lang, __FndLang) != 0) {
michael@0 1493 GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, Lang, MAX_LANG_LEN);
michael@0 1494 if (lstrcmpiA(Lang, __FndLang) == 0) LangFlag = 1;
michael@0 1495 }
michael@0 1496 else LangFlag = 1;
michael@0 1497 }
michael@0 1498 else LangFlag = 1;
michael@0 1499
michael@0 1500 if (__FndCtry) {
michael@0 1501 GetLocaleInfoA(lcid, LOCALE_SENGCOUNTRY, Ctry, MAX_CTRY_LEN);
michael@0 1502 if (lstrcmpiA(Ctry, __FndCtry) != 0) {
michael@0 1503 GetLocaleInfoA(lcid, LOCALE_SABBREVCTRYNAME, Ctry, MAX_CTRY_LEN);
michael@0 1504 if (lstrcmpiA(Ctry, __FndCtry) != 0) {
michael@0 1505 GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, Ctry, MAX_CTRY_LEN);
michael@0 1506 if (lstrcmpiA(Ctry, __FndCtry) == 0) CtryFlag = 1;
michael@0 1507 }
michael@0 1508 else CtryFlag = 1;
michael@0 1509 }
michael@0 1510 else
michael@0 1511 CtryFlag = 1;
michael@0 1512 }
michael@0 1513
michael@0 1514 if (LangFlag && CtryFlag) {
michael@0 1515 __FindFlag = 1;
michael@0 1516 __FndLCID = lcid;
michael@0 1517 return FALSE;
michael@0 1518 }
michael@0 1519
michael@0 1520 return TRUE;
michael@0 1521 }
michael@0 1522
michael@0 1523 int __GetLCID(const char* lang, const char* ctry, LCID* lcid) {
michael@0 1524 int ret;
michael@0 1525 EnterCriticalSection(&__criticalSection);
michael@0 1526
michael@0 1527 __FindFlag = 0;
michael@0 1528 __FndLang = lang;
michael@0 1529 __FndCtry = ctry;
michael@0 1530 EnumSystemLocalesA(EnumLocalesProcA, LCID_INSTALLED);
michael@0 1531
michael@0 1532 if (__FindFlag != 0) *lcid = __FndLCID;
michael@0 1533 ret = __FindFlag != 0 ? 0 : -1;
michael@0 1534
michael@0 1535 LeaveCriticalSection(&__criticalSection);
michael@0 1536 return ret;
michael@0 1537 }
michael@0 1538
michael@0 1539 int __GetLCIDFromName(const char* lname, LCID* lcid, char* cp, _Locale_lcid_t *hint) {
michael@0 1540 char lang[MAX_LANG_LEN + 1], ctry[MAX_CTRY_LEN + 1], page[MAX_CP_LEN + 1];
michael@0 1541 int result = 0;
michael@0 1542 if (lname == NULL || lname[0] == 0) {
michael@0 1543 *lcid = LOCALE_USER_DEFAULT;
michael@0 1544 return 0;
michael@0 1545 }
michael@0 1546
michael@0 1547 memset(lang, 0, MAX_LANG_LEN + 1);
michael@0 1548 memset(ctry, 0, MAX_CTRY_LEN + 1);
michael@0 1549 memset(page, 0, MAX_CP_LEN + 1);
michael@0 1550 if (__ParseLocaleString(lname, lang, ctry, page) == -1) return -1;
michael@0 1551
michael@0 1552 if (hint != 0) {
michael@0 1553 *lcid = hint->id;
michael@0 1554 }
michael@0 1555 else {
michael@0 1556 if (lang[0] == 0 && ctry[0] == 0)
michael@0 1557 *lcid = LOCALE_USER_DEFAULT; /* Only code page given. */
michael@0 1558 else {
michael@0 1559 if (ctry[0] == 0) {
michael@0 1560 result = __GetLCID(__ConvertName(lang, __rg_language, sizeof(__rg_language) / sizeof(LOCALECONV)), NULL, lcid);
michael@0 1561 if (result != 0) {
michael@0 1562 /* Check 'C' special case. Check is done after call to __GetLCID because normal programs do not
michael@0 1563 * generate facet from 'C' name, they use the locale::classic() facets. */
michael@0 1564 if (lang[0] == 'C' && lang[1] == 0) {
michael@0 1565 *lcid = INVARIANT_LCID;
michael@0 1566 result = 0;
michael@0 1567 }
michael@0 1568 }
michael@0 1569 }
michael@0 1570 else {
michael@0 1571 result = __GetLCID(__ConvertName(lang, __rg_language, sizeof(__rg_language) / sizeof(LOCALECONV)),
michael@0 1572 __ConvertName(ctry, __rg_country, sizeof(__rg_country) / sizeof(LOCALECONV)),
michael@0 1573 lcid);
michael@0 1574 if (result != 0) {
michael@0 1575 /* Non NLS mapping might introduce problem with some locales when only one entry is mapped,
michael@0 1576 * the lang or the country (example: chinese locales like 'chinese_taiwan' gives 'CHS_taiwan'
michael@0 1577 * that do not exists in system). This is why we are giving this locale an other chance by
michael@0 1578 * calling __GetLCID without the mapping. */
michael@0 1579 result = __GetLCID(lang, ctry, lcid);
michael@0 1580 }
michael@0 1581 }
michael@0 1582 }
michael@0 1583 }
michael@0 1584
michael@0 1585 if (result == 0) {
michael@0 1586 /* Handling code page */
michael@0 1587 if (lstrcmpiA(page, "ACP") == 0 || page[0] == 0)
michael@0 1588 my_ltoa(__intGetACP(*lcid), cp);
michael@0 1589 else if (lstrcmpiA(page, "OCP") == 0)
michael@0 1590 my_ltoa(__intGetOCP(*lcid), cp);
michael@0 1591 else if (lstrcmpiA(page, "UTF7") == 0)
michael@0 1592 my_ltoa(CP_UTF7, cp);
michael@0 1593 else if (lstrcmpiA(page, "UTF8") == 0)
michael@0 1594 my_ltoa(CP_UTF8, cp);
michael@0 1595 else
michael@0 1596 _STLP_STRNCPY(cp, MAX_CP_LEN + 1, page, 5);
michael@0 1597
michael@0 1598 /* Code page must be an integer value,
michael@0 1599 * 0 returned by __intGetACP and 1 returned by __intGetOCP are invalid
michael@0 1600 * values.
michael@0 1601 */
michael@0 1602 if (cp[1] == 0 && (cp[0] == '0' || cp[1] == '1'))
michael@0 1603 return -1;
michael@0 1604 else if (atoi(cp) == 0)
michael@0 1605 return -1;
michael@0 1606 }
michael@0 1607
michael@0 1608 return result;
michael@0 1609 }
michael@0 1610
michael@0 1611 char const* __GetLocaleName(LCID lcid, const char* cp, char* buf) {
michael@0 1612 if (lcid == INVARIANT_LCID) {
michael@0 1613 return _C_name;
michael@0 1614 }
michael@0 1615 else {
michael@0 1616 char lang[MAX_LANG_LEN + 1], ctry[MAX_CTRY_LEN + 1];
michael@0 1617 GetLocaleInfoA(lcid, LOCALE_SENGLANGUAGE, lang, MAX_LANG_LEN);
michael@0 1618 GetLocaleInfoA(lcid, LOCALE_SENGCOUNTRY, ctry, MAX_CTRY_LEN);
michael@0 1619 _STLP_STRCPY(buf, _Locale_MAX_SIMPLE_NAME, lang);
michael@0 1620 _STLP_STRCAT(buf, _Locale_MAX_SIMPLE_NAME, "_");
michael@0 1621 _STLP_STRCAT(buf, _Locale_MAX_SIMPLE_NAME, ctry);
michael@0 1622 _STLP_STRCAT(buf, _Locale_MAX_SIMPLE_NAME, ".");
michael@0 1623 _STLP_STRCAT(buf, _Locale_MAX_SIMPLE_NAME, cp);
michael@0 1624 return buf;
michael@0 1625 }
michael@0 1626 }
michael@0 1627
michael@0 1628 char const* __Extract_locale_name(const char* loc, const char* category, char* buf) {
michael@0 1629 char *expr;
michael@0 1630 size_t len_name;
michael@0 1631
michael@0 1632 if (loc[0] == 'L' && loc[1] == 'C' && loc[2] == '_') {
michael@0 1633 expr = strstr((char*)loc, category);
michael@0 1634 if (expr == NULL) return NULL; /* Category not found. */
michael@0 1635 expr = strchr(expr, '=');
michael@0 1636 if (expr == NULL) return NULL;
michael@0 1637 ++expr;
michael@0 1638 len_name = strcspn(expr, ";");
michael@0 1639 len_name = len_name >= _Locale_MAX_SIMPLE_NAME ? _Locale_MAX_SIMPLE_NAME - 1
michael@0 1640 : len_name;
michael@0 1641 _STLP_STRNCPY(buf, _Locale_MAX_SIMPLE_NAME, expr, len_name); buf[len_name] = 0;
michael@0 1642 return buf;
michael@0 1643 }
michael@0 1644 else {
michael@0 1645 return loc;
michael@0 1646 }
michael@0 1647 }
michael@0 1648
michael@0 1649 char const* __TranslateToSystem(const char* lname, char* buf, _Locale_lcid_t* hint,
michael@0 1650 int *__err_code) {
michael@0 1651 LCID lcid;
michael@0 1652 char cp[MAX_CP_LEN + 1];
michael@0 1653 if (__GetLCIDFromName(lname, &lcid, cp, hint) != 0)
michael@0 1654 { *__err_code = _STLP_LOC_UNKNOWN_NAME; return NULL; }
michael@0 1655
michael@0 1656 return __GetLocaleName(lcid, cp, buf);
michael@0 1657 }
michael@0 1658
michael@0 1659 void __GetLocaleInfoUsingACP(LCID lcid, const char* cp, LCTYPE lctype, char* buf, int buf_size, wchar_t* wbuf, int wbuf_size) {
michael@0 1660 wchar_t *Buffer;
michael@0 1661 int BufferSize;
michael@0 1662 int icp;
michael@0 1663
michael@0 1664 GetLocaleInfoA(lcid, lctype, buf, buf_size);
michael@0 1665
michael@0 1666 icp = atoi(cp);
michael@0 1667 if (icp != CP_ACP && buf[0] != 0) {
michael@0 1668 BufferSize = MultiByteToWideChar(CP_ACP, 0, buf, -1, NULL, 0);
michael@0 1669 if (BufferSize > wbuf_size)
michael@0 1670 {
michael@0 1671 Buffer = (wchar_t*)malloc(sizeof(wchar_t) * BufferSize);
michael@0 1672 }
michael@0 1673 else
michael@0 1674 {
michael@0 1675 Buffer = wbuf;
michael@0 1676 }
michael@0 1677 MultiByteToWideChar(CP_ACP, 0, buf, -1, Buffer, BufferSize);
michael@0 1678 WideCharToMultiByte(icp, 0, Buffer, -1, buf, buf_size, NULL, NULL);
michael@0 1679 if (Buffer != wbuf)
michael@0 1680 {
michael@0 1681 free(Buffer);
michael@0 1682 }
michael@0 1683 }
michael@0 1684 }
michael@0 1685
michael@0 1686 /* Return 0 if ANSI code page not used */
michael@0 1687 int __intGetACP(LCID lcid) {
michael@0 1688 char cp[6];
michael@0 1689 if (!GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE, cp, 6)) {
michael@0 1690 #if defined (_STLP_LANG_INVARIANT_DEFINED)
michael@0 1691 if (lcid == INVARIANT_LCID) {
michael@0 1692 /* We are using a limited PSDK, we rely on the most common code page */
michael@0 1693 return 1252;
michael@0 1694 }
michael@0 1695 #endif
michael@0 1696 return 0;
michael@0 1697 }
michael@0 1698 return atoi(cp);
michael@0 1699 }
michael@0 1700
michael@0 1701 /* Return 1 if OEM code page not used */
michael@0 1702 int __intGetOCP(LCID lcid) {
michael@0 1703 char cp[6];
michael@0 1704 if (!GetLocaleInfoA(lcid, LOCALE_IDEFAULTCODEPAGE, cp, 6))
michael@0 1705 return 0;
michael@0 1706 return atoi(cp);
michael@0 1707 }
michael@0 1708
michael@0 1709 int __GetDefaultCP(LCID lcid) {
michael@0 1710 int cp = __intGetACP(lcid);
michael@0 1711 if (cp == 0) return __intGetOCP(lcid);
michael@0 1712 else return cp;
michael@0 1713 }
michael@0 1714
michael@0 1715 static int trim_size_t_to_int(size_t n) { return n < (size_t)INT_MAX ? (int)n : INT_MAX; }
michael@0 1716
michael@0 1717 char* __ConvertToCP(int from_cp, int to_cp, const char *from, size_t size, size_t *ret_buf_size) {
michael@0 1718 size_t wbuffer_size, buffer_size, from_offset, wbuf_offset;
michael@0 1719 int from_size, to_size, wbuf_size;
michael@0 1720 wchar_t *wbuffer;
michael@0 1721 char* buffer;
michael@0 1722
michael@0 1723 size_t orig_size = size;
michael@0 1724
michael@0 1725 wbuffer_size = 0;
michael@0 1726 from_offset = 0;
michael@0 1727 while (size > 0) {
michael@0 1728 from_size = trim_size_t_to_int(size);
michael@0 1729 wbuffer_size += MultiByteToWideChar(from_cp, MB_PRECOMPOSED,
michael@0 1730 from + from_offset, from_size, NULL, 0);
michael@0 1731 from_offset += from_size;
michael@0 1732 size -= from_size;
michael@0 1733 }
michael@0 1734
michael@0 1735 wbuffer = (wchar_t*)malloc(sizeof(wchar_t)*wbuffer_size);
michael@0 1736
michael@0 1737 size = orig_size;
michael@0 1738 wbuf_offset = 0;
michael@0 1739 from_offset = 0;
michael@0 1740 while (size > 0) {
michael@0 1741 from_size = trim_size_t_to_int(size);
michael@0 1742 wbuf_size = trim_size_t_to_int(wbuffer_size - wbuf_offset);
michael@0 1743 wbuf_offset += MultiByteToWideChar(from_cp, MB_PRECOMPOSED,
michael@0 1744 from + from_offset, from_size, wbuffer + wbuf_offset, wbuf_size);
michael@0 1745 from_offset += from_size;
michael@0 1746 size -= from_size;
michael@0 1747 }
michael@0 1748
michael@0 1749 buffer_size = 0;
michael@0 1750 wbuf_offset = 0;
michael@0 1751 size = wbuffer_size;
michael@0 1752 while (size > 0) {
michael@0 1753 wbuf_size = trim_size_t_to_int(size);
michael@0 1754 buffer_size += WideCharToMultiByte(to_cp, WC_COMPOSITECHECK | WC_SEPCHARS,
michael@0 1755 wbuffer + wbuf_offset, wbuf_size,
michael@0 1756 NULL, 0, NULL, FALSE);
michael@0 1757 wbuf_offset += wbuf_size;
michael@0 1758 size -= wbuf_size;
michael@0 1759 }
michael@0 1760
michael@0 1761 buffer = (char*)malloc(buffer_size);
michael@0 1762 *ret_buf_size = buffer_size;
michael@0 1763
michael@0 1764 size = wbuffer_size;
michael@0 1765 wbuf_offset = 0;
michael@0 1766 while (size > 0) {
michael@0 1767 wbuf_size = trim_size_t_to_int(size);
michael@0 1768 to_size = trim_size_t_to_int(buffer_size);
michael@0 1769 buffer_size -= WideCharToMultiByte(to_cp, WC_COMPOSITECHECK | WC_SEPCHARS,
michael@0 1770 wbuffer + wbuf_offset, wbuf_size,
michael@0 1771 buffer, to_size, NULL, FALSE);
michael@0 1772 wbuf_offset += wbuf_size;
michael@0 1773 size -= wbuf_size;
michael@0 1774 }
michael@0 1775
michael@0 1776 free(wbuffer);
michael@0 1777 return buffer;
michael@0 1778 }
michael@0 1779
michael@0 1780 #ifdef __cplusplus
michael@0 1781 }
michael@0 1782 #endif
michael@0 1783
michael@0 1784 #ifndef _STLP_NO_WCHAR_T
michael@0 1785 # include "c_wlocale_win32.c"
michael@0 1786 #endif

mercurial