> I'm therefore taking the code from gettext. It provides a workaround against > the problems 1 and 3.
And here's the fix for problem 2. 2011-02-11 Bruno Haible <br...@clisp.org> setlocale: Workaround native Windows bug. * lib/setlocale.c (rpl_setlocale): On native Windows, when setlocale succeeds but sets LC_CTYPE to "C", report a failure. * tests/test-setlocale2.sh: New file. * tests/test-setlocale2.c: New file. * modules/setlocale-tests (Files): Add the new files. (Makefile.am): Enable test-setlocale2.sh test. * doc/posix-functions/setlocale.texi: Mention workaround. --- doc/posix-functions/setlocale.texi.orig Sat Feb 12 18:14:38 2011 +++ doc/posix-functions/setlocale.texi Sat Feb 12 17:15:50 2011 @@ -13,6 +13,10 @@ ignores the environment variables @code{LC_ALL}, @code{@var{category}}, and @code{LANG}. @item +On Windows platforms (excluding Cygwin), @code{setlocale(LC_ALL,@var{name})} +succeeds and sets the LC_CTYPE category to @samp{C} when it does not support +the encoding, instead of failing. +@item On Windows platforms (excluding Cygwin), @code{setlocale} understands different locale names, that are not based on ISO 639 language names and ISO 3166 country names. @@ -25,8 +29,4 @@ @code{setlocale(LC_ALL,NULL)} always returns @code{"C"}. @item On Cygwin 1.7.0, only the charset portion of a locale designation is honored. -@item -On Windows platforms (excluding Cygwin), @code{setlocale(LC_ALL,@var{name})} -succeeds and sets the LC_CTYPE category to @samp{C} when it does not support -the encoding, instead of failing. @end itemize --- lib/setlocale.c.orig Sat Feb 12 18:14:38 2011 +++ lib/setlocale.c Sat Feb 12 18:14:34 2011 @@ -844,6 +844,14 @@ if (setlocale_unixlike (LC_ALL, base_name) == NULL) goto fail; +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + /* On native Windows, setlocale(LC_ALL,...) may succeed but set the + LC_CTYPE category to an invalid value ("C") when it does not + support the specified encoding. Report a failure instead. */ + if (strchr (base_name, '.') != NULL + && strcmp (setlocale (LC_CTYPE, NULL), "C") == 0) + goto fail; +# endif for (i = 0; i < sizeof (categories) / sizeof (categories[0]); i++) { @@ -886,7 +894,45 @@ } } else - return setlocale_single (category, locale); + { +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + if (category == LC_ALL && locale != NULL && strchr (locale, '.') != NULL) + { + char *saved_locale; + + /* Back up the old locale. */ + saved_locale = setlocale (LC_ALL, NULL); + if (saved_locale == NULL) + return NULL; + saved_locale = strdup (saved_locale); + if (saved_locale == NULL) + return NULL; + + if (setlocale_unixlike (LC_ALL, locale) == NULL) + { + free (saved_locale); + return NULL; + } + + /* On native Windows, setlocale(LC_ALL,...) may succeed but set the + LC_CTYPE category to an invalid value ("C") when it does not + support the specified encoding. Report a failure instead. */ + if (strcmp (setlocale (LC_CTYPE, NULL), "C") == 0) + { + if (saved_locale[0] != '\0') /* don't risk an endless recursion */ + setlocale (LC_ALL, saved_locale); + free (saved_locale); + return NULL; + } + + /* It was really successful. */ + free (saved_locale); + return setlocale (LC_ALL, NULL); + } + else +# endif + return setlocale_single (category, locale); + } } #endif -- In memoriam France Bloch-Sérazin <http://en.wikipedia.org/wiki/France_Bloch-Sérazin>