]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
intl: Support the UTF-8 environment on native Windows.
authorBruno Haible <bruno@clisp.org>
Mon, 23 Dec 2024 16:54:38 +0000 (17:54 +0100)
committerBruno Haible <bruno@clisp.org>
Tue, 24 Dec 2024 17:36:19 +0000 (18:36 +0100)
Reported by Lasse Collin <lasse.collin@tukaani.org> in
<https://lists.gnu.org/archive/html/bug-gettext/2024-12/msg00111.html>.

* gettext-runtime/intl/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().

gettext-runtime/intl/setlocale.c

index 71a61a3f1efa06c3e3dcf7450a54572356710f2a..65883b69673a255766575ad98fff753c12d20101 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
+
 /* Get _nl_msg_cat_cntr declaration.  */
 #include "gettextP.h"
 
@@ -669,6 +674,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];
@@ -679,6 +685,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 (category, locale);
   if (result != NULL)
@@ -711,7 +726,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;
         }
@@ -728,7 +751,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;
           }
@@ -782,13 +813,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);
@@ -806,8 +839,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;
                       }