ReactOS Fundraising Campaign 2012
 
€ 4,060 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

c_locale_win32.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1999
00003  * Silicon Graphics Computer Systems, Inc.
00004  *
00005  * Copyright (c) 1999
00006  * Boris Fomitchev
00007  *
00008  * Written 2000
00009  * Anton Lapach
00010  *
00011  * This material is provided "as is", with absolutely no warranty expressed
00012  * or implied. Any use is at your own risk.
00013  *
00014  * Permission to use or copy this software for any purpose is hereby granted
00015  * without fee, provided the above notices are retained on all copies.
00016  * Permission to modify the code and to distribute modified code is granted,
00017  * provided the above notices are retained, and a notice that the code was
00018  * modified is included with the above copyright notice.
00019  *
00020  */
00021 
00022 #include <limits.h>
00023 #if defined (_STLP_MSVC) || defined (__ICL)
00024 #  include <memory.h>
00025 #endif
00026 #include <string.h>
00027 #include <locale.h>
00028 #include <stdlib.h>
00029 #include <stdio.h>
00030 
00031 #if defined (_STLP_USE_SAFE_STRING_FUNCTIONS)
00032 #  define _STLP_STRCPY(D, DS, S) strcpy_s(D, DS, S)
00033 #  define _STLP_STRNCPY(D, DS, S, C) strncpy_s(D, DS, S, C)
00034 #  define _STLP_STRCAT(D, DS, S) strcat_s(D, DS, S)
00035 #else
00036 #  define _STLP_STRCPY(D, DS, S) strcpy(D, S)
00037 #  define _STLP_STRNCPY(D, DS, S, C) strncpy(D, S, C)
00038 #  define _STLP_STRCAT(D, DS, S) strcat(D, S)
00039 #endif
00040 
00041 #if defined (__cplusplus)
00042 extern "C" {
00043 #endif
00044 
00045 /* Framework functions */
00046 /*
00047   locale :: "lang[_country[.code_page]]"
00048   | ".code_page"
00049   | ""
00050   | NULL
00051 
00052 */
00053 
00054 typedef struct _LOCALECONV {
00055   const char* name;
00056   const char* abbrev;
00057 } LOCALECONV;
00058 
00059 #define MAX_LANG_LEN        64  /* max language name length */
00060 #define MAX_CTRY_LEN        64  /* max country name length */
00061 #define MAX_MODIFIER_LEN    0   /* max modifier name length - n/a */
00062 #define MAX_LC_LEN          (MAX_LANG_LEN+MAX_CTRY_LEN+MAX_MODIFIER_LEN+3)
00063                                 /* max entire locale string length */
00064 #define MAX_CP_LEN          5   /* max code page name length */
00065 
00066 #if !defined (LANG_INVARIANT)
00067 #  define LANG_INVARIANT 0x7f
00068 #  define _STLP_LANG_INVARIANT_DEFINED
00069 #endif
00070 
00071 #ifndef CP_UTF7
00072 #  define CP_UTF7 65000
00073 #endif
00074 
00075 #ifndef CP_UTF8
00076 #  define CP_UTF8 65001
00077 #endif
00078 
00079 #define INVARIANT_LCID MAKELCID(MAKELANGID(LANG_INVARIANT, SUBLANG_NEUTRAL), SORT_DEFAULT)
00080 
00081 static const char *_C_name = "C";
00082 
00083 /*  non-NLS language string table */
00084 static LOCALECONV __rg_language[] = {
00085   {"american",                    "ENU"},
00086   {"american english",            "ENU"},
00087   {"american-english",            "ENU"},
00088   {"australian",                  "ENA"},
00089   {"belgian",                     "NLB"},
00090   {"canadian",                    "ENC"},
00091   {"chh",                         "ZHH"},
00092   {"chi",                         "ZHI"},
00093   {"chinese",                     "CHS"},
00094   {"chinese-hongkong",            "ZHH"},
00095   {"chinese-simplified",          "CHS"},
00096   {"chinese-singapore",           "ZHI"},
00097   {"chinese-traditional",         "CHT"},
00098   {"dutch-belgian",               "NLB"},
00099   {"english-american",            "ENU"},
00100   {"english-aus",                 "ENA"},
00101   {"english-belize",              "ENL"},
00102   {"english-can",                 "ENC"},
00103   {"english-caribbean",           "ENB"},
00104   {"english-ire",                 "ENI"},
00105   {"english-jamaica",             "ENJ"},
00106   {"english-nz",                  "ENZ"},
00107   {"english-south africa",        "ENS"},
00108   {"english-trinidad y tobago",   "ENT"},
00109   {"english-uk",                  "ENG"},
00110   {"english-us",                  "ENU"},
00111   {"english-usa",                 "ENU"},
00112   {"french-belgian",              "FRB"},
00113   {"french-canadian",             "FRC"},
00114   {"french-luxembourg",           "FRL"},
00115   {"french-swiss",                "FRS"},
00116   {"german-austrian",             "DEA"},
00117   {"german-lichtenstein",         "DEC"},
00118   {"german-luxembourg",           "DEL"},
00119   {"german-swiss",                "DES"},
00120   {"irish-english",               "ENI"},
00121   {"italian-swiss",               "ITS"},
00122   {"norwegian",                   "NOR"},
00123   {"norwegian-bokmal",            "NOR"},
00124   {"norwegian-nynorsk",           "NON"},
00125   {"portuguese-brazilian",        "PTB"},
00126   {"spanish-argentina",           "ESS"},
00127   {"spanish-bolivia",             "ESB"},
00128   {"spanish-chile",               "ESL"},
00129   {"spanish-colombia",            "ESO"},
00130   {"spanish-costa rica",          "ESC"},
00131   {"spanish-dominican republic",  "ESD"},
00132   {"spanish-ecuador",             "ESF"},
00133   {"spanish-el salvador",         "ESE"},
00134   {"spanish-guatemala",           "ESG"},
00135   {"spanish-honduras",            "ESH"},
00136   {"spanish-mexican",             "ESM"},
00137   {"spanish-modern",              "ESN"},
00138   {"spanish-nicaragua",           "ESI"},
00139   {"spanish-panama",              "ESA"},
00140   {"spanish-paraguay",            "ESZ"},
00141   {"spanish-peru",                "ESR"},
00142   {"spanish-puerto rico",         "ESU"},
00143   {"spanish-uruguay",             "ESY"},
00144   {"spanish-venezuela",           "ESV"},
00145   {"swedish-finland",             "SVF"},
00146   {"swiss",                       "DES"},
00147   {"uk",                          "ENG"},
00148   {"us",                          "ENU"},
00149   {"usa",                         "ENU"}
00150 };
00151 
00152 /*  non-NLS country string table */
00153 static LOCALECONV __rg_country[] = {
00154   {"america",                     "USA"},
00155   {"britain",                     "GBR"},
00156   {"china",                       "CHN"},
00157   {"czech",                       "CZE"},
00158   {"england",                     "GBR"},
00159   {"great britain",               "GBR"},
00160   {"holland",                     "NLD"},
00161   {"hong-kong",                   "HKG"},
00162   {"new-zealand",                 "NZL"},
00163   {"nz",                          "NZL"},
00164   {"pr china",                    "CHN"},
00165   {"pr-china",                    "CHN"},
00166   {"puerto-rico",                 "PRI"},
00167   {"slovak",                      "SVK"},
00168   {"south africa",                "ZAF"},
00169   {"south korea",                 "KOR"},
00170   {"south-africa",                "ZAF"},
00171   {"south-korea",                 "KOR"},
00172   {"trinidad & tobago",           "TTO"},
00173   {"uk",                          "GBR"},
00174   {"united-kingdom",              "GBR"},
00175   {"united-states",               "USA"},
00176   {"us",                          "USA"},
00177 };
00178 
00179 typedef struct _Locale_name_hint {
00180   LCID id;
00181 } _Locale_lcid_t;
00182 
00183 typedef struct _Locale_ctype {
00184   _Locale_lcid_t lc;
00185   UINT cp;
00186   unsigned short ctable[256];
00187 } _Locale_ctype_t;
00188 
00189 typedef struct _Locale_numeric {
00190   _Locale_lcid_t lc;
00191   char cp[MAX_CP_LEN + 1];
00192   char decimal_point[4];
00193   char thousands_sep[4];
00194   char *grouping;
00195 } _Locale_numeric_t;
00196 
00197 typedef struct _Locale_time {
00198   _Locale_lcid_t lc;
00199   char cp[MAX_CP_LEN + 1];
00200   char *month[12];
00201   char *abbrev_month[12];
00202   char *dayofweek[7];
00203   char *abbrev_dayofweek[7];
00204   char *date_time_format;
00205   char *long_date_time_format;
00206   char *date_format;
00207   char *long_date_format;
00208   char *time_format;
00209   char am[9];
00210   char pm[9];
00211 } _Locale_time_t;
00212 
00213 typedef struct _Locale_collate {
00214   _Locale_lcid_t lc;
00215   char cp[MAX_CP_LEN + 1];
00216 } _Locale_collate_t;
00217 
00218 typedef struct _Locale_monetary {
00219   _Locale_lcid_t lc;
00220   char cp[MAX_CP_LEN + 1];
00221   char decimal_point[4];
00222   char thousands_sep[4];
00223   char *grouping;
00224   char int_curr_symbol[5]; /* 3 + 1 + 1 */
00225   char curr_symbol[6];
00226   char negative_sign[5];
00227   char positive_sign[5];
00228   int frac_digits;
00229   int int_frac_digits;
00230 } _Locale_monetary_t;
00231 
00232 /* Internal function */
00233 static void __FixGrouping(char *grouping);
00234 static const char* __ConvertName(const char* lname, LOCALECONV* ConvTable, int TableSize);
00235 static int __ParseLocaleString(const char* lname, char* lang, char* ctry, char* page);
00236 static int __GetLCID(const char* lang, const char* ctry, LCID* lcid);
00237 static int __GetLCIDFromName(const char* lname, LCID* lcid, char *cp, _Locale_lcid_t *hint);
00238 static char const* __GetLocaleName(LCID lcid, const char* cp, char* buf);
00239 static char const* __Extract_locale_name(const char* loc, const char* category, char* buf);
00240 static char const* __TranslateToSystem(const char* lname, char* buf, _Locale_lcid_t* hint, int *__err_code);
00241 static void __GetLocaleInfoUsingACP(LCID lcid, const char* cp, LCTYPE lctype, char* buf, int buf_size, wchar_t* wbuf, int wbuf_size);
00242 static int __intGetACP(LCID lcid);
00243 static int __intGetOCP(LCID lcid);
00244 static int __GetDefaultCP(LCID lcid);
00245 static char* __ConvertToCP(int from_cp, int to_cp, const char *from, size_t size, size_t *ret_buf_size);
00246 static void my_ltoa(long __x, char* buf);
00247 
00248 void my_ltoa(long __x, char* buf) {
00249   char rbuf[64];
00250   char* ptr = rbuf;
00251 
00252   if (__x == 0)
00253     *ptr++ = '0';
00254   else {
00255     for (; __x != 0; __x /= 10)
00256       *ptr++ = (char)(__x % 10) + '0';
00257   }
00258   while(ptr > rbuf) *buf++ = *--ptr;
00259   /* psw */
00260   *buf = '\0';
00261 }
00262 
00263 #if defined (__cplusplus)
00264 _STLP_BEGIN_NAMESPACE
00265 extern "C" {
00266 #endif
00267 
00268 _Locale_lcid_t* _Locale_get_ctype_hint(_Locale_ctype_t* ltype)
00269 { return (ltype != 0) ? &ltype->lc : 0; }
00270 _Locale_lcid_t* _Locale_get_numeric_hint(_Locale_numeric_t* lnumeric)
00271 { return (lnumeric != 0) ? &lnumeric->lc : 0; }
00272 _Locale_lcid_t* _Locale_get_time_hint(_Locale_time_t* ltime)
00273 { return (ltime != 0) ? &ltime->lc : 0; }
00274 _Locale_lcid_t* _Locale_get_collate_hint(_Locale_collate_t* lcollate)
00275 { return (lcollate != 0) ? &lcollate->lc : 0; }
00276 _Locale_lcid_t* _Locale_get_monetary_hint(_Locale_monetary_t* lmonetary)
00277 { return (lmonetary != 0) ? &lmonetary->lc : 0; }
00278 _Locale_lcid_t* _Locale_get_messages_hint(struct _Locale_messages* lmessages) {
00279   _STLP_MARK_PARAMETER_AS_UNUSED(lmessages)
00280   return 0;
00281 }
00282 
00283 #define MAP(x, y) if ((mask & x) != 0) ret |= (y)
00284 unsigned short MapCtypeMask(unsigned short mask) {
00285   unsigned short ret = 0;
00286   MAP(C1_UPPER, _Locale_UPPER | _Locale_PRINT);
00287   MAP(C1_LOWER, _Locale_LOWER | _Locale_PRINT);
00288   MAP(C1_DIGIT, _Locale_DIGIT | _Locale_PRINT);
00289   MAP(C1_SPACE, _Locale_SPACE | _Locale_PRINT);
00290   MAP(C1_PUNCT, _Locale_PUNCT | _Locale_PRINT);
00291   /* MAP(C1_BLANK, ?); */
00292   MAP(C1_XDIGIT, _Locale_XDIGIT | _Locale_PRINT);
00293   MAP(C1_ALPHA, _Locale_ALPHA | _Locale_PRINT);
00294   if ((mask & C1_CNTRL) != 0) { ret |= _Locale_CNTRL; ret &= ~_Locale_PRINT; }
00295   return ret;
00296 }
00297 
00298 static void MapCtypeMasks(unsigned short *cur, unsigned short *end) {
00299   for (; cur != end; ++cur) {
00300     *cur = MapCtypeMask(*cur);
00301   }
00302 }
00303 
00304 _Locale_ctype_t* _Locale_ctype_create(const char * name, _Locale_lcid_t* lc_hint, int *__err_code) {
00305   char cp_name[MAX_CP_LEN + 1];
00306   int NativeCP;
00307   unsigned char Buffer[256];
00308   unsigned char *ptr;
00309   CPINFO CPInfo;
00310   int i;
00311   wchar_t *wbuffer;
00312   int BufferSize;
00313 
00314   _Locale_ctype_t *ltype = (_Locale_ctype_t*)malloc(sizeof(_Locale_ctype_t));
00315 
00316   if (!ltype) { *__err_code = _STLP_LOC_NO_MEMORY; return ltype; }
00317   memset(ltype, 0, sizeof(_Locale_ctype_t));
00318 
00319   if (__GetLCIDFromName(name, &ltype->lc.id, cp_name, lc_hint) == -1)
00320   { free(ltype); *__err_code = _STLP_LOC_UNKNOWN_NAME; return NULL; }
00321 
00322 #if defined (__BORLANDC__)
00323   if ( ltype->lc.id == INVARIANT_LCID && name[0] == 'C' && name[1] == 0 )
00324   { ltype->lc.id = 0x409; }
00325 #endif
00326 
00327   ltype->cp = atoi(cp_name);
00328 
00329   NativeCP = __GetDefaultCP(ltype->lc.id);
00330 
00331   /* Make table with all characters. */
00332   for (i = 0; i < 256; ++i) Buffer[i] = (unsigned char)i;
00333 
00334   if (!GetCPInfo(NativeCP, &CPInfo)) { free(ltype); return NULL; }
00335 
00336   if (CPInfo.MaxCharSize > 1) {
00337     for (ptr = (unsigned char*)CPInfo.LeadByte; *ptr && *(ptr + 1); ptr+=2)
00338       for (i = *ptr; i <= *(ptr + 1); ++i) Buffer[i] = 0;
00339   }
00340 
00341   if ((UINT)NativeCP != ltype->cp) {
00342     OSVERSIONINFO ver_info;
00343     ver_info.dwOSVersionInfoSize = sizeof(ver_info);
00344     GetVersionEx(&ver_info);
00345     if (ver_info.dwPlatformId == VER_PLATFORM_WIN32_NT) {
00346       /* Convert character sequence to Unicode. */
00347       BufferSize = MultiByteToWideChar(ltype->cp, MB_PRECOMPOSED, (const char*)Buffer, 256, NULL, 0);
00348       if (!BufferSize) { free(ltype); *__err_code = _STLP_LOC_UNKNOWN_NAME; return NULL; }
00349       wbuffer = (wchar_t*)malloc(BufferSize * sizeof(wchar_t));
00350       if (!wbuffer) { free(ltype); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }
00351       MultiByteToWideChar(ltype->cp, MB_PRECOMPOSED, (const char*)Buffer, 256, wbuffer, BufferSize);
00352 
00353       GetStringTypeW(CT_CTYPE1, wbuffer, 256, ltype->ctable);
00354       MapCtypeMasks(ltype->ctable, ltype->ctable + 256);
00355       free(wbuffer);
00356     }
00357     else {
00358       unsigned short ctable[256];
00359       unsigned char TargetBuffer[256];
00360       GetStringTypeA(ltype->lc.id, CT_CTYPE1, (const char*)Buffer, 256, ctable);
00361 
00362       /* Convert character sequence to target code page. */
00363       BufferSize = MultiByteToWideChar(NativeCP, MB_PRECOMPOSED, (const char*)Buffer, 256, NULL, 0);
00364       if (!BufferSize) { free(ltype); *__err_code = _STLP_LOC_UNKNOWN_NAME; return NULL; }
00365       wbuffer = (wchar_t*)malloc(BufferSize * sizeof(wchar_t));
00366       if (!wbuffer) { free(ltype); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }
00367       MultiByteToWideChar(NativeCP, MB_PRECOMPOSED, (const char*)Buffer, 256, wbuffer, BufferSize);
00368       if (!WideCharToMultiByte(ltype->cp, WC_COMPOSITECHECK | WC_SEPCHARS, wbuffer, BufferSize, (char*)TargetBuffer, 256, NULL, FALSE))
00369       { free(wbuffer); free(ltype); *__err_code = _STLP_LOC_UNKNOWN_NAME; return NULL; }
00370 
00371       free(wbuffer);
00372 
00373       /* Translate ctype table. */
00374       for (i = 0; i < 256; ++i) {
00375         if (!TargetBuffer[i]) continue;
00376         ltype->ctable[TargetBuffer[i]] = MapCtypeMask(ctable[i]);
00377       }
00378     }
00379   }
00380   else {
00381     GetStringTypeA(ltype->lc.id, CT_CTYPE1, (const char*)Buffer, 256, ltype->ctable);
00382     MapCtypeMasks(ltype->ctable, ltype->ctable + 256);
00383   }
00384   return ltype;
00385 }
00386 
00387 _Locale_numeric_t* _Locale_numeric_create(const char * name, _Locale_lcid_t* lc_hint, int *__err_code) {
00388   wchar_t wbuf[4];
00389   char *GroupingBuffer;
00390   int BufferSize;
00391 
00392   _Locale_numeric_t *lnum = (_Locale_numeric_t*)malloc(sizeof(_Locale_numeric_t));
00393   if (!lnum) { *__err_code = _STLP_LOC_NO_MEMORY; return lnum; }
00394   memset(lnum, 0, sizeof(_Locale_numeric_t));
00395 
00396   if (__GetLCIDFromName(name, &lnum->lc.id, lnum->cp, lc_hint) == -1)
00397   { free(lnum); *__err_code = _STLP_LOC_UNKNOWN_NAME; return NULL; }
00398 
00399 #if defined (__BORLANDC__)
00400   if (lnum->lc.id != INVARIANT_LCID) {
00401 #endif
00402   __GetLocaleInfoUsingACP(lnum->lc.id, lnum->cp, LOCALE_SDECIMAL, lnum->decimal_point, 4, wbuf, 4);
00403   __GetLocaleInfoUsingACP(lnum->lc.id, lnum->cp, LOCALE_STHOUSAND, lnum->thousands_sep, 4, wbuf, 4);
00404 #if defined (__BORLANDC__)
00405   }
00406   else
00407     lnum->decimal_point[0] = '.';
00408 #endif
00409 
00410   if (lnum->lc.id != INVARIANT_LCID) {
00411     BufferSize = GetLocaleInfoA(lnum->lc.id, LOCALE_SGROUPING, NULL, 0);
00412     GroupingBuffer = (char*)malloc(BufferSize);
00413     if (!GroupingBuffer) { free(lnum); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }
00414     GetLocaleInfoA(lnum->lc.id, LOCALE_SGROUPING, GroupingBuffer, BufferSize);
00415     __FixGrouping(GroupingBuffer);
00416     lnum->grouping = GroupingBuffer;
00417   }
00418   else {
00419     lnum->grouping = (char*)malloc(1);
00420     if (!lnum->grouping) { free(lnum); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }
00421     lnum->grouping[0] = 0;
00422   }
00423 
00424   return lnum;
00425 }
00426 
00427 static int __ConvertDate(const char *NTDate, char *buffer, int buf_size) {
00428   /* This function will return an incomplete buffer if buffer is not long enough */
00429   const char *cur_char;
00430   char *cur_output, *end_output;
00431 
00432   /* Correct time format. */
00433   cur_char = NTDate;
00434   cur_output = buffer;
00435   end_output = cur_output + buf_size;
00436   buf_size = 0;
00437   while (*cur_char) {
00438     if (cur_output && (cur_output == end_output)) break;
00439     switch (*cur_char) {
00440     case 'd':
00441     {
00442       if (*(cur_char + 1) == 'd') {
00443         if (cur_output && (cur_output + 2 > end_output)) {
00444           *cur_output = 0;
00445           return ++buf_size;
00446         }
00447         if (*(cur_char + 2) == 'd') {
00448           if (*(cur_char + 3) == 'd') {
00449             if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = 'A'; }
00450             buf_size += 2;
00451             cur_char += 3;
00452           }
00453           else {
00454             if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = 'a'; }
00455             buf_size += 2;
00456             cur_char += 2;
00457           }
00458         }
00459         else {
00460           if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = 'd'; }
00461           buf_size += 2;
00462           cur_char++;
00463         }
00464       }
00465       else {
00466         if (cur_output && (cur_output + 3 > end_output)) {
00467           *cur_output = 0;
00468           return ++buf_size;
00469         }
00470         if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = '#'; *(cur_output++) = 'd'; }
00471         buf_size += 3;
00472       }
00473     }
00474     break;
00475     case 'M':
00476     {
00477       if (*(cur_char + 1) == 'M') {
00478         if (cur_output && (cur_output + 2 > end_output)) {
00479           *cur_output = 0;
00480           return ++buf_size;
00481         }
00482         if (*(cur_char + 2) == 'M') {
00483           if (*(cur_char + 3) == 'M') {
00484             if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = 'B'; }
00485             buf_size += 2;
00486             cur_char += 3;
00487           }
00488           else {
00489             if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = 'b'; }
00490             buf_size += 2;
00491             cur_char += 2;
00492           }
00493         }
00494         else {
00495           if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = 'm'; }
00496           buf_size += 2;
00497           cur_char++;
00498         }
00499       }
00500       else {
00501         if (cur_output && (cur_output + 3 > end_output)) {
00502           *cur_output = 0;
00503           return ++buf_size;
00504         }
00505         if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = '#'; *(cur_output++) = 'm'; }
00506         buf_size += 3;
00507       }
00508     }
00509     break;
00510     case 'y':
00511     {
00512       if (*(cur_char + 1) == 'y') {
00513         if (cur_output && (cur_output + 2 > end_output)) {
00514           *cur_output = 0;
00515           return ++buf_size;
00516         }
00517         if (*(cur_char + 2) == 'y' && *(cur_char + 3) == 'y') {
00518           if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = 'Y'; }
00519           buf_size += 2;
00520           cur_char += 3;
00521         }
00522         else {
00523           if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = 'y'; }
00524           buf_size += 2;
00525           cur_char++;
00526         }
00527       }
00528       else {
00529         if (cur_output && (cur_output + 3 > end_output)) {
00530           *cur_output = 0;
00531           return ++buf_size;
00532         }
00533         if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = '#'; *(cur_output++) = 'y'; }
00534         buf_size += 3;
00535       }
00536     }
00537     break;
00538     case '%':
00539     {
00540       if (cur_output && (cur_output + 2 > end_output)) {
00541         *cur_output = 0;
00542         return ++buf_size;
00543       }
00544       if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = '%'; }
00545       buf_size += 2;
00546     }
00547     break;
00548     case '\'':
00549     {
00550       ++cur_char;
00551       while (*cur_char != '\'' && *cur_char != 0 && (cur_output == NULL || cur_output != end_output)) {
00552         if (cur_output) { *cur_output++ = *cur_char; }
00553         ++cur_char;
00554         buf_size += 1;
00555       }
00556     }
00557     break;
00558     default:
00559     {
00560       if (cur_output) { *(cur_output++) = *cur_char; }
00561       buf_size += 1;
00562     }
00563     break;
00564     }
00565     if (*cur_char == 0) break;
00566     ++cur_char;
00567   }
00568 
00569   if (!cur_output || cur_output != end_output) {
00570     if (cur_output) *cur_output = 0;
00571     buf_size += 1;
00572   }
00573   else {
00574     /* We trunc result */
00575     *(--cur_output) = 0;
00576   }
00577 
00578   return buf_size;
00579 }
00580 
00581 static int __ConvertTime(const char *NTTime, char *buffer, int buf_size) {
00582   const char *cur_char;
00583   char *cur_output, *end_output;
00584   cur_char = NTTime;
00585   cur_output = buffer;
00586   end_output = cur_output + buf_size;
00587   buf_size = 0;
00588   while (*cur_char) {
00589     switch(*cur_char) {
00590     case 'h':
00591       if (*(cur_char + 1) == 'h') {
00592         if (cur_output && (cur_output + 2 > end_output)) {
00593           *cur_output = 0;
00594           return ++buf_size;
00595         }
00596         if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = 'I'; }
00597         buf_size += 2;
00598         ++cur_char;
00599       }
00600       else {
00601         if (cur_output && (cur_output + 3 > end_output)) {
00602           *cur_output = 0;
00603           return ++buf_size;
00604         }
00605         if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = '#'; *(cur_output++) = 'I'; }
00606         buf_size += 3;
00607       }
00608       break;
00609     case 'H':
00610       if (*(cur_char + 1) == 'H') {
00611         if (cur_output && (cur_output + 2 > end_output)) {
00612           *cur_output = 0;
00613           return ++buf_size;
00614         }
00615         if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = 'H'; }
00616         buf_size += 2;
00617         ++cur_char;
00618       }
00619       else {
00620         if (cur_output && (cur_output + 3 > end_output)) {
00621           *cur_output = 0;
00622           return ++buf_size;
00623         }
00624         if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = '#'; *(cur_output++) = 'H'; }
00625         buf_size += 3;
00626       }
00627       break;
00628     case 'm':
00629       if (*(cur_char + 1) == 'm') {
00630         if (cur_output && (cur_output + 2 > end_output)) {
00631           *cur_output = 0;
00632           return ++buf_size;
00633         }
00634         if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = 'M'; }
00635         buf_size += 2;
00636         cur_char++;
00637       }
00638       else {
00639         if (cur_output && (cur_output + 3 > end_output)) {
00640           *cur_output = 0;
00641           return ++buf_size;
00642         }
00643         if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = '#'; *(cur_output++) = 'M'; }
00644         buf_size += 3;
00645       }
00646       break;
00647     case 's':
00648       if (*(cur_char + 1) == 's') {
00649         if (cur_output && (cur_output + 2 > end_output)) {
00650           *cur_output = 0;
00651           return ++buf_size;
00652         }
00653         if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = 'S'; }
00654         buf_size += 2;
00655         ++cur_char;
00656       }
00657       else {
00658         if (cur_output && (cur_output + 3 > end_output)) {
00659           *cur_output = 0;
00660           return ++buf_size;
00661         }
00662         if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = '#'; *(cur_output++) = 'S'; }
00663         buf_size += 3;
00664       }
00665       break;
00666     case 't':
00667       if (*(cur_char + 1) == 't')
00668         ++cur_char;
00669       if (cur_output && (cur_output + 2 > end_output)) {
00670         *cur_output = 0;
00671         return ++buf_size;
00672       }
00673       if (cur_output) { *(cur_output++) = '%'; *(cur_output++) = 'p'; }
00674       buf_size += 2;
00675       break;
00676     case '%':
00677       if (cur_output && (cur_output + 2 > end_output)) {
00678         *cur_output = 0;
00679         return ++buf_size;
00680       }
00681       if (cur_output) { *(cur_output++)='%'; *(cur_output++)='%'; }
00682       buf_size += 2;
00683       break;
00684     case '\'':
00685       ++cur_char;
00686       while (*cur_char != '\'' && *cur_char != 0 && (!cur_output || (cur_output != end_output))) {
00687         if (cur_output) *cur_output++ = *cur_char;
00688         ++cur_char;
00689         buf_size += 1;
00690       }
00691       break;
00692     default:
00693       if (cur_output) { *(cur_output++) = *cur_char; }
00694       buf_size += 1;
00695       break;
00696     }
00697     if (*cur_char == 0) break;
00698     ++cur_char;
00699   }
00700 
00701   if (!cur_output || cur_output != end_output) {
00702     if (cur_output) *cur_output = 0;
00703     buf_size += 1;
00704   }
00705   else {
00706     /* We trunc result */
00707     *(--cur_output) = 0;
00708   }
00709 
00710   return buf_size;
00711 }
00712 
00713 _Locale_time_t* _Locale_time_create(const char * name, _Locale_lcid_t* lc_hint, int *__err_code) {
00714   int size, month, dayofweek;
00715   size_t length;
00716   char fmt80[80];
00717   wchar_t wbuf80[80];
00718 
00719   _Locale_time_t *ltime = (_Locale_time_t*)malloc(sizeof(_Locale_time_t));
00720   
00721   if (!ltime) { *__err_code = _STLP_LOC_NO_MEMORY; return ltime; }
00722   memset(ltime, 0, sizeof(_Locale_time_t));
00723 
00724   if (__GetLCIDFromName(name, &ltime->lc.id, ltime->cp, lc_hint) == -1)
00725   { free(ltime); *__err_code = _STLP_LOC_UNKNOWN_NAME; return NULL; }
00726 
00727 #if defined (__BORLANDC__)
00728   if ( ltime->lc.id == INVARIANT_LCID && name[0] == 'C' && name[1] == 0 )
00729   { ltime->lc.id = 0x409; }
00730 #endif
00731 
00732   for (month = LOCALE_SMONTHNAME1; month <= LOCALE_SMONTHNAME12; ++month) { /* Small hack :-) */
00733     size = GetLocaleInfoA(ltime->lc.id, month, NULL, 0);
00734     ltime->month[month - LOCALE_SMONTHNAME1] = (char*)malloc(size);
00735     if (!ltime->month[month - LOCALE_SMONTHNAME1])
00736     { _Locale_time_destroy(ltime); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }
00737     __GetLocaleInfoUsingACP(ltime->lc.id, ltime->cp, month, ltime->month[month - LOCALE_SMONTHNAME1], size, wbuf80, 80);
00738   }
00739 
00740   for (month = LOCALE_SABBREVMONTHNAME1; month <= LOCALE_SABBREVMONTHNAME12; ++month) {
00741     size = GetLocaleInfoA(ltime->lc.id, month, NULL, 0);
00742     ltime->abbrev_month[month - LOCALE_SABBREVMONTHNAME1] = (char*)malloc(size);
00743     if (!ltime->abbrev_month[month - LOCALE_SABBREVMONTHNAME1])
00744     { _Locale_time_destroy(ltime); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }
00745     __GetLocaleInfoUsingACP(ltime->lc.id, ltime->cp, month, ltime->abbrev_month[month - LOCALE_SABBREVMONTHNAME1], size, wbuf80, 80);
00746   }
00747 
00748   for (dayofweek = LOCALE_SDAYNAME1; dayofweek <= LOCALE_SDAYNAME7; ++dayofweek) {
00749     int dayindex = ( dayofweek != LOCALE_SDAYNAME7 ) ? dayofweek - LOCALE_SDAYNAME1 + 1 : 0;
00750     size = GetLocaleInfoA(ltime->lc.id, dayofweek, NULL, 0);
00751     ltime->dayofweek[dayindex] = (char*)malloc(size);
00752     if (!ltime->dayofweek[dayindex])
00753     { _Locale_time_destroy(ltime); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }
00754     __GetLocaleInfoUsingACP(ltime->lc.id, ltime->cp, dayofweek, ltime->dayofweek[dayindex], size, wbuf80, 80);
00755   }
00756 
00757   for (dayofweek = LOCALE_SABBREVDAYNAME1; dayofweek <= LOCALE_SABBREVDAYNAME7; ++dayofweek) {
00758     int dayindex = ( dayofweek != LOCALE_SABBREVDAYNAME7 ) ? dayofweek - LOCALE_SABBREVDAYNAME1 + 1 : 0;
00759     size = GetLocaleInfoA(ltime->lc.id, dayofweek, NULL, 0);
00760     ltime->abbrev_dayofweek[dayindex] = (char*)malloc(size);
00761     if (!ltime->abbrev_dayofweek[dayindex])
00762     { _Locale_time_destroy(ltime); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }
00763     __GetLocaleInfoUsingACP(ltime->lc.id, ltime->cp, dayofweek, ltime->abbrev_dayofweek[dayindex], size, wbuf80, 80);
00764   }
00765 
00766   __GetLocaleInfoUsingACP(ltime->lc.id, ltime->cp, LOCALE_SSHORTDATE, fmt80, 80, wbuf80, 80);
00767   size = __ConvertDate(fmt80, NULL, 0);
00768   ltime->date_format = (char*)malloc(size);
00769   if (!ltime->date_format)
00770   { _Locale_time_destroy(ltime); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }
00771   __ConvertDate(fmt80, ltime->date_format, size);
00772 
00773   __GetLocaleInfoUsingACP(ltime->lc.id, ltime->cp, LOCALE_SLONGDATE, fmt80, 80, wbuf80, 80);
00774   size = __ConvertDate(fmt80, NULL, 0);
00775   ltime->long_date_format = (char*)malloc(size);
00776   if (!ltime->long_date_format)
00777   { _Locale_time_destroy(ltime);*__err_code = _STLP_LOC_NO_MEMORY; return NULL; }
00778   __ConvertDate(fmt80, ltime->long_date_format, size);
00779 
00780   __GetLocaleInfoUsingACP(ltime->lc.id, ltime->cp, LOCALE_STIMEFORMAT, fmt80, 80, wbuf80, 80);
00781   size = __ConvertTime(fmt80, NULL, 0);
00782   ltime->time_format = (char*)malloc(size);
00783   if (!ltime->time_format)
00784   { _Locale_time_destroy(ltime); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }
00785   __ConvertTime(fmt80, ltime->time_format, size);
00786 
00787   /* NT doesn't provide this information, we must simulate. */
00788   length = strlen(ltime->date_format) + strlen(ltime->time_format) + 1 /* space */ + 1 /* trailing 0 */;
00789   ltime->date_time_format = (char*)malloc(length);
00790   if (!ltime->date_time_format)
00791   { _Locale_time_destroy(ltime); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }
00792   _STLP_STRCPY(ltime->date_time_format, length, ltime->date_format);
00793   _STLP_STRCAT(ltime->date_time_format, length, " ");
00794   _STLP_STRCAT(ltime->date_time_format, length, ltime->time_format);
00795 
00796   /* NT doesn't provide this information, we must simulate. */
00797   length = strlen(ltime->long_date_format) + strlen(ltime->time_format) + 1 /* space */ + 1 /* trailing 0 */;
00798   ltime->long_date_time_format = (char*)malloc(length);
00799   if (!ltime->long_date_time_format)
00800   { _Locale_time_destroy(ltime); *__err_code = _STLP_LOC_NO_MEMORY; return NULL; }
00801   _STLP_STRCPY(ltime->long_date_time_format, length, ltime->long_date_format);
00802   _STLP_STRCAT(ltime->long_date_time_format, length, " ");
00803   _STLP_STRCAT(ltime->long_date_time_format, length, ltime->time_format);
00804 
00805   __GetLocaleInfoUsingACP(ltime->lc.id, ltime->cp, LOCALE_S1159, ltime->am, 9, wbuf80, 80);
00806   __GetLocaleInfoUsingACP(ltime->lc.id, ltime->cp, LOCALE_S2359, ltime->pm, 9, wbuf80, 80);
00807 
00808   return ltime;
00809 }
00810 
00811 _Locale_collate_t* _Locale_collate_create(const char * name, _Locale_lcid_t* lc_hint, int *__err_code) {
00812   _Locale_collate_t *lcol = (_Locale_collate_t*)malloc(sizeof(_Locale_collate_t));
00813   if (!lcol) { *__err_code = _STLP_LOC_NO_MEMORY; return lcol; }
00814   memset(lcol, 0, sizeof(_Locale_collate_t));
00815 
00816   if (__GetLCIDFromName(name, &lcol->lc.id, lcol->cp, lc_hint) == -1)
00817   { free(lcol); *__err_code = _STLP_LOC_UNKNOWN_NAME; return NULL; }
00818 
00819 #if defined (__BORLANDC__)
00820   if ( lcol->lc.id == INVARIANT_LCID && name[0] == 'C' && name[1] == 0 )
00821   { lcol->lc.id = 0x409; }
00822 #endif
00823 
00824   return lcol;
00825 }
00826 
00827 _Locale_monetary_t* _Locale_monetary_create(const char * name, _Locale_lcid_t* lc_hint, int *__err_code) {
00828   char *GroupingBuffer;
00829   int BufferSize;
00830   char FracDigits[3];
00831   wchar_t wbuf[6];
00832 
00833   _Locale_monetary_t *lmon = (_Locale_monetary_t*)malloc(sizeof(_Locale_monetary_t));
00834   if (!lmon) { *__err_code = _STLP_LOC_NO_MEMORY; return lmon; }
00835   memset(lmon, 0, sizeof(_Locale_monetary_t));
00836 
00837   if (__GetLCIDFromName(name, &lmon->lc.id, lmon->cp, lc_hint) == -1)
00838   { free(lmon); *__err_code = _STLP_LOC_UNKNOWN_NAME; return NULL; }
00839 
00840   if (lmon->lc.id != INVARIANT_LCID) {
00841     /* Extract information about monetary system */
00842     __GetLocaleInfoUsingACP(lmon->lc.id, lmon->cp, LOCALE_SDECIMAL, lmon->decimal_point, 4, wbuf, 6);
00843     __GetLocaleInfoUsingACP(lmon->lc.id, lmon->cp, LOCALE_STHOUSAND, lmon->thousands_sep, 4, wbuf, 6);
00844 
00845     BufferSize = GetLocaleInfoA(lmon->lc.id, LOCALE_SGROUPING, NULL, 0);
00846     GroupingBuffer = (char*)malloc(BufferSize);
00847     if (!GroupingBuffer)
00848     { lmon->grouping = NULL; *__err_code = _STLP_LOC_NO_MEMORY; return lmon; }
00849     GetLocaleInfoA(lmon->lc.id, LOCALE_SGROUPING, GroupingBuffer, BufferSize);
00850     __FixGrouping(GroupingBuffer);
00851     lmon->grouping = GroupingBuffer;
00852 
00853     __GetLocaleInfoUsingACP(lmon->lc.id, lmon->cp, LOCALE_SCURRENCY, lmon->curr_symbol, 6, wbuf, 6);
00854     __GetLocaleInfoUsingACP(lmon->lc.id, lmon->cp, LOCALE_SNEGATIVESIGN, lmon->negative_sign, 5, wbuf, 6);
00855     __GetLocaleInfoUsingACP(lmon->lc.id, lmon->cp, LOCALE_SPOSITIVESIGN, lmon->positive_sign, 5, wbuf, 6);
00856 
00857     GetLocaleInfoA(lmon->lc.id, LOCALE_ICURRDIGITS, FracDigits, 3);
00858     lmon->frac_digits = atoi(FracDigits);
00859 
00860     GetLocaleInfoA(lmon->lc.id, LOCALE_IINTLCURRDIGITS, FracDigits, 3);
00861     lmon->int_frac_digits = atoi(FracDigits);
00862 
00863     __GetLocaleInfoUsingACP(lmon->lc.id, lmon->cp, LOCALE_SINTLSYMBOL, lmon->int_curr_symbol, 5, wbuf, 6);
00864     /* Even if Platform SDK documentation says that the returned symbol should
00865      * be a 3 letters symbol followed by a seperation character, experimentation
00866      * has shown that no seperation character is ever appended. We are adding it
00867      * ourself to conform to the POSIX specification.
00868      */
00869     if (lmon->int_curr_symbol[3] == 0) {
00870       lmon->int_curr_symbol[3] = ' ';
00871       lmon->int_curr_symbol[4] = 0;
00872     }
00873   }
00874   /* else it is already ok */
00875 
00876   return lmon;
00877 }
00878 
00879 struct _Locale_messages* _Locale_messages_create(const char *name, _Locale_lcid_t* lc_hint, int *__err_code) {
00880   /* The Win32 API has no support for messages facet */
00881   _STLP_MARK_PARAMETER_AS_UNUSED(name)
00882   _STLP_MARK_PARAMETER_AS_UNUSED(lc_hint)
00883   *__err_code = _STLP_LOC_UNSUPPORTED_FACET_CATEGORY;
00884   return NULL;
00885 }
00886 
00887 static const char* _Locale_common_default(char* buf) {
00888   char cp[MAX_CP_LEN + 1];
00889   int CodePage = __GetDefaultCP(LOCALE_USER_DEFAULT);
00890   my_ltoa(CodePage, cp);
00891   return __GetLocaleName(LOCALE_USER_DEFAULT, cp, buf);
00892 }
00893 
00894 const char* _Locale_ctype_default(char* buf)
00895 { return _Locale_common_default(buf); }
00896 
00897 const char* _Locale_numeric_default(char * buf)
00898 { return _Locale_common_default(buf); }
00899 
00900 const char* _Locale_time_default(char* buf)
00901 { return _Locale_common_default(buf); }
00902 
00903 const char* _Locale_collate_default(char* buf)
00904 { return _Locale_common_default(buf); }
00905 
00906 const char* _Locale_monetary_default(char* buf)
00907 { return _Locale_common_default(buf); }
00908 
00909 const char* _Locale_messages_default(char* buf)
00910 { return _Locale_common_default(buf); }
00911 
00912 char const* _Locale_ctype_name(const _Locale_ctype_t* ltype, char* buf) {
00913   char cp_buf[MAX_CP_LEN + 1];
00914   my_ltoa(ltype->cp, cp_buf);
00915   return __GetLocaleName(ltype->lc.id, cp_buf, buf);
00916 }
00917 
00918 char const* _Locale_numeric_name(const _Locale_numeric_t* lnum, char* buf)
00919 { return __GetLocaleName(lnum->lc.id, lnum->cp, buf); }
00920 
00921 char const* _Locale_time_name(const _Locale_time_t* ltime, char* buf)
00922 { return __GetLocaleName(ltime->lc.id, ltime->cp, buf); }
00923 
00924 char const* _Locale_collate_name(const _Locale_collate_t* lcol, char* buf)
00925 { return __GetLocaleName(lcol->lc.id, lcol->cp, buf); }
00926 
00927 char const* _Locale_monetary_name(const _Locale_monetary_t* lmon, char* buf)
00928 { return __GetLocaleName(lmon->lc.id, lmon->cp, buf); }
00929 
00930 char const* _Locale_messages_name(const struct _Locale_messages* lmes, char* buf) {
00931   _STLP_MARK_PARAMETER_AS_UNUSED(lmes)
00932   _STLP_MARK_PARAMETER_AS_UNUSED(buf)
00933   return NULL;
00934 }
00935 
00936 void _Locale_ctype_destroy(_Locale_ctype_t* ltype) {
00937   if (!ltype) return;
00938 
00939   free(ltype);
00940 }
00941 
00942 void _Locale_numeric_destroy(_Locale_numeric_t* lnum) {
00943   if (!lnum) return;
00944 
00945   if (lnum->grouping) free(lnum->grouping);
00946   free(lnum);
00947 }
00948 
00949 void _Locale_time_destroy(_Locale_time_t* ltime) {
00950   int i;
00951   if (!ltime) return;
00952 
00953   for (i = 0; i < 12; ++i) {
00954     if (ltime->month[i]) free(ltime->month[i]);
00955     if (ltime->abbrev_month[i]) free(ltime->abbrev_month[i]);
00956   }
00957 
00958   for (i = 0; i < 7; ++i) {
00959     if (ltime->dayofweek[i]) free(ltime->dayofweek[i]);
00960     if (ltime->abbrev_dayofweek[i]) free(ltime->abbrev_dayofweek[i]);
00961   }
00962 
00963   if (ltime->date_format) free(ltime->date_format);
00964   if (ltime->long_date_format) free(ltime->long_date_format);
00965   if (ltime->time_format) free(ltime->time_format);
00966   if (ltime->date_time_format) free(ltime->date_time_format);
00967   if (ltime->long_date_time_format) free(ltime->long_date_time_format);
00968 
00969   free(ltime);
00970 }
00971 
00972 void _Locale_collate_destroy(_Locale_collate_t* lcol) {
00973   if (!lcol) return;
00974 
00975   free(lcol);
00976 }
00977 
00978 void _Locale_monetary_destroy(_Locale_monetary_t* lmon) {
00979   if (!lmon) return;
00980 
00981   if (lmon->grouping) free(lmon->grouping);
00982   free(lmon);
00983 }
00984 
00985 void _Locale_messages_destroy(struct _Locale_messages* lmes)
00986 { _STLP_MARK_PARAMETER_AS_UNUSED(lmes) }
00987 
00988 static char const* _Locale_extract_category_name(const char* name, const char* category, char* buf,
00989                                                  _Locale_lcid_t* hint, int *__err_code) {
00990   const char* cname = __Extract_locale_name(name, category, buf);
00991   if (cname == 0 || (cname[0] == 'C' && cname[1] == 0)) {
00992     return cname;
00993   }
00994   return __TranslateToSystem(cname, buf, hint, __err_code);
00995 }
00996 
00997 char const* _Locale_extract_ctype_name(const char* cname, char* buf,
00998                                        _Locale_lcid_t* hint, int *__err_code)
00999 { return _Locale_extract_category_name(cname, "LC_CTYPE", buf, hint, __err_code); }
01000 
01001 char const* _Locale_extract_numeric_name(const char* cname, char* buf,
01002                                          _Locale_lcid_t* hint, int *__err_code)
01003 { return _Locale_extract_category_name(cname, "LC_NUMERIC", buf, hint, __err_code); }
01004 
01005 char const* _Locale_extract_time_name(const char* cname, char* buf,
01006                                       _Locale_lcid_t* hint, int *__err_code)
01007 { return _Locale_extract_category_name(cname, "LC_TIME", buf, hint, __err_code); }
01008 
01009 char const* _Locale_extract_collate_name(const char* cname, char* buf,
01010                                          _Locale_lcid_t* hint, int *__err_code)
01011 { return _Locale_extract_category_name(cname, "LC_COLLATE", buf, hint, __err_code); }
01012 
01013 char const* _Locale_extract_monetary_name(const char* cname, char* buf,
01014                                           _Locale_lcid_t* hint, int *__err_code)
01015 { return _Locale_extract_category_name(cname, "LC_MONETARY", buf, hint, __err_code); }
01016 
01017 char const* _Locale_extract_messages_name(const char* cname, char* buf,
01018                                           _Locale_lcid_t* hint, int *__err_code) {
01019   if (cname[0] == 'L' && cname[1] == 'C' && cname[2] == '_') {
01020     return _C_name;
01021   }
01022   if (cname[0] == 'C' && cname[1] == 0) {
01023     return _C_name;
01024   }
01025   return __TranslateToSystem(cname, buf, hint, __err_code);
01026 }
01027 
01028 /* ctype */
01029 
01030 const _Locale_mask_t* _Locale_ctype_table(_Locale_ctype_t* ltype) {
01031   _STLP_STATIC_ASSERT(sizeof(_Locale_mask_t) == sizeof(ltype->ctable[0]))
01032   return (const _Locale_mask_t*)ltype->ctable;
01033 }
01034 
01035 int _Locale_toupper(_Locale_ctype_t* ltype, int c) {
01036   char buf[2], out_buf[2];
01037   buf[0] = (char)c; buf[1] = 0;
01038   if ((UINT)__GetDefaultCP(ltype->lc.id) == ltype->cp) {
01039     LCMapStringA(ltype->lc.id, LCMAP_LINGUISTIC_CASING | LCMAP_UPPERCASE, buf, 2, out_buf, 2);
01040     return out_buf[0];
01041   }
01042   else {
01043     wchar_t wbuf[2];
01044     MultiByteToWideChar(ltype->cp, MB_PRECOMPOSED, buf, 2, wbuf, 2);
01045     WideCharToMultiByte(__GetDefaultCP(ltype->lc.id), WC_COMPOSITECHECK | WC_SEPCHARS, wbuf, 2, buf, 2, NULL, FALSE);
01046 
01047     LCMapStringA(ltype->lc.id, LCMAP_LINGUISTIC_CASING | LCMAP_UPPERCASE, buf, 2, out_buf, 2);
01048 
01049     MultiByteToWideChar(__GetDefaultCP(ltype->lc.id), MB_PRECOMPOSED, out_buf, 2, wbuf, 2);
01050     WideCharToMultiByte(ltype->cp, WC_COMPOSITECHECK | WC_SEPCHARS, wbuf, 2, out_buf, 2, NULL, FALSE);
01051     return out_buf[0];
01052   }
01053 }
01054 
01055 int _Locale_tolower(_Locale_ctype_t* ltype, int c) {
01056   char buf[2], out_buf[2];
01057   buf[0] = (char)c; buf[1] = 0;
01058   if ((UINT)__GetDefaultCP(ltype->lc.id) == ltype->cp) {
01059     LCMapStringA(ltype->lc.id, LCMAP_LINGUISTIC_CASING | LCMAP_LOWERCASE, buf, 2, out_buf, 2);
01060     return out_buf[0];
01061   }
01062   else {
01063     wchar_t wbuf[2];
01064     MultiByteToWideChar(ltype->cp, MB_PRECOMPOSED, buf, 2, wbuf, 2);
01065     WideCharToMultiByte(__GetDefaultCP(ltype->lc.id), WC_COMPOSITECHECK | WC_SEPCHARS, wbuf, 2, buf, 2, NULL, FALSE);
01066 
01067     LCMapStringA(ltype->lc.id, LCMAP_LINGUISTIC_CASING | LCMAP_LOWERCASE, buf, 2, out_buf, 2);
01068 
01069     MultiByteToWideChar(__GetDefaultCP(ltype->lc.id), MB_PRECOMPOSED, out_buf, 2, wbuf, 2);
01070     WideCharToMultiByte(ltype->cp, WC_COMPOSITECHECK | WC_SEPCHARS, wbuf, 2, out_buf, 2, NULL, FALSE);
01071     return out_buf[0];
01072   }
01073 }
01074 
01075 #ifndef CSTR_EQUAL /* VC5SP3*/
01076 #  define CSTR_EQUAL 2
01077 #endif
01078 #ifndef CSTR_LESS_THAN /* VC5SP3 */
01079 #  define CSTR_LESS_THAN 1
01080 #endif
01081 
01082 static DWORD max_DWORD = 0xffffffff;
01083 static DWORD trim_size_t_to_DWORD(size_t n) { return n < (size_t)max_DWORD ? (DWORD)n : max_DWORD; }
01084 
01085 /* Collate */
01086 /* This function takes care of the potential size_t DWORD different size. */
01087 static int _Locale_strcmp_auxA(_Locale_collate_t* lcol,
01088                                const char* s1, size_t n1,
01089                                const char* s2, size_t n2) {
01090   int result = CSTR_EQUAL;
01091   while (n1 > 0 || n2 > 0) {
01092     DWORD size1 = trim_size_t_to_DWORD(n1);
01093     DWORD size2 = trim_size_t_to_DWORD(n2);
01094     result = CompareStringA(lcol->lc.id, 0, s1, size1, s2, size2);
01095     if (result != CSTR_EQUAL)
01096       break;
01097     n1 -= size1;
01098     n2 -= size2;
01099   }
01100   return result;
01101 }
01102 
01103 int _Locale_strcmp(_Locale_collate_t* lcol,
01104                    const char* s1, size_t n1,
01105                    const char* s2, size_t n2) {
01106   int result;
01107   if (__GetDefaultCP(lcol->lc.id) == atoi(lcol->cp)) {
01108     result = _Locale_strcmp_auxA(lcol, s1, n1, s2, n2);
01109   }
01110   else {
01111     char *buf1, *buf2;
01112     size_t size1, size2;
01113     buf1 = __ConvertToCP(atoi(lcol->cp), __GetDefaultCP(lcol->lc.id), s1, n1, &size1);
01114     buf2 = __ConvertToCP(atoi(lcol->cp), __GetDefaultCP(lcol->lc.id), s2, n2, &size2);
01115 
01116     result = _Locale_strcmp_auxA(lcol, buf1, size1, buf2, size2);
01117     free(buf1); free(buf2);
01118   }
01119   return (result == CSTR_EQUAL) ? 0 : (result == CSTR_LESS_THAN) ? -1 : 1;
01120 }
01121 
01122 size_t _Locale_strxfrm(_Locale_collate_t* lcol,
01123                        char* dst, size_t dst_size,
01124                        const char* src, size_t src_size) {
01125   int result;
01126 
01127   /* The Windows API do not support transformation of very long strings (src_size > INT_MAX)
01128    * In this case the result will just be the input string:
01129    */
01130   if (src_size > INT_MAX) {
01131     if (dst != 0) {
01132       _STLP_STRNCPY(dst, dst_size, src, src_size);
01133     }
01134     return src_size;
01135   }
01136   if (dst_size > INT_MAX) {
01137     /* now that we know that src_size <= INT_MAX we can safely decrease dst_size to INT_MAX. */
01138     dst_size = INT_MAX;
01139   }
01140 
01141   if (__GetDefaultCP(lcol->lc.id) == atoi(lcol->cp))
01142     result = LCMapStringA(lcol->lc.id, LCMAP_SORTKEY, src, (int)src_size, dst, (int)dst_size);
01143   else {
01144     char *buf;
01145     size_t size;
01146     buf = __ConvertToCP(atoi(lcol->cp), __GetDefaultCP(lcol->lc.id), src, src_size, &size);
01147 
01148     result = LCMapStringA(lcol->lc.id, LCMAP_SORTKEY, buf, (int)size, dst, (int)dst_size);
01149     free(buf);
01150   }
01151   return result != 0 ? result - 1 : 0;
01152 }
01153 
01154 /* Numeric */
01155 static const char* __true_name = "true";
01156 static const char* __false_name = "false";
01157 
01158 char _Locale_decimal_point(_Locale_numeric_t* lnum)
01159 { return lnum->decimal_point[0]; }
01160 
01161 char _Locale_thousands_sep(_Locale_numeric_t* lnum)
01162 { return lnum->thousands_sep[0]; }
01163 
01164 const char* _Locale_grouping(_Locale_numeric_t * lnum) {
01165   if (!lnum->grouping) return "";
01166   else return lnum->grouping;
01167 }
01168 
01169 const char * _Locale_true(_Locale_numeric_t * lnum) {
01170   _STLP_MARK_PARAMETER_AS_UNUSED(lnum)
01171   return __true_name; /* NT does't provide information about this */
01172 }
01173 
01174 const char * _Locale_false(_Locale_numeric_t * lnum) {
01175   _STLP_MARK_PARAMETER_AS_UNUSED(lnum)
01176   return __false_name; /* NT does't provide information about this */
01177 }
01178 
01179 /* Monetary */
01180 const char* _Locale_int_curr_symbol(_Locale_monetary_t * lmon)
01181 { return lmon->int_curr_symbol; }
01182 
01183 const char* _Locale_currency_symbol(_Locale_monetary_t * lmon)
01184 { return lmon->curr_symbol; }
01185 
01186 char _Locale_mon_decimal_point(_Locale_monetary_t * lmon)
01187 { return lmon->decimal_point[0]; }
01188 
01189 char _Locale_mon_thousands_sep(_Locale_monetary_t * lmon)
01190 { return lmon->thousands_sep[0]; }
01191 
01192 const char* _Locale_mon_grouping(_Locale_monetary_t * lmon) {
01193   if (!lmon->grouping) return "";
01194   else return lmon->grouping;
01195 }
01196 
01197 const char* _Locale_positive_sign(_Locale_monetary_t * lmon)
01198 { return lmon->positive_sign; }
01199 
01200 const char* _Locale_negative_sign(_Locale_monetary_t * lmon)
01201 { return lmon->negative_sign; }
01202 
01203 char _Locale_int_frac_digits(_Locale_monetary_t * lmon)
01204 { return (char)lmon->int_frac_digits; }
01205 
01206 char _Locale_frac_digits(_Locale_monetary_t * lmon)
01207 { return (char)lmon->frac_digits; }
01208 
01209 int _Locale_p_cs_precedes(_Locale_monetary_t * lmon) {
01210   char loc_data[2];
01211   GetLocaleInfoA(lmon->lc.id, LOCALE_IPOSSYMPRECEDES, loc_data, 2);
01212   if (loc_data[0] == '0') return 0;
01213   else if (loc_data[0] == '1') return 1;
01214   else return -1;
01215 }
01216 
01217 int _Locale_p_sep_by_space(_Locale_monetary_t * lmon) {
01218   char loc_data[2];
01219   GetLocaleInfoA(lmon->lc.id, LOCALE_IPOSSEPBYSPACE, loc_data, 2);
01220   if (loc_data[0] == '0') return 0;
01221   else if (loc_data[0] == '1') return 1;
01222   else return -1;
01223 }
01224 
01225 int _Locale_p_sign_posn(_Locale_monetary_t * lmon) {
01226   char loc_data[2];
01227   if (lmon->lc.id != INVARIANT_LCID) {
01228     GetLocaleInfoA(lmon->lc.id, LOCALE_IPOSSIGNPOSN, loc_data, 2);
01229     return atoi(loc_data);
01230   }
01231   else {
01232     return CHAR_MAX;
01233   }
01234 }
01235 
01236 int _Locale_n_cs_precedes(_Locale_monetary_t * lmon) {
01237   char loc_data[2];
01238   GetLocaleInfoA(lmon->lc.id, LOCALE_INEGSYMPRECEDES, loc_data, 2);
01239   if (loc_data[0] == '0') return 0;
01240   else if (loc_data[0] == '1') return 1;
01241   else return -1;
01242 }
01243 
01244 int _Locale_n_sep_by_space(_Locale_monetary_t * lmon) {
01245   char loc_data[2];
01246   GetLocaleInfoA(lmon->lc.id, LOCALE_INEGSEPBYSPACE, loc_data, 2);
01247   if (loc_data[0] == '0') return 0;
01248   else if (loc_data[0] == '1') return 1;
01249   else return -1;
01250 }
01251 
01252 int _Locale_n_sign_posn(_Locale_monetary_t * lmon) {
01253   char loc_data[2];
01254   if (lmon->lc.id != INVARIANT_LCID) {
01255     GetLocaleInfoA(lmon->lc.id, LOCALE_INEGSIGNPOSN, loc_data, 2);
01256     return atoi(loc_data);
01257   }
01258   else {
01259     return CHAR_MAX;
01260   }
01261 }
01262 
01263 /* Time */
01264 const char * _Locale_full_monthname(_Locale_time_t * ltime, int month) {
01265   const char **names = (const char**)ltime->month;
01266   return names[month];
01267 }
01268 
01269 const char * _Locale_abbrev_monthname(_Locale_time_t * ltime, int month) {
01270   const char **names = (const char**)ltime->abbrev_month;
01271   return names[month];
01272 }
01273 
01274 const char * _Locale_full_dayofweek(_Locale_time_t * ltime, int day) {
01275   const char **names = (const char**)ltime->dayofweek;
01276   return names[day];
01277 }
01278 
01279 const char * _Locale_abbrev_dayofweek(_Locale_time_t * ltime, int day) {
01280   const char **names = (const char**)ltime->abbrev_dayofweek;
01281   return names[day];
01282 }
01283 
01284 const char* _Locale_d_t_fmt(_Locale_time_t* ltime)
01285 { return ltime->date_time_format; }
01286 
01287 const char* _Locale_long_d_t_fmt(_Locale_time_t* ltime)
01288 { return ltime->long_date_time_format; }
01289 
01290 const char* _Locale_d_fmt(_Locale_time_t* ltime)
01291 { return ltime->date_format; }
01292 
01293 const char* _Locale_long_d_fmt(_Locale_time_t* ltime)
01294 { return ltime->long_date_format; }
01295 
01296 const char* _Locale_t_fmt(_Locale_time_t* ltime)
01297 { return ltime->time_format; }
01298 
01299 const char* _Locale_am_str(_Locale_time_t* ltime)
01300 { return ltime->am; }
01301 
01302 const char* _Locale_pm_str(_Locale_time_t* ltime)
01303 { return ltime->pm; }
01304 
01305 /* Messages */
01306 nl_catd_type _Locale_catopen(struct _Locale_messages* lmes, const char* cat_name) {
01307   _STLP_MARK_PARAMETER_AS_UNUSED(lmes)
01308   _STLP_MARK_PARAMETER_AS_UNUSED(cat_name)
01309   return -1;
01310 }
01311 void _Locale_catclose(struct _Locale_messages* lmes, nl_catd_type cat) {
01312   _STLP_MARK_PARAMETER_AS_UNUSED(lmes)
01313   _STLP_MARK_PARAMETER_AS_UNUSED(&cat)
01314 }
01315 const char* _Locale_catgets(struct _Locale_messages* lmes, nl_catd_type cat,
01316                             int setid, int msgid, const char *dfault) {
01317   _STLP_MARK_PARAMETER_AS_UNUSED(lmes)
01318   _STLP_MARK_PARAMETER_AS_UNUSED(&cat)
01319   _STLP_MARK_PARAMETER_AS_UNUSED(&setid)
01320   _STLP_MARK_PARAMETER_AS_UNUSED(&msgid)
01321   return dfault;
01322 }
01323 
01324 #ifdef __cplusplus
01325 } /* extern C */
01326 _STLP_END_NAMESPACE
01327 #endif
01328 
01329 void __FixGrouping(char *grouping) {
01330   /* This converts NT version which uses '0' instead of 0, etc ; to ANSI */
01331   char *g = grouping;
01332   char building_group = 0;
01333   char repeat_last = 0;
01334   /* Check there is a grouping info otherwise we would add a useless CHAR_MAX */
01335   if (*g) {
01336     for (; *g; ++g) {
01337       if (*g > '0' && *g <= '9') {
01338         if (!building_group) {
01339           *grouping = *g - '0';
01340           building_group = 1;
01341         }
01342         else {
01343           /* Known issue: grouping might roll. */
01344           *grouping = *grouping * 10 + *g - '0';
01345         }
01346       }
01347       else if (*g == '0') {
01348         if (!building_group) {
01349           repeat_last = 1;
01350         }
01351         else
01352           /* Known issue: grouping might roll. */
01353           *grouping *= 10;
01354       }
01355       else if (*g == ';') {
01356         /* Stop adding to the current group */
01357         building_group = 0;
01358         ++grouping;
01359       }
01360       /* else we ignore the character */
01361     }
01362 
01363     if (!repeat_last)
01364       *grouping++ = CHAR_MAX;
01365     *grouping = 0;
01366   }
01367 }
01368 
01369 const char* __ConvertName(const char* lname, LOCALECONV* ConvTable, int TableSize) {
01370   int i;
01371   int cmp;
01372   int low = 0;
01373   int high = TableSize - 1;
01374 
01375   /*  typical binary search - do until no more to search or match */
01376   while (low <= high) {
01377     i = (low + high) / 2;
01378 
01379     if ((cmp = lstrcmpiA(lname, (*(ConvTable + i)).name)) == 0)
01380       return (*(ConvTable + i)).abbrev;
01381     else if (cmp < 0)
01382       high = i - 1;
01383     else
01384       low = i + 1;
01385   }
01386   return lname;
01387 }
01388 
01389 int __ParseLocaleString(const char* lname,
01390                         char* lang, char* ctry, char* page) {
01391   int param = 0;
01392   size_t len;
01393   size_t tmpLen;
01394 
01395   if (lname[0] == 0)
01396     return 0;
01397 
01398   /* We look for the first country separator '_' */
01399   len = strcspn(lname, "_");
01400   if (lname[len] == '_') {
01401     if (len == 0 || len > MAX_LANG_LEN) return -1; /* empty lang is invalid*/
01402     _STLP_STRNCPY(lang, MAX_LANG_LEN + 1, lname, len);
01403     lname += len + 1;
01404     ++param;
01405   }
01406 
01407   /* We look for the last code page separator '.' */
01408   len = -1;
01409   tmpLen = strcspn(lname, ".");
01410   while (lname[tmpLen] == '.') {
01411     len = tmpLen; ++tmpLen;
01412     tmpLen += strcspn(lname + tmpLen, ".");
01413   }
01414   if (len != -1) { /* Means that we found a '.' */
01415     if (param == 0) {
01416       /* We have no lang yet so we have to fill it first, no country */
01417       if (len > MAX_LANG_LEN) return -1;
01418       if (len == 0) {
01419         /* No language nor country, only code page */
01420         ++param;
01421       }
01422       else
01423       { _STLP_STRNCPY(lang, MAX_LANG_LEN + 1, lname, len); }
01424       ++param;
01425     }
01426     else {
01427       /* We already have a lang so we are now looking for the country: */
01428       if (len == 0) return -1; /* We forbid locale name with the "_." motif in it */
01429       if (len > MAX_CTRY_LEN) return -1;
01430       _STLP_STRNCPY(ctry, MAX_CTRY_LEN + 1, lname, len);
01431     }
01432     ++param;
01433     lname += len + 1;
01434   }
01435 
01436   /* We look for ',' for compatibility with POSIX */
01437   len = strcspn(lname, ",");
01438   switch (param) {
01439     case 0:
01440       if (len > MAX_LANG_LEN) return -1;
01441       _STLP_STRNCPY(lang, MAX_LANG_LEN + 1, lname, len);
01442       break;
01443     case 1:
01444       if (len > MAX_CTRY_LEN) return -1;
01445       _STLP_STRNCPY(ctry, MAX_CTRY_LEN + 1, lname, len);
01446       break;
01447     default:
01448       if (len > MAX_CP_LEN) return -1;
01449       _STLP_STRNCPY(page, MAX_CP_LEN + 1, lname, len);
01450       break;
01451   }
01452 
01453   /* ',' POSIX modifier is not used in NT */
01454   return 0;
01455 }
01456 
01457 /* Data necessary for find LCID*/
01458 static CRITICAL_SECTION __criticalSection;
01459 static int __FindFlag;
01460 static LCID __FndLCID;
01461 static const char* __FndLang;
01462 static const char* __FndCtry;
01463 
01464 void _Locale_init()
01465 { InitializeCriticalSection(&__criticalSection); }
01466 
01467 void _Locale_final()
01468 { DeleteCriticalSection(&__criticalSection); }
01469 
01470 static LCID LocaleFromHex(const char* locale) {
01471   unsigned long result = 0;
01472   int digit;
01473   while (*locale) {
01474     result <<= 4;
01475     digit = (*locale >= '0' && *locale <= '9') ? *locale - '0':
01476             (*locale >= 'A' && *locale <= 'F') ? (*locale - 'A') + 10
01477                                                : (*locale - 'a') + 10;
01478     result += digit;
01479     ++locale;
01480   }
01481   return (LCID)result;
01482 }
01483 
01484 static BOOL CALLBACK EnumLocalesProcA(LPSTR locale) {
01485   LCID lcid = LocaleFromHex(locale);
01486   int LangFlag = 0, CtryFlag = !__FndCtry;
01487   static char Lang[MAX_LANG_LEN], Ctry[MAX_CTRY_LEN];
01488 
01489   GetLocaleInfoA(lcid, LOCALE_SENGLANGUAGE, Lang, MAX_LANG_LEN);
01490   if (lstrcmpiA(Lang, __FndLang) != 0) {
01491     GetLocaleInfoA(lcid, LOCALE_SABBREVLANGNAME, Lang, MAX_LANG_LEN);
01492     if (lstrcmpiA(Lang, __FndLang) != 0) {
01493       GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, Lang, MAX_LANG_LEN);
01494       if (lstrcmpiA(Lang, __FndLang) == 0) LangFlag = 1;
01495     }
01496     else LangFlag = 1;
01497   }
01498   else LangFlag = 1;
01499 
01500   if (__FndCtry) {
01501     GetLocaleInfoA(lcid, LOCALE_SENGCOUNTRY, Ctry, MAX_CTRY_LEN);
01502     if (lstrcmpiA(Ctry, __FndCtry) != 0) {
01503       GetLocaleInfoA(lcid, LOCALE_SABBREVCTRYNAME, Ctry, MAX_CTRY_LEN);
01504       if (lstrcmpiA(Ctry, __FndCtry) != 0) {
01505         GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, Ctry, MAX_CTRY_LEN);
01506         if (lstrcmpiA(Ctry, __FndCtry) == 0) CtryFlag = 1;
01507       }
01508       else CtryFlag = 1;
01509     }
01510     else
01511       CtryFlag = 1;
01512   }
01513 
01514   if (LangFlag && CtryFlag) {
01515     __FindFlag = 1;
01516     __FndLCID = lcid;
01517     return FALSE;
01518   }
01519 
01520   return TRUE;
01521 }
01522 
01523 int __GetLCID(const char* lang, const char* ctry, LCID* lcid) {
01524   int ret;
01525   EnterCriticalSection(&__criticalSection);
01526 
01527   __FindFlag = 0;
01528   __FndLang = lang;
01529   __FndCtry = ctry;
01530   EnumSystemLocalesA(EnumLocalesProcA, LCID_INSTALLED);
01531 
01532   if (__FindFlag != 0) *lcid = __FndLCID;
01533   ret = __FindFlag != 0 ? 0 : -1;
01534 
01535   LeaveCriticalSection(&__criticalSection);
01536   return ret;
01537 }
01538 
01539 int __GetLCIDFromName(const char* lname, LCID* lcid, char* cp, _Locale_lcid_t *hint) {
01540   char lang[MAX_LANG_LEN + 1], ctry[MAX_CTRY_LEN + 1], page[MAX_CP_LEN + 1];
01541   int result = 0;
01542   if (lname == NULL || lname[0] == 0) {
01543     *lcid = LOCALE_USER_DEFAULT;
01544     return 0;
01545   }
01546 
01547   memset(lang, 0, MAX_LANG_LEN + 1);
01548   memset(ctry, 0, MAX_CTRY_LEN + 1);
01549   memset(page, 0, MAX_CP_LEN + 1);
01550   if (__ParseLocaleString(lname, lang, ctry, page) == -1) return -1;
01551 
01552   if (hint != 0) {
01553     *lcid = hint->id;
01554   }
01555   else {
01556     if (lang[0] == 0 && ctry[0] == 0)
01557       *lcid = LOCALE_USER_DEFAULT; /* Only code page given. */
01558     else {
01559       if (ctry[0] == 0) {
01560         result = __GetLCID(__ConvertName(lang, __rg_language, sizeof(__rg_language) / sizeof(LOCALECONV)), NULL, lcid);
01561         if (result != 0) {
01562           /* Check 'C' special case. Check is done after call to __GetLCID because normal programs do not
01563            * generate facet from 'C' name, they use the locale::classic() facets. */
01564           if (lang[0] == 'C' && lang[1] == 0) {
01565             *lcid = INVARIANT_LCID;
01566             result = 0;
01567           }
01568         }
01569       }
01570       else {
01571         result = __GetLCID(__ConvertName(lang, __rg_language, sizeof(__rg_language) / sizeof(LOCALECONV)),
01572                            __ConvertName(ctry, __rg_country, sizeof(__rg_country) / sizeof(LOCALECONV)),
01573                            lcid);
01574         if (result != 0) {
01575           /* Non NLS mapping might introduce problem with some locales when only one entry is mapped,
01576            * the lang or the country (example: chinese locales like 'chinese_taiwan' gives 'CHS_taiwan'
01577            * that do not exists in system). This is why we are giving this locale an other chance by
01578            * calling __GetLCID without the mapping. */
01579           result = __GetLCID(lang, ctry, lcid);
01580         }
01581       }
01582     }
01583   }
01584 
01585   if (result == 0) {
01586     /* Handling code page */
01587     if (lstrcmpiA(page, "ACP") == 0 || page[0] == 0)
01588       my_ltoa(__intGetACP(*lcid), cp);
01589     else if (lstrcmpiA(page, "OCP") == 0)
01590       my_ltoa(__intGetOCP(*lcid), cp);
01591     else if (lstrcmpiA(page, "UTF7") == 0)
01592       my_ltoa(CP_UTF7, cp);
01593     else if (lstrcmpiA(page, "UTF8") == 0)
01594       my_ltoa(CP_UTF8, cp);
01595     else
01596       _STLP_STRNCPY(cp, MAX_CP_LEN + 1, page, 5);
01597 
01598     /* Code page must be an integer value,
01599      * 0 returned by __intGetACP and 1 returned by __intGetOCP are invalid
01600      * values.
01601      */
01602     if (cp[1] == 0 && (cp[0] == '0' || cp[1] == '1'))
01603       return -1;
01604     else if (atoi(cp) == 0)
01605       return -1;
01606   }
01607 
01608   return result;
01609 }
01610 
01611 char const* __GetLocaleName(LCID lcid, const char* cp, char* buf) {
01612   if (lcid == INVARIANT_LCID) {
01613     return _C_name;
01614   }
01615   else {
01616     char lang[MAX_LANG_LEN + 1], ctry[MAX_CTRY_LEN + 1];
01617     GetLocaleInfoA(lcid, LOCALE_SENGLANGUAGE, lang, MAX_LANG_LEN);
01618     GetLocaleInfoA(lcid, LOCALE_SENGCOUNTRY, ctry, MAX_CTRY_LEN);
01619     _STLP_STRCPY(buf, _Locale_MAX_SIMPLE_NAME, lang);
01620     _STLP_STRCAT(buf, _Locale_MAX_SIMPLE_NAME, "_");
01621     _STLP_STRCAT(buf, _Locale_MAX_SIMPLE_NAME, ctry);
01622     _STLP_STRCAT(buf, _Locale_MAX_SIMPLE_NAME, ".");
01623     _STLP_STRCAT(buf, _Locale_MAX_SIMPLE_NAME, cp);
01624     return buf;
01625   }
01626 }
01627 
01628 char const* __Extract_locale_name(const char* loc, const char* category, char* buf) {
01629   char *expr;
01630   size_t len_name;
01631 
01632   if (loc[0] == 'L' && loc[1] == 'C' && loc[2] == '_') {
01633     expr = strstr((char*)loc, category);
01634     if (expr == NULL) return NULL; /* Category not found. */
01635     expr = strchr(expr, '=');
01636     if (expr == NULL) return NULL;
01637     ++expr;
01638     len_name = strcspn(expr, ";");
01639     len_name = len_name >= _Locale_MAX_SIMPLE_NAME ? _Locale_MAX_SIMPLE_NAME - 1
01640                                                    : len_name;
01641     _STLP_STRNCPY(buf, _Locale_MAX_SIMPLE_NAME, expr, len_name); buf[len_name] = 0;
01642     return buf;
01643   }
01644   else {
01645     return loc;
01646   }
01647 }
01648 
01649 char const* __TranslateToSystem(const char* lname, char* buf, _Locale_lcid_t* hint,
01650                                 int *__err_code) {
01651   LCID lcid;
01652   char cp[MAX_CP_LEN + 1];
01653   if (__GetLCIDFromName(lname, &lcid, cp, hint) != 0)
01654   { *__err_code = _STLP_LOC_UNKNOWN_NAME; return NULL; }
01655 
01656   return __GetLocaleName(lcid, cp, buf);
01657 }
01658 
01659 void __GetLocaleInfoUsingACP(LCID lcid, const char* cp, LCTYPE lctype, char* buf, int buf_size, wchar_t* wbuf, int wbuf_size) {
01660   wchar_t *Buffer;
01661   int BufferSize;
01662   int icp;
01663 
01664   GetLocaleInfoA(lcid, lctype, buf, buf_size);
01665 
01666   icp = atoi(cp);
01667   if (icp != CP_ACP && buf[0] != 0) {
01668     BufferSize = MultiByteToWideChar(CP_ACP, 0, buf, -1, NULL, 0);
01669     if (BufferSize > wbuf_size)
01670     {
01671       Buffer = (wchar_t*)malloc(sizeof(wchar_t) * BufferSize);
01672     }
01673     else
01674     {
01675       Buffer = wbuf;
01676     }
01677     MultiByteToWideChar(CP_ACP, 0, buf, -1, Buffer, BufferSize);
01678     WideCharToMultiByte(icp, 0, Buffer, -1, buf, buf_size, NULL, NULL);
01679     if (Buffer != wbuf)
01680     {
01681       free(Buffer);
01682     }
01683   }
01684 }
01685 
01686 /* Return 0 if ANSI code page not used */
01687 int __intGetACP(LCID lcid) {
01688   char cp[6];
01689   if (!GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE, cp, 6)) {
01690 #if defined (_STLP_LANG_INVARIANT_DEFINED)
01691     if (lcid == INVARIANT_LCID) {
01692       /* We are using a limited PSDK, we rely on the most common code page */
01693       return 1252;
01694     }
01695 #endif
01696     return 0;
01697   }
01698   return atoi(cp);
01699 }
01700 
01701 /* Return 1 if OEM code page not used */
01702 int __intGetOCP(LCID lcid) {
01703   char cp[6];
01704   if (!GetLocaleInfoA(lcid, LOCALE_IDEFAULTCODEPAGE, cp, 6))
01705     return 0;
01706   return atoi(cp);
01707 }
01708 
01709 int __GetDefaultCP(LCID lcid) {
01710   int cp = __intGetACP(lcid);
01711   if (cp == 0) return __intGetOCP(lcid);
01712   else return cp;
01713 }
01714 
01715 static int trim_size_t_to_int(size_t n) { return n < (size_t)INT_MAX ? (int)n : INT_MAX; }
01716 
01717 char* __ConvertToCP(int from_cp, int to_cp, const char *from, size_t size, size_t *ret_buf_size) {
01718   size_t wbuffer_size, buffer_size, from_offset, wbuf_offset;
01719   int from_size, to_size, wbuf_size;
01720   wchar_t *wbuffer;
01721   char* buffer;
01722 
01723   size_t orig_size = size;
01724 
01725   wbuffer_size = 0;
01726   from_offset = 0;
01727   while (size > 0) {
01728     from_size = trim_size_t_to_int(size);
01729     wbuffer_size += MultiByteToWideChar(from_cp, MB_PRECOMPOSED,
01730                                         from + from_offset, from_size, NULL, 0);
01731     from_offset += from_size;
01732     size -= from_size;
01733   }
01734 
01735   wbuffer = (wchar_t*)malloc(sizeof(wchar_t)*wbuffer_size);
01736 
01737   size = orig_size;
01738   wbuf_offset = 0;
01739   from_offset = 0;
01740   while (size > 0) {
01741     from_size = trim_size_t_to_int(size);
01742     wbuf_size = trim_size_t_to_int(wbuffer_size - wbuf_offset);
01743     wbuf_offset += MultiByteToWideChar(from_cp, MB_PRECOMPOSED,
01744                                        from + from_offset, from_size, wbuffer + wbuf_offset, wbuf_size);
01745     from_offset += from_size;
01746     size -= from_size;
01747   }
01748 
01749   buffer_size = 0;
01750   wbuf_offset = 0;
01751   size = wbuffer_size;
01752   while (size > 0) {
01753     wbuf_size = trim_size_t_to_int(size);
01754     buffer_size += WideCharToMultiByte(to_cp, WC_COMPOSITECHECK | WC_SEPCHARS,
01755                                        wbuffer + wbuf_offset, wbuf_size,
01756                                        NULL, 0, NULL, FALSE);
01757     wbuf_offset += wbuf_size;
01758     size -= wbuf_size;
01759   }
01760 
01761   buffer = (char*)malloc(buffer_size);
01762   *ret_buf_size = buffer_size;
01763 
01764   size = wbuffer_size;
01765   wbuf_offset = 0;
01766   while (size > 0) {
01767     wbuf_size = trim_size_t_to_int(size);
01768     to_size = trim_size_t_to_int(buffer_size);
01769     buffer_size -= WideCharToMultiByte(to_cp, WC_COMPOSITECHECK | WC_SEPCHARS,
01770                                        wbuffer + wbuf_offset, wbuf_size,
01771                                        buffer, to_size, NULL, FALSE);
01772     wbuf_offset += wbuf_size;
01773     size -= wbuf_size;
01774   }
01775 
01776   free(wbuffer);
01777   return buffer;
01778 }
01779 
01780 #ifdef __cplusplus
01781 }
01782 #endif
01783 
01784 #ifndef _STLP_NO_WCHAR_T
01785 #  include "c_wlocale_win32.c"
01786 #endif

Generated on Tue May 22 2012 04:39:18 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.