]> Savannah Git Hosting - gnulib.git/commitdiff
setlocale: Support the UTF-8 environment on native Windows.
authorBruno Haible <bruno@clisp.org>
Mon, 23 Dec 2024 15:57:15 +0000 (16:57 +0100)
committerBruno Haible <bruno@clisp.org>
Wed, 25 Dec 2024 14:34:14 +0000 (15:34 +0100)
* lib/setlocale.c: Include <windows.h>.
(setlocale_unixlike): In the UTF-8 environment, append a suffix ".65001"
to the locale names passed to the native setlocale().

ChangeLog
lib/setlocale.c

index a9f8dbad72c867cee78eac5267a9e728582bbb71..91cc478a27508faae3db311ab23c2a72682b68e5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2024-12-23  Bruno Haible  <bruno@clisp.org>
+
+       setlocale: Support the UTF-8 environment on native Windows.
+       * lib/setlocale.c: Include <windows.h>.
+       (setlocale_unixlike): In the UTF-8 environment, append a suffix ".65001"
+       to the locale names passed to the native setlocale().
+
 2024-12-23  Bruno Haible  <bruno@clisp.org>
 
        localename-unsafe: Support the UTF-8 environment on native Windows.
index 62dce81de3a3636ea2fb9e8ce467892c34b5d7ca..c239bd1e2cb4fa8c29821833584b8665a4846e3e 100644 (file)
 extern void gl_locale_name_canonicalize (char *name);
 #endif
 
+#if defined _WIN32 && !defined __CYGWIN__
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
+
 #if 1
 
 # undef setlocale
@@ -672,6 +677,7 @@ search (const struct table_entry *table, size_t table_size, const char *string,
 static char *
 setlocale_unixlike (int category, const char *locale)
 {
+  int is_utf8 = (GetACP () == 65001);
   char *result;
   char llCC_buf[64];
   char ll_buf[64];
@@ -682,6 +688,15 @@ setlocale_unixlike (int category, const char *locale)
   if (locale != NULL && strcmp (locale, "POSIX") == 0)
     locale = "C";
 
+  /* The native Windows implementation of setlocale, in the UTF-8 environment,
+     does not understand the locale names "C.UTF-8" or "C.utf8" or "C.65001",
+     but it understands "English_United States.65001", which is functionally
+     equivalent.  */
+  if (locale != NULL
+      && ((is_utf8 && strcmp (locale, "C") == 0)
+          || strcmp (locale, "C.UTF-8") == 0))
+    locale = "English_United States.65001";
+
   /* First, try setlocale with the original argument unchanged.  */
   result = setlocale_mtsafe (category, locale);
   if (result != NULL)
@@ -714,7 +729,15 @@ setlocale_unixlike (int category, const char *locale)
        */
       if (strcmp (llCC_buf, locale) != 0)
         {
-          result = setlocale (category, llCC_buf);
+          if (is_utf8)
+            {
+              char buf[64+6];
+              strcpy (buf, llCC_buf);
+              strcat (buf, ".65001");
+              result = setlocale (category, buf);
+            }
+          else
+            result = setlocale (category, llCC_buf);
           if (result != NULL)
             return result;
         }
@@ -731,7 +754,15 @@ setlocale_unixlike (int category, const char *locale)
         for (i = range.lo; i < range.hi; i++)
           {
             /* Try the replacement in language_table[i].  */
-            result = setlocale (category, language_table[i].english);
+            if (is_utf8)
+              {
+                char buf[64+6];
+                strcpy (buf, language_table[i].english);
+                strcat (buf, ".65001");
+                result = setlocale (category, buf);
+              }
+            else
+              result = setlocale (category, language_table[i].english);
             if (result != NULL)
               return result;
           }
@@ -785,13 +816,15 @@ setlocale_unixlike (int category, const char *locale)
                             size_t part1_len = strlen (part1);
                             const char *part2 = country_table[j].english;
                             size_t part2_len = strlen (part2) + 1;
-                            char buf[64+64];
+                            char buf[64+64+6];
 
-                            if (!(part1_len + 1 + part2_len <= sizeof (buf)))
+                            if (!(part1_len + 1 + part2_len + 6 <= sizeof (buf)))
                               abort ();
                             memcpy (buf, part1, part1_len);
                             buf[part1_len] = '_';
                             memcpy (buf + part1_len + 1, part2, part2_len);
+                            if (is_utf8)
+                              strcat (buf, ".65001");
 
                             /* Try the concatenated replacements.  */
                             result = setlocale (category, buf);
@@ -809,8 +842,16 @@ setlocale_unixlike (int category, const char *locale)
                     for (i = language_range.lo; i < language_range.hi; i++)
                       {
                         /* Try only the language replacement.  */
-                        result =
-                          setlocale (category, language_table[i].english);
+                        if (is_utf8)
+                          {
+                            char buf[64+6];
+                            strcpy (buf, language_table[i].english);
+                            strcat (buf, ".65001");
+                            result = setlocale (category, buf);
+                          }
+                        else
+                          result =
+                            setlocale (category, language_table[i].english);
                         if (result != NULL)
                           return result;
                       }