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



Generated on Mon Mar 10 15:32:16 2008 by  doxygen 1.5.1