ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 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

locale.c
Go to the documentation of this file.
00001 /*
00002  * Some stuff takem from wine msvcrt\locale.c
00003  *
00004  * Copyright 2000 Jon Griffiths
00005  */
00006 
00007 #include <precomp.h>
00008 #include <locale.h>
00009 
00010 #include "mbctype.h"
00011 
00012 // mtdll.h
00013 #define _SETLOCALE_LOCK 19
00014 
00015 // msvcrt.h
00016 #define MSVCRT_LC_ALL          0
00017 #define MSVCRT_LC_COLLATE      1
00018 #define MSVCRT_LC_CTYPE        2
00019 #define MSVCRT_LC_MONETARY     3
00020 #define MSVCRT_LC_NUMERIC      4
00021 #define MSVCRT_LC_TIME         5
00022 #define MSVCRT_LC_MIN          MSVCRT_LC_ALL
00023 #define MSVCRT_LC_MAX          MSVCRT_LC_TIME
00024 
00025 /* FIXME: Need to hold locale for each LC_* type and aggregate
00026  * string to produce lc_all.
00027  */
00028 #define MAX_ELEM_LEN 64 /* Max length of country/language/CP string */
00029 
00030 unsigned char _mbctype[257] = { 0 };
00031 int g_mbcp_is_multibyte = 0;
00032 
00033 /* It seems that the data about valid trail bytes is not available from kernel32
00034  * so we have to store is here. The format is the same as for lead bytes in CPINFO */
00035 struct cp_extra_info_t
00036 {
00037     int cp;
00038     BYTE TrailBytes[MAX_LEADBYTES];
00039 };
00040 
00041 static struct cp_extra_info_t g_cpextrainfo[] =
00042 {
00043     {932, {0x40, 0x7e, 0x80, 0xfc, 0, 0}},
00044     {936, {0x40, 0xfe, 0, 0}},
00045     {949, {0x41, 0xfe, 0, 0}},
00046     {950, {0x40, 0x7e, 0xa1, 0xfe, 0, 0}},
00047     {1361, {0x31, 0x7e, 0x81, 0xfe, 0, 0}},
00048     {20932, {1, 255, 0, 0}},  /* seems to give different results on different systems */
00049     {0, {1, 255, 0, 0}}       /* match all with FIXME */
00050 };
00051 
00052 
00053 char MSVCRT_current_lc_all[MAX_LOCALE_LENGTH] = { 0 };
00054 LCID MSVCRT_current_lc_all_lcid = 0;
00055 int MSVCRT___lc_codepage = 0;
00056 int MSVCRT___lc_collate_cp = 0;
00057 HANDLE MSVCRT___lc_handle[MSVCRT_LC_MAX - MSVCRT_LC_MIN + 1] = { 0 };
00058 int __mb_cur_max = 1;
00059 
00060 /* MT */
00061 #define LOCK_LOCALE   _mlock(_SETLOCALE_LOCK);
00062 #define UNLOCK_LOCALE _munlock(_SETLOCALE_LOCK);
00063 
00064 #define MSVCRT_LEADBYTE  0x8000
00065 
00066 typedef struct {
00067   char search_language[MAX_ELEM_LEN];
00068   char search_country[MAX_ELEM_LEN];
00069   char search_codepage[MAX_ELEM_LEN];
00070   char found_language[MAX_ELEM_LEN];
00071   char found_country[MAX_ELEM_LEN];
00072   char found_codepage[MAX_ELEM_LEN];
00073   unsigned int match_flags;
00074   LANGID found_lang_id;
00075 } locale_search_t;
00076 
00077 unsigned int __setlc_active;
00078 unsigned int __unguarded_readlc_active;
00079 int _current_category;  /* used by setlocale */
00080 const char *_current_locale;
00081 
00082 
00083 int parse_locale(const char *locale, char *lang, char *country, char *code_page);
00084 
00085 #define _C_ _CONTROL
00086 #define _S_ _SPACE
00087 #define _P_ _PUNCT
00088 #define _D_ _DIGIT
00089 #define _H_ _HEX
00090 #define _U_ _UPPER
00091 #define _L_ _LOWER
00092 
00093 WORD MSVCRT__ctype [257] = {
00094   0, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _S_|_C_, _S_|_C_,
00095   _S_|_C_, _S_|_C_, _S_|_C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_,
00096   _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _C_, _S_|_BLANK,
00097   _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _P_,
00098   _P_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_, _D_|_H_,
00099   _D_|_H_, _D_|_H_, _D_|_H_, _P_, _P_, _P_, _P_, _P_, _P_, _P_, _U_|_H_,
00100   _U_|_H_, _U_|_H_, _U_|_H_, _U_|_H_, _U_|_H_, _U_, _U_, _U_, _U_, _U_,
00101   _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_, _U_,
00102   _U_, _P_, _P_, _P_, _P_, _P_, _P_, _L_|_H_, _L_|_H_, _L_|_H_, _L_|_H_,
00103   _L_|_H_, _L_|_H_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_,
00104   _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _L_, _P_, _P_, _P_, _P_,
00105   _C_, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00106   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00107   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00108   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00109   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00110   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00111 };
00112 
00113 /* Internal: Current ctype table for locale */
00114 WORD MSVCRT_current_ctype[257];
00115 
00116 /* pctype is used by macros in the Win32 headers. It must point
00117  * To a table of flags exactly like ctype. To allow locale
00118  * changes to affect ctypes (i.e. isleadbyte), we use a second table
00119  * and update its flags whenever the current locale changes.
00120  */
00121 WORD* MSVCRT__pctype = MSVCRT_current_ctype + 1;
00122 
00123 /* Friendly country strings & iso codes for synonym support.
00124  * Based on MS documentation for setlocale().
00125  */
00126 static const char * const _country_synonyms[] =
00127 {
00128   "Hong Kong","HK",
00129   "Hong-Kong","HK",
00130   "New Zealand","NZ",
00131   "New-Zealand","NZ",
00132   "PR China","CN",
00133   "PR-China","CN",
00134   "United Kingdom","GB",
00135   "United-Kingdom","GB",
00136   "Britain","GB",
00137   "England","GB",
00138   "Great Britain","GB",
00139   "United States","US",
00140   "United-States","US",
00141   "America","US"
00142 };
00143 
00144 /* Note: Flags are weighted in order of matching importance */
00145 #define FOUND_LANGUAGE         0x4
00146 #define FOUND_COUNTRY          0x2
00147 #define FOUND_CODEPAGE         0x1
00148 
00149 /* INTERNAL: Map a synonym to an ISO code */
00150 static void remap_synonym(char *name)
00151 {
00152   size_t i;
00153   for (i = 0; i < sizeof(_country_synonyms)/sizeof(char*); i += 2 )
00154   {
00155     if (!_stricmp(_country_synonyms[i],name))
00156     {
00157       TRACE(":Mapping synonym %s to %s\n",name,_country_synonyms[i+1]);
00158       name[0] = _country_synonyms[i+1][0];
00159       name[1] = _country_synonyms[i+1][1];
00160       name[2] = '\0';
00161       return;
00162     }
00163   }
00164 }
00165 
00166 #define CONTINUE_LOOKING TRUE
00167 #define STOP_LOOKING     FALSE
00168 
00169 /* INTERNAL: Get and compare locale info with a given string */
00170 static int compare_info(LCID lcid, DWORD flags, char* buff, const char* cmp)
00171 {
00172   buff[0] = 0;
00173   GetLocaleInfoA(lcid, flags|LOCALE_NOUSEROVERRIDE,buff, MAX_ELEM_LEN);
00174   if (!buff[0] || !cmp[0])
00175     return 0;
00176   /* Partial matches are allowed, e.g. "Germ" matches "Germany" */
00177   return !_strnicmp(cmp, buff, strlen(cmp));
00178 }
00179 
00180 
00181 static BOOL CALLBACK
00182 find_best_locale_proc(HMODULE hModule, LPCSTR type, LPCSTR name, WORD LangID, LONG_PTR lParam)
00183 {
00184   locale_search_t *res = (locale_search_t *)lParam;
00185   const LCID lcid = MAKELCID(LangID, SORT_DEFAULT);
00186   char buff[MAX_ELEM_LEN];
00187   unsigned int flags = 0;
00188 
00189   if(PRIMARYLANGID(LangID) == LANG_NEUTRAL)
00190     return CONTINUE_LOOKING;
00191 
00192   /* Check Language */
00193   if (compare_info(lcid,LOCALE_SISO639LANGNAME,buff,res->search_language) ||
00194       compare_info(lcid,LOCALE_SABBREVLANGNAME,buff,res->search_language) ||
00195       compare_info(lcid,LOCALE_SENGLANGUAGE,buff,res->search_language))
00196   {
00197     TRACE(":Found language: %s->%s\n", res->search_language, buff);
00198     flags |= FOUND_LANGUAGE;
00199     memcpy(res->found_language,res->search_language,MAX_ELEM_LEN);
00200   }
00201   else if (res->match_flags & FOUND_LANGUAGE)
00202   {
00203     return CONTINUE_LOOKING;
00204   }
00205 
00206   /* Check Country */
00207   if (compare_info(lcid,LOCALE_SISO3166CTRYNAME,buff,res->search_country) ||
00208       compare_info(lcid,LOCALE_SABBREVCTRYNAME,buff,res->search_country) ||
00209       compare_info(lcid,LOCALE_SENGCOUNTRY,buff,res->search_country))
00210   {
00211     TRACE("Found country:%s->%s\n", res->search_country, buff);
00212     flags |= FOUND_COUNTRY;
00213     memcpy(res->found_country,res->search_country,MAX_ELEM_LEN);
00214   }
00215   else if (res->match_flags & FOUND_COUNTRY)
00216   {
00217     return CONTINUE_LOOKING;
00218   }
00219 
00220   /* Check codepage */
00221   if (compare_info(lcid,LOCALE_IDEFAULTCODEPAGE,buff,res->search_codepage) ||
00222       (compare_info(lcid,LOCALE_IDEFAULTANSICODEPAGE,buff,res->search_codepage)))
00223   {
00224     TRACE("Found codepage:%s->%s\n", res->search_codepage, buff);
00225     flags |= FOUND_CODEPAGE;
00226     memcpy(res->found_codepage,res->search_codepage,MAX_ELEM_LEN);
00227   }
00228   else if (res->match_flags & FOUND_CODEPAGE)
00229   {
00230     return CONTINUE_LOOKING;
00231   }
00232 
00233   if (flags > res->match_flags)
00234   {
00235     /* Found a better match than previously */
00236     res->match_flags = flags;
00237     res->found_lang_id = LangID;
00238   }
00239   if ((flags & (FOUND_LANGUAGE | FOUND_COUNTRY | FOUND_CODEPAGE)) ==
00240         (FOUND_LANGUAGE | FOUND_COUNTRY | FOUND_CODEPAGE))
00241   {
00242     TRACE(":found exact locale match\n");
00243     return STOP_LOOKING;
00244   }
00245   return CONTINUE_LOOKING;
00246 }
00247 
00248 /* Internal: Find the LCID for a locale specification */
00249 static LCID MSVCRT_locale_to_LCID(locale_search_t* locale)
00250 {
00251   LCID lcid;
00252   EnumResourceLanguagesA(GetModuleHandleA("KERNEL32"), (LPSTR)RT_STRING,
00253              (LPCSTR)LOCALE_ILANGUAGE,find_best_locale_proc,
00254              (LONG_PTR)locale);
00255 
00256   if (!locale->match_flags)
00257     return 0;
00258 
00259   /* If we were given something that didn't match, fail */
00260   if (locale->search_country[0] && !(locale->match_flags & FOUND_COUNTRY))
00261     return 0;
00262 
00263   lcid =  MAKELCID(locale->found_lang_id, SORT_DEFAULT);
00264 
00265   /* Populate partial locale, translating LCID to locale string elements */
00266   if (!locale->found_codepage[0])
00267   {
00268     /* Even if a codepage is not enumerated for a locale
00269      * it can be set if valid */
00270     if (locale->search_codepage[0])
00271     {
00272       if (IsValidCodePage(atoi(locale->search_codepage)))
00273         memcpy(locale->found_codepage,locale->search_codepage,MAX_ELEM_LEN);
00274       else
00275       {
00276         /* Special codepage values: OEM & ANSI */
00277         if (_stricmp(locale->search_codepage,"OCP"))
00278         {
00279           GetLocaleInfoA(lcid, LOCALE_IDEFAULTCODEPAGE,
00280                          locale->found_codepage, MAX_ELEM_LEN);
00281         }
00282         if (_stricmp(locale->search_codepage,"ACP"))
00283         {
00284           GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE,
00285                          locale->found_codepage, MAX_ELEM_LEN);
00286         }
00287         else
00288           return 0;
00289 
00290         if (!atoi(locale->found_codepage))
00291            return 0;
00292       }
00293     }
00294     else
00295     {
00296       /* Prefer ANSI codepages if present */
00297       GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE,
00298                      locale->found_codepage, MAX_ELEM_LEN);
00299       if (!locale->found_codepage[0] || !atoi(locale->found_codepage))
00300           GetLocaleInfoA(lcid, LOCALE_IDEFAULTCODEPAGE,
00301                          locale->found_codepage, MAX_ELEM_LEN);
00302     }
00303   }
00304   GetLocaleInfoA(lcid, LOCALE_SENGLANGUAGE|LOCALE_NOUSEROVERRIDE,
00305                  locale->found_language, MAX_ELEM_LEN);
00306   GetLocaleInfoA(lcid, LOCALE_SENGCOUNTRY|LOCALE_NOUSEROVERRIDE,
00307                  locale->found_country, MAX_ELEM_LEN);
00308   return lcid;
00309 }
00310 
00311 /* INTERNAL: Set ctype behaviour for a codepage */
00312 static void msvcrt_set_ctype(unsigned int codepage, LCID lcid)
00313 {
00314   CPINFO cp;
00315 
00316   memset(&cp, 0, sizeof(CPINFO));
00317 
00318   if (GetCPInfo(codepage, &cp))
00319   {
00320     int i;
00321     char str[3];
00322     unsigned char *traverse = cp.LeadByte;
00323 
00324     memset(MSVCRT_current_ctype, 0, sizeof(MSVCRT__ctype));
00325     MSVCRT___lc_codepage = codepage;
00326     MSVCRT___lc_collate_cp = codepage;
00327 
00328     /* Switch ctype macros to MBCS if needed */
00329     __mb_cur_max = cp.MaxCharSize;
00330 
00331     /* Set remaining ctype flags: FIXME: faster way to do this? */
00332     str[1] = str[2] = 0;
00333     for (i = 0; i < 256; i++)
00334     {
00335       if (!(MSVCRT__pctype[i] & MSVCRT_LEADBYTE))
00336       {
00337         str[0] = i;
00338         GetStringTypeA(lcid, CT_CTYPE1, str, 1, MSVCRT__pctype + i);
00339       }
00340     }
00341 
00342     /* Set leadbyte flags */
00343     while (traverse[0] || traverse[1])
00344     {
00345       for( i = traverse[0]; i <= traverse[1]; i++ )
00346         MSVCRT_current_ctype[i+1] |= MSVCRT_LEADBYTE;
00347       traverse += 2;
00348     };
00349   }
00350 }
00351 
00352 
00353 /*
00354  * @implemented
00355  */
00356 char *setlocale(int category, const char *locale)
00357 {
00358   LCID lcid = 0;
00359   locale_search_t lc;
00360   int haveLang, haveCountry, haveCP;
00361   char* next;
00362   int lc_all = 0;
00363 
00364   TRACE("(%d %s)\n",category,locale);
00365 
00366   if (category < MSVCRT_LC_MIN || category > MSVCRT_LC_MAX)
00367     return NULL;
00368 
00369   if (locale == NULL)
00370   {
00371     /* Report the current Locale */
00372     return MSVCRT_current_lc_all;
00373   }
00374 
00375   LOCK_LOCALE;
00376 
00377   if (locale[0] == 'L' && locale[1] == 'C' && locale[2] == '_')
00378   {
00379     WARN(":restore previous locale not implemented!\n");
00380     /* FIXME: Easiest way to do this is parse the string and
00381      * call this function recursively with its elements,
00382      * Where they differ for each lc_ type.
00383      */
00384     UNLOCK_LOCALE;
00385     return MSVCRT_current_lc_all;
00386   }
00387 
00388   /* Default Locale: Special case handling */
00389   if (!strlen(locale) || ((toupper(locale[0]) == 'C') && !locale[1]))
00390   {
00391     MSVCRT_current_lc_all[0] = 'C';
00392     MSVCRT_current_lc_all[1] = '\0';
00393     MSVCRT___lc_codepage = GetACP();
00394     MSVCRT___lc_collate_cp = GetACP();
00395 
00396     switch (category) {
00397     case MSVCRT_LC_ALL:
00398       lc_all = 1; /* Fall through all cases ... */
00399     case MSVCRT_LC_COLLATE:
00400       if (!lc_all) break;
00401     case MSVCRT_LC_CTYPE:
00402       /* Restore C locale ctype info */
00403       __mb_cur_max = 1;
00404       memcpy(MSVCRT_current_ctype, MSVCRT__ctype, sizeof(MSVCRT__ctype));
00405       if (!lc_all) break;
00406     case MSVCRT_LC_MONETARY:
00407       if (!lc_all) break;
00408     case MSVCRT_LC_NUMERIC:
00409       if (!lc_all) break;
00410     case MSVCRT_LC_TIME:
00411       break;
00412     }
00413     UNLOCK_LOCALE;
00414     return MSVCRT_current_lc_all;
00415   }
00416 
00417   /* Get locale elements */
00418   haveLang = haveCountry = haveCP = 0;
00419   memset(&lc,0,sizeof(lc));
00420 
00421   next = strchr(locale,'_');
00422   if (next && next != locale)
00423   {
00424     haveLang = 1;
00425     memcpy(lc.search_language,locale,next-locale);
00426     locale += next-locale+1;
00427   }
00428 
00429   next = strchr(locale,'.');
00430   if (next)
00431   {
00432     haveCP = 1;
00433     if (next == locale)
00434     {
00435       locale++;
00436       lstrcpynA(lc.search_codepage, locale, MAX_ELEM_LEN);
00437     }
00438     else
00439     {
00440       if (haveLang)
00441       {
00442         haveCountry = 1;
00443         memcpy(lc.search_country,locale,next-locale);
00444         locale += next-locale+1;
00445       }
00446       else
00447       {
00448         haveLang = 1;
00449         memcpy(lc.search_language,locale,next-locale);
00450         locale += next-locale+1;
00451       }
00452       lstrcpynA(lc.search_codepage, locale, MAX_ELEM_LEN);
00453     }
00454   }
00455   else
00456   {
00457     if (haveLang)
00458     {
00459       haveCountry = 1;
00460       lstrcpynA(lc.search_country, locale, MAX_ELEM_LEN);
00461     }
00462     else
00463     {
00464       haveLang = 1;
00465       lstrcpynA(lc.search_language, locale, MAX_ELEM_LEN);
00466     }
00467   }
00468 
00469   if (haveCountry)
00470     remap_synonym(lc.search_country);
00471 
00472   if (haveCP && !haveCountry && !haveLang)
00473   {
00474     ERR(":Codepage only locale not implemented\n");
00475     /* FIXME: Use default lang/country and skip locale_to_LCID()
00476      * call below...
00477      */
00478     UNLOCK_LOCALE;
00479     return NULL;
00480   }
00481 
00482   lcid = MSVCRT_locale_to_LCID(&lc);
00483 
00484   TRACE(":found LCID %d\n",lcid);
00485 
00486   if (lcid == 0)
00487   {
00488     UNLOCK_LOCALE;
00489     return NULL;
00490   }
00491 
00492   MSVCRT_current_lc_all_lcid = lcid;
00493 
00494   _snprintf(MSVCRT_current_lc_all,MAX_LOCALE_LENGTH,"%s_%s.%s",
00495        lc.found_language,lc.found_country,lc.found_codepage);
00496 
00497   switch (category) {
00498   case MSVCRT_LC_ALL:
00499     lc_all = 1; /* Fall through all cases ... */
00500   case MSVCRT_LC_COLLATE:
00501     if (!lc_all) break;
00502   case MSVCRT_LC_CTYPE:
00503     msvcrt_set_ctype(atoi(lc.found_codepage),lcid);
00504     if (!lc_all) break;
00505   case MSVCRT_LC_MONETARY:
00506     if (!lc_all) break;
00507   case MSVCRT_LC_NUMERIC:
00508     if (!lc_all) break;
00509   case MSVCRT_LC_TIME:
00510     break;
00511   }
00512   UNLOCK_LOCALE;
00513   return MSVCRT_current_lc_all;
00514 }
00515 
00516 /*
00517  * @unimplemented
00518  */
00519 wchar_t* _wsetlocale(int category, const wchar_t* locale)
00520 {
00521   static wchar_t fake[] = {
00522     'E','n','g','l','i','s','h','_','U','n','i','t','e','d',' ',
00523     'S','t','a','t','e','s','.','1','2','5','2',0 };
00524 
00525   TRACE("%d %S\n", category, locale);
00526 
00527   return fake;
00528 }
00529 
00530 /*
00531 
00532 locale  "lang[_country[.code_page]]"
00533             | ".code_page"
00534             | ""
00535             | NULL
00536 
00537 */
00538 int parse_locale(const char *locale, char *lang, char *country, char *code_page)
00539 {
00540     while ( *locale != 0 && *locale != '.' && *locale != '_' )
00541     {
00542         *lang = *locale;
00543         lang++;
00544         locale++;
00545     }
00546     *lang = 0;
00547     if ( *locale == '_' ) {
00548         locale++;
00549         while ( *locale != 0 && *locale != '.' )
00550         {
00551             *country = *locale;
00552             country++;
00553             locale++;
00554         }
00555     }
00556     *country = 0;
00557 
00558 
00559     if ( *locale == '.' ) {
00560         locale++;
00561         while ( *locale != 0 && *locale != '.' )
00562         {
00563             *code_page = *locale;
00564             code_page++;
00565             locale++;
00566         }
00567     }
00568 
00569     *code_page = 0;
00570     return 0;
00571 }
00572 
00573 const struct map_lcid2str {
00574         short            langid;
00575         const char      *langname;
00576     const char  *country;
00577 } languages[]={
00578         {0x0409,"English", "United States"},
00579         {0x0809,"English", "United Kingdom"},
00580         {0x0000,"Unknown", "Unknown"}
00581 
00582 };
00583 
00584 const struct map_cntr {
00585     const char *abrev;
00586     const char  *country;
00587 } abrev[] = {
00588     {"britain", "united kingdom"},
00589     {"england", "united kingdom"},
00590     {"gbr", "united kingdom"},
00591     {"great britain", "united kingdom"},
00592     {"uk", "united kingdom"},
00593     {"united kingdom", "united kingdom"},
00594     {"united-kingdom", "united kingdom"},
00595     {"america", "united states" },
00596     {"united states", "united states"},
00597     {"united-states", "united states"},
00598     {"us", "united states"},
00599     {"usa", "united states"}
00600 };
00601 
00602 
00603 struct lconv _lconv = {
00604 ".",   // decimal_point
00605 ",",   // thousands_sep
00606 "",    // grouping;
00607 "DOL", // int_curr_symbol
00608 "$",   // currency_symbol
00609 ".",   // mon_decimal_point
00610 ",",   // mon_thousands_sep
00611 "",    // mon_grouping;
00612 "+",   // positive_sign
00613 "-",   // negative_sign
00614 127,     // int_frac_digits
00615 127,     // frac_digits
00616 127,     // p_cs_precedes
00617 127,     // p_sep_by_space
00618 127,     // n_cs_precedes
00619 127,     // n_sep_by_space
00620 127,     // p_sign_posn;
00621 127      // n_sign_posn;
00622 };
00623 
00624 /*
00625  * @implemented
00626  */
00627 struct lconv *localeconv(void)
00628 {
00629   return (struct lconv *) &_lconv;
00630 }
00631 
00632 /*********************************************************************
00633  *      _setmbcp (MSVCRT.@)
00634  * @implemented
00635  */
00636 int CDECL _setmbcp(int cp)
00637 {
00638   int newcp;
00639   CPINFO cpi;
00640   BYTE *bytes;
00641   WORD chartypes[256];
00642   WORD *curr_type;
00643   char bufA[256];
00644   WCHAR bufW[256];
00645   int charcount;
00646   int ret;
00647   int i;
00648 
00649   TRACE("_setmbcp %d\n",cp);
00650   switch (cp)
00651   {
00652     case _MB_CP_ANSI:
00653       newcp = GetACP();
00654       break;
00655     case _MB_CP_OEM:
00656       newcp = GetOEMCP();
00657       break;
00658     case _MB_CP_LOCALE:
00659       newcp = MSVCRT___lc_codepage;
00660       break;
00661     case _MB_CP_SBCS:
00662       newcp = 20127;   /* ASCII */
00663       break;
00664     default:
00665       newcp = cp;
00666       break;
00667   }
00668 
00669   if (!GetCPInfo(newcp, &cpi))
00670   {
00671     ERR("Codepage %d not found\n", newcp);
00672     _set_errno(EINVAL);
00673     return -1;
00674   }
00675 
00676   /* setup the _mbctype */
00677   memset(_mbctype, 0, sizeof(_mbctype));
00678 
00679   bytes = cpi.LeadByte;
00680   while (bytes[0] || bytes[1])
00681   {
00682     for (i = bytes[0]; i <= bytes[1]; i++)
00683       _mbctype[i + 1] |= _M1;
00684     bytes += 2;
00685   }
00686 
00687   if (cpi.MaxCharSize > 1)
00688   {
00689     /* trail bytes not available through kernel32 but stored in a structure in msvcrt */
00690     struct cp_extra_info_t *cpextra = g_cpextrainfo;
00691 
00692     g_mbcp_is_multibyte = 1;
00693     while (TRUE)
00694     {
00695       if (cpextra->cp == 0 || cpextra->cp == newcp)
00696       {
00697         if (cpextra->cp == 0)
00698           ERR("trail bytes data not available for DBCS codepage %d - assuming all bytes\n", newcp);
00699 
00700         bytes = cpextra->TrailBytes;
00701         while (bytes[0] || bytes[1])
00702         {
00703           for (i = bytes[0]; i <= bytes[1]; i++)
00704             _mbctype[i + 1] |= _M2;
00705           bytes += 2;
00706         }
00707         break;
00708       }
00709       cpextra++;
00710     }
00711   }
00712   else
00713     g_mbcp_is_multibyte = 0;
00714 
00715   /* we can't use GetStringTypeA directly because we don't have a locale - only a code page
00716    */
00717   charcount = 0;
00718   for (i = 0; i < 256; i++)
00719     if (!(_mbctype[i + 1] & _M1))
00720       bufA[charcount++] = i;
00721 
00722   ret = MultiByteToWideChar(newcp, 0, bufA, charcount, bufW, charcount);
00723   if (ret != charcount)
00724     ERR("MultiByteToWideChar of chars failed for cp %d, ret=%d (exp %d), error=%d\n", newcp, ret, charcount, GetLastError());
00725 
00726   GetStringTypeW(CT_CTYPE1, bufW, charcount, chartypes);
00727 
00728   curr_type = chartypes;
00729   for (i = 0; i < 256; i++)
00730     if (!(_mbctype[i + 1] & _M1))
00731     {
00732     if ((*curr_type) & C1_UPPER)
00733         _mbctype[i + 1] |= _SBUP;
00734     if ((*curr_type) & C1_LOWER)
00735         _mbctype[i + 1] |= _SBLOW;
00736     curr_type++;
00737     }
00738 
00739   if (newcp == 932)   /* CP932 only - set _MP and _MS */
00740   {
00741     /* On Windows it's possible to calculate the _MP and _MS from CT_CTYPE1
00742      * and CT_CTYPE3. But as of Wine 0.9.43 we return wrong values what makes
00743      * it hard. As this is set only for codepage 932 we hardcode it what gives
00744      * also faster execution.
00745      */
00746     for (i = 161; i <= 165; i++)
00747       _mbctype[i + 1] |= _MP;
00748     for (i = 166; i <= 223; i++)
00749       _mbctype[i + 1] |= _MS;
00750   }
00751 
00752   MSVCRT___lc_collate_cp = MSVCRT___lc_codepage = newcp;
00753   TRACE("(%d) -> %d\n", cp, MSVCRT___lc_codepage);
00754   return 0;
00755 }
00756 
00757 
00758 /*********************************************************************
00759  *      ___lc_handle_func (MSVCRT.@)
00760  */
00761 HANDLE * CDECL ___lc_handle_func(void)
00762 {
00763     return MSVCRT___lc_handle;
00764 }
00765 
00766 
00767 /*********************************************************************
00768  *      ___lc_codepage_func (MSVCRT.@)
00769  */
00770 int CDECL ___lc_codepage_func(void)
00771 {
00772     return MSVCRT___lc_codepage;
00773 }
00774 
00775 
00776 /*********************************************************************
00777  *    _Gettnames (MSVCRT.@)
00778  */
00779 void *_Gettnames(void)
00780 {
00781   FIXME("(void), stub!\n");
00782   return NULL;
00783 }
00784 
00785 /*********************************************************************
00786  *    __lconv_init (MSVCRT.@)
00787  */
00788 void __lconv_init(void)
00789 {
00790   char Char = (char) UCHAR_MAX;
00791 
00792   TRACE("__lconv_init()\n");
00793 
00794   _lconv.int_frac_digits = Char;
00795   _lconv.frac_digits = Char;
00796   _lconv.p_sep_by_space = _lconv.n_sep_by_space = Char;
00797   _lconv.p_cs_precedes = _lconv.n_cs_precedes = Char;
00798   _lconv.p_sign_posn = _lconv.n_sign_posn = Char;
00799 }
00800 
00801 
00802 /*********************************************************************
00803  *    _Strftime (MSVCRT.@)
00804  */
00805 const char* _Strftime(char *out, unsigned int len, const char *fmt,
00806                                      const void *tm, void *foo)
00807 {
00808   /* FIXME: */
00809   FIXME("(%p %d %s %p %p) stub\n", out, len, fmt, tm, foo);
00810   return "";
00811 }
00812 
00813 
00814 /*********************************************************************
00815  *    _Getdays (MSVCRT.@)
00816  */
00817 const char* _Getdays(void)
00818 {
00819   static const char *MSVCRT_days = ":Sun:Sunday:Mon:Monday:Tue:Tuesday:Wed:"
00820                             "Wednesday:Thu:Thursday:Fri:Friday:Sat:Saturday";
00821   /* FIXME: Use locale */
00822   FIXME("(void) semi-stub\n");
00823   return MSVCRT_days;
00824 }
00825 
00826 /*********************************************************************
00827  *    _Getmonths (MSVCRT.@)
00828  */
00829 const char* _Getmonths(void)
00830 {
00831   static const char *MSVCRT_months = ":Jan:January:Feb:February:Mar:March:Apr:"
00832                 "April:May:May:Jun:June:Jul:July:Aug:August:Sep:September:Oct:"
00833                 "October:Nov:November:Dec:December";
00834   /* FIXME: Use locale */
00835   FIXME("(void) semi-stub\n");
00836   return MSVCRT_months;
00837 }
00838 
00839 /*********************************************************************
00840  *    __crtLCMapStringA (MSVCRT.@)
00841  */
00842 int __crtLCMapStringA(
00843   LCID lcid, DWORD mapflags, const char* src, int srclen, char* dst,
00844   int dstlen, unsigned int codepage, int xflag
00845 ) {
00846   TRACE("(lcid %lx, flags %lx, %s(%d), %p(%d), %x, %d), partial stub!\n",
00847         lcid,mapflags,src,srclen,dst,dstlen,codepage,xflag);
00848   /* FIXME: A bit incorrect. But msvcrt itself just converts its
00849    * arguments to wide strings and then calls LCMapStringW
00850    */
00851   return LCMapStringA(lcid,mapflags,src,srclen,dst,dstlen);
00852 }
00853 
00854 /*********************************************************************
00855  *    __crtLCMapStringW (MSVCRT.@)
00856  */
00857 int __crtLCMapStringW(
00858   LCID lcid, DWORD mapflags, LPCWSTR src, int srclen, LPWSTR dst,
00859   int dstlen, unsigned int codepage, int xflag
00860 ) {
00861   TRACE("(lcid %lx, flags %lx, %s(%d), %p(%d), %x, %d), partial stub!\n",
00862         lcid,mapflags,src,srclen,dst,dstlen,codepage,xflag);
00863 
00864   return LCMapStringW(lcid,mapflags,src,srclen,dst,dstlen);
00865 }
00866 
00867 int CDECL _getmbcp(void)
00868 {
00869     return MSVCRT___lc_codepage;
00870 }
00871 
00872 /*********************************************************************
00873  *      ___unguarded_readlc_active_add_func (MSVCRT.@)
00874  */
00875 unsigned int * CDECL ___unguarded_readlc_active_add_func(void)
00876 {
00877   return &__unguarded_readlc_active;
00878 }
00879 
00880 /*********************************************************************
00881  *      ___setlc_active_func (MSVCRT.@)
00882  */
00883 unsigned int CDECL ___setlc_active_func(void)
00884 {
00885   return __setlc_active;
00886 }
00887 
00888 /*********************************************************************
00889  *              __crtGetStringTypeW(MSVCRT.@)
00890  *
00891  * This function was accepting different number of arguments in older
00892  * versions of msvcrt.
00893  */
00894 BOOL CDECL __crtGetStringTypeW(DWORD unk, DWORD type,
00895         wchar_t *buffer, int len, WORD *out)
00896 {
00897     FIXME("(unk %x, type %x, wstr %p(%d), %p) partial stub\n",
00898             unk, type, buffer, len, out);
00899 
00900     return GetStringTypeW(type, buffer, len, out);
00901 }

Generated on Sun May 27 2012 04:18:12 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.