X-Git-Url: https://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fsetlocale.c;h=c729fa6f751dd6dce70086ceadbacbf03eb75c98;hb=84d1749c4b5ad026522be96537320556ec6f7a57;hp=9fe1aa9fa7f9ff016a049e2a0c03ba48d5d1affc;hpb=4f1d12a5e3cef3d0da80e63320fcbc4d46a39c14;p=gnulib.git diff --git a/lib/setlocale.c b/lib/setlocale.c index 9fe1aa9fa..c729fa6f7 100644 --- a/lib/setlocale.c +++ b/lib/setlocale.c @@ -1,5 +1,5 @@ /* Set the current locale. - Copyright (C) 2009, 2011 Free Software Foundation, Inc. + Copyright (C) 2009, 2011-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -74,7 +74,7 @@ category_to_name (int category) # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ -/* The native Win32 setlocale() function expects locale names of the form +/* The native Windows setlocale() function expects locale names of the form "German" or "German_Germany" or "DEU", but not "de" or "de_DE". We need to convert the names from the form with ISO 639 language code and ISO 3166 country code to the form with English names or with three-letter identifier. @@ -844,6 +844,14 @@ rpl_setlocale (int category, const char *locale) 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 @@ rpl_setlocale (int category, const char *locale) } } 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