Piotr Caban : msvcrt: Use default user locale when only codepage is passed to setlocale.

Alexandre Julliard julliard at winehq.org
Fri Sep 18 15:52:50 CDT 2020


Module: wine
Branch: master
Commit: dc117553905c1b779ef083aa7418d169cd180a3d
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=dc117553905c1b779ef083aa7418d169cd180a3d

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Fri Sep 18 15:52:54 2020 +0200

msvcrt: Use default user locale when only codepage is passed to setlocale.

Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/msvcrt/locale.c | 172 +++++++++++++++++++++------------------------------
 1 file changed, 71 insertions(+), 101 deletions(-)

diff --git a/dlls/msvcrt/locale.c b/dlls/msvcrt/locale.c
index 9a10ceabc4..7562f70eb0 100644
--- a/dlls/msvcrt/locale.c
+++ b/dlls/msvcrt/locale.c
@@ -176,18 +176,17 @@ static void remap_synonym(char *name)
 }
 
 /* Note: Flags are weighted in order of matching importance */
-#define FOUND_SNAME            0x8
-#define FOUND_LANGUAGE         0x4
-#define FOUND_COUNTRY          0x2
-#define FOUND_CODEPAGE         0x1
+#define FOUND_SNAME            0x4
+#define FOUND_LANGUAGE         0x2
+#define FOUND_COUNTRY          0x1
 
 typedef struct {
   char search_language[MAX_ELEM_LEN];
   char search_country[MAX_ELEM_LEN];
-  char search_codepage[MAX_ELEM_LEN];
   DWORD found_codepage;
   unsigned int match_flags;
   LANGID found_lang_id;
+  BOOL allow_sname;
 } locale_search_t;
 
 #define CONTINUE_LOOKING TRUE
@@ -226,8 +225,7 @@ find_best_locale_proc(HMODULE hModule, LPCSTR type, LPCSTR name, WORD LangID, LO
     return CONTINUE_LOOKING;
 
 #if _MSVCR_VER >= 110
-  if (!res->search_country[0] && !res->search_codepage[0] &&
-          compare_info(lcid,LOCALE_SNAME,buff,res->search_language, TRUE))
+  if (res->allow_sname && compare_info(lcid,LOCALE_SNAME,buff,res->search_language, TRUE))
   {
     TRACE(":Found locale: %s->%s\n", res->search_language, buff);
     res->match_flags = FOUND_SNAME;
@@ -262,27 +260,14 @@ find_best_locale_proc(HMODULE hModule, LPCSTR type, LPCSTR name, WORD LangID, LO
     return CONTINUE_LOOKING;
   }
 
-  /* Check codepage */
-  if (compare_info(lcid,LOCALE_IDEFAULTCODEPAGE,buff,res->search_codepage, TRUE) ||
-      (compare_info(lcid,LOCALE_IDEFAULTANSICODEPAGE,buff,res->search_codepage, TRUE)))
-  {
-    TRACE("Found codepage:%s->%s\n", res->search_codepage, buff);
-    flags |= FOUND_CODEPAGE;
-    res->found_codepage = atoi(res->search_codepage);
-  }
-  else if (!flags && (res->match_flags & FOUND_CODEPAGE))
-  {
-    return CONTINUE_LOOKING;
-  }
-
   if (flags > res->match_flags)
   {
     /* Found a better match than previously */
     res->match_flags = flags;
     res->found_lang_id = LangID;
   }
-  if ((flags & (FOUND_LANGUAGE | FOUND_COUNTRY | FOUND_CODEPAGE)) ==
-        (FOUND_LANGUAGE | FOUND_COUNTRY | FOUND_CODEPAGE))
+  if ((flags & (FOUND_LANGUAGE | FOUND_COUNTRY)) ==
+        (FOUND_LANGUAGE | FOUND_COUNTRY))
   {
     TRACE(":found exact locale match\n");
     return STOP_LOOKING;
@@ -290,15 +275,14 @@ find_best_locale_proc(HMODULE hModule, LPCSTR type, LPCSTR name, WORD LangID, LO
   return CONTINUE_LOOKING;
 }
 
-extern int atoi(const char *);
-
 /* Internal: Find the LCID for a locale specification */
 LCID MSVCRT_locale_to_LCID(const char *locale, unsigned short *codepage, BOOL *sname)
 {
     thread_data_t *data = msvcrt_get_thread_data();
-    LCID lcid;
-    locale_search_t search;
     const char *cp, *region;
+    BOOL is_sname = FALSE;
+    DWORD locale_cp;
+    LCID lcid;
 
     if (!strcmp(locale, data->cached_locale)) {
         if (codepage)
@@ -308,88 +292,84 @@ LCID MSVCRT_locale_to_LCID(const char *locale, unsigned short *codepage, BOOL *s
         return data->cached_lcid;
     }
 
-    memset(&search, 0, sizeof(locale_search_t));
-
     cp = strchr(locale, '.');
     region = strchr(locale, '_');
 
-    lstrcpynA(search.search_language, locale, MAX_ELEM_LEN);
-    if(region) {
-        lstrcpynA(search.search_country, region+1, MAX_ELEM_LEN);
-        if(region-locale < MAX_ELEM_LEN)
-            search.search_language[region-locale] = '\0';
-    } else
-        search.search_country[0] = '\0';
-
-    if(cp) {
-        lstrcpynA(search.search_codepage, cp+1, MAX_ELEM_LEN);
-        if(region && cp-region-1<MAX_ELEM_LEN)
-          search.search_country[cp-region-1] = '\0';
-        if(cp-locale < MAX_ELEM_LEN)
-            search.search_language[cp-locale] = '\0';
-    } else
-        search.search_codepage[0] = '\0';
+    if(!locale[0] || (cp == locale && !region)) {
+        lcid = GetUserDefaultLCID();
+    } else {
+        locale_search_t search;
+
+        memset(&search, 0, sizeof(locale_search_t));
+        lstrcpynA(search.search_language, locale, MAX_ELEM_LEN);
+        if(region) {
+            lstrcpynA(search.search_country, region+1, MAX_ELEM_LEN);
+            if(region-locale < MAX_ELEM_LEN)
+                search.search_language[region-locale] = '\0';
+        } else
+            search.search_country[0] = '\0';
+
+        if(cp) {
+            if(region && cp-region-1<MAX_ELEM_LEN)
+                search.search_country[cp-region-1] = '\0';
+            if(cp-locale < MAX_ELEM_LEN)
+                search.search_language[cp-locale] = '\0';
+        }
+
+        if(!cp && !region)
+        {
+            remap_synonym(search.search_language);
+            search.allow_sname = TRUE;
+        }
 
-    if(!search.search_country[0] && !search.search_codepage[0])
-        remap_synonym(search.search_language);
+        if(!MSVCRT__stricmp(search.search_country, "China"))
+            strcpy(search.search_country, "People's Republic of China");
 
-    if(!MSVCRT__stricmp(search.search_country, "China"))
-        strcpy(search.search_country, "People's Republic of China");
+        EnumResourceLanguagesA(GetModuleHandleA("KERNEL32"), (LPSTR)RT_STRING,
+                (LPCSTR)LOCALE_ILANGUAGE,find_best_locale_proc,
+                (LONG_PTR)&search);
 
-    EnumResourceLanguagesA(GetModuleHandleA("KERNEL32"), (LPSTR)RT_STRING,
-            (LPCSTR)LOCALE_ILANGUAGE,find_best_locale_proc,
-            (LONG_PTR)&search);
+        if (!search.match_flags)
+            return -1;
 
-    if (!search.match_flags)
-        return -1;
+        /* If we were given something that didn't match, fail */
+        if (search.search_language[0] && !(search.match_flags & (FOUND_SNAME | FOUND_LANGUAGE)))
+            return -1;
+        if (search.search_country[0] && !(search.match_flags & FOUND_COUNTRY))
+            return -1;
+
+        lcid =  MAKELCID(search.found_lang_id, SORT_DEFAULT);
+        is_sname = (search.match_flags & FOUND_SNAME) != 0;
+    }
 
-    /* If we were given something that didn't match, fail */
-    if (search.search_language[0] && !(search.match_flags & (FOUND_SNAME | FOUND_LANGUAGE)))
+    /* Obtain code page */
+    if (!cp || !cp[1] || !MSVCRT__strnicmp(cp, ".ACP", 4)) {
+        GetLocaleInfoW(lcid, LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER,
+                (WCHAR *)&locale_cp, sizeof(DWORD)/sizeof(WCHAR));
+        if (!locale_cp)
+            locale_cp = GetACP();
+    } else if (!MSVCRT__strnicmp(cp, ".OCP", 4)) {
+        GetLocaleInfoW(lcid, LOCALE_IDEFAULTCODEPAGE | LOCALE_RETURN_NUMBER,
+                (WCHAR *)&locale_cp, sizeof(DWORD)/sizeof(WCHAR));
+    } else {
+        locale_cp = atoi(cp + 1);
+    }
+    if (!IsValidCodePage(locale_cp))
         return -1;
-    if (search.search_country[0] && !(search.match_flags & FOUND_COUNTRY))
+
+    if (!locale_cp)
         return -1;
 
-    lcid =  MAKELCID(search.found_lang_id, SORT_DEFAULT);
-
-    /* Populate partial locale, translating LCID to locale string elements */
-    if (!(search.match_flags & FOUND_CODEPAGE)) {
-        /* Even if a codepage is not enumerated for a locale
-         * it can be set if valid */
-        if (search.search_codepage[0]) {
-            search.found_codepage = atoi(search.search_codepage);
-            if (!IsValidCodePage(atoi(search.search_codepage)))
-            {
-                /* Special codepage values: OEM & ANSI */
-                if (!MSVCRT__stricmp(search.search_codepage,"OCP")) {
-                    GetLocaleInfoW(lcid, LOCALE_IDEFAULTCODEPAGE | LOCALE_RETURN_NUMBER,
-                                   (WCHAR *)&search.found_codepage, sizeof(DWORD)/sizeof(WCHAR));
-                } else if (!MSVCRT__stricmp(search.search_codepage,"ACP")) {
-                    GetLocaleInfoW(lcid, LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER,
-                                   (WCHAR *)&search.found_codepage, sizeof(DWORD)/sizeof(WCHAR));
-                } else
-                    return -1;
-                if (!search.found_codepage)
-                    return -1;
-            }
-        } else {
-            /* Prefer ANSI codepages if present */
-            GetLocaleInfoW(lcid, LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER,
-                           (WCHAR *)&search.found_codepage, sizeof(DWORD)/sizeof(WCHAR));
-            if (!search.found_codepage)
-                GetLocaleInfoW(lcid, LOCALE_IDEFAULTCODEPAGE | LOCALE_RETURN_NUMBER,
-                               (WCHAR *)&search.found_codepage, sizeof(DWORD)/sizeof(WCHAR));
-        }
-    }
     if (codepage)
-        *codepage = search.found_codepage;
+        *codepage = locale_cp;
     if (sname)
-        *sname = (search.match_flags & FOUND_SNAME) != 0;
+        *sname = is_sname;
 
     if (strlen(locale) < sizeof(data->cached_locale)) {
         strcpy(data->cached_locale, locale);
         data->cached_lcid = lcid;
-        data->cached_cp = codepage ? *codepage : search.found_codepage;
-        data->cached_sname = (search.match_flags & FOUND_SNAME) != 0;
+        data->cached_cp = locale_cp;
+        data->cached_sname = is_sname;
     }
 
     return lcid;
@@ -1129,16 +1109,6 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
     if(locale[0]=='C' && !locale[1]) {
         lcid[0] = 0;
         cp[0] = CP_ACP;
-    } else if(!locale[0]) {
-        lcid[0] = GetSystemDefaultLCID();
-        GetLocaleInfoA(lcid[0], LOCALE_IDEFAULTANSICODEPAGE
-                |LOCALE_NOUSEROVERRIDE, buf, sizeof(buf));
-        cp[0] = atoi(buf);
-
-        for(i=1; i<6; i++) {
-            lcid[i] = lcid[0];
-            cp[i] = cp[0];
-        }
     } else if (locale[0] == 'L' && locale[1] == 'C' && locale[2] == '_') {
         const char *p;
 




More information about the wine-cvs mailing list