From dcf4f2ef1e083443c8fe1069b21c0aa0c44e1237 Mon Sep 17 00:00:00 2001 From: Tor Lillqvist Date: Tue, 10 Oct 2006 21:51:11 +0000 Subject: [PATCH] Merge from 2.10 branch: 2006-10-11 Tor Lillqvist Merge from 2.10 branch: * gtk/gtkmain.c (do_pre_parse_initialization): On Win32, if environment variable LC_ALL or LANG is set, set the Win32 thread locale to the corresponding locale. Then call the C library setlocale() to set the C library locale accordingly. The inconsistency mentioned below is gone. (#339756) Do some special casing for Serbia and Montenegro. Handle the Latin and Cyrillic scripts for Azeri, Uzbek and Serbian. (enum_locale_proc): Helper function for the above functionality. * gtk/gtkcalendar.c (gtk_calendar_init): No longer need to check if the environment variables are set here, as they have already been taken into account and the Win32 thread locale has been set. --- ChangeLog | 18 ++++++ gtk/gtkcalendar.c | 34 ++++------- gtk/gtkmain.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 175 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6a68eb8cb7..dca71c12f9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2006-10-11 Tor Lillqvist + + Merge from 2.10 branch: + + * gtk/gtkmain.c (do_pre_parse_initialization): On Win32, if + environment variable LC_ALL or LANG is set, set the Win32 thread + locale to the corresponding locale. Then call the C library + setlocale() to set the C library locale accordingly. The + inconsistency mentioned below is gone. (#339756) Do some special + casing for Serbia and Montenegro. Handle the Latin and Cyrillic + scripts for Azeri, Uzbek and Serbian. + (enum_locale_proc): Helper function for the above functionality. + + * gtk/gtkcalendar.c (gtk_calendar_init): No longer need to check + if the environment variables are set here, as they have already + been taken into account and the Win32 thread locale has been + set. + Tue Oct 10 16:38:23 2006 Tim Janik * gtk/tmpl/gtkbindings.sgml: diff --git a/gtk/gtkcalendar.c b/gtk/gtkcalendar.c index eb97c1f8e0..9197706908 100644 --- a/gtk/gtkcalendar.c +++ b/gtk/gtkcalendar.c @@ -674,31 +674,19 @@ gtk_calendar_init (GtkCalendar *calendar) g_warning ("Whoever translated calendar:MY did so wrongly.\n"); #ifdef G_OS_WIN32 - /* Check if any of those environment variables that affect the - * behaviour of gettext are set. If not, we use the thread's - * locale's week start day. - */ - if (getenv ("LANGUAGE") == NULL && - getenv ("LC_ALL") == NULL && - getenv ("LC_MESSAGES") == NULL && - getenv ("LANG") == NULL) - { - priv->week_start = 0; - week_start = NULL; + priv->week_start = 0; + week_start = NULL; - if (GetLocaleInfoW (GetThreadLocale (), LOCALE_IFIRSTDAYOFWEEK, - wbuffer, G_N_ELEMENTS (wbuffer))) - week_start = g_utf16_to_utf8 (wbuffer, -1, NULL, NULL, NULL); + if (GetLocaleInfoW (GetThreadLocale (), LOCALE_IFIRSTDAYOFWEEK, + wbuffer, G_N_ELEMENTS (wbuffer))) + week_start = g_utf16_to_utf8 (wbuffer, -1, NULL, NULL, NULL); - if (week_start != NULL) - { - priv->week_start = (week_start[0] - '0' + 1) % 7; - g_free(week_start); - } - } - else + if (week_start != NULL) { -#endif + priv->week_start = (week_start[0] - '0' + 1) % 7; + g_free(week_start); + } +#else #ifdef HAVE__NL_TIME_FIRST_WEEKDAY langinfo = nl_langinfo (_NL_TIME_FIRST_WEEKDAY); first_weekday = langinfo[0]; @@ -730,8 +718,6 @@ gtk_calendar_init (GtkCalendar *calendar) priv->week_start = 0; } #endif -#ifdef G_OS_WIN32 - } #endif calendar_compute_days (calendar); diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index 92af98a25f..8168e573b6 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -417,6 +417,95 @@ static const GOptionEntry gtk_args[] = { { NULL } }; +#ifdef G_OS_WIN32 + +static char *iso639_to_check = NULL; +static char *iso3166_to_check = NULL; +static char *script_to_check = NULL; +static gboolean setlocale_called = FALSE; + +static BOOL CALLBACK +enum_locale_proc (LPTSTR locale) +{ + LCID lcid; + char iso639[10]; + char iso3166[10]; + char *endptr; + + + lcid = strtoul (locale, &endptr, 16); + if (*endptr == '\0' && + GetLocaleInfo (lcid, LOCALE_SISO639LANGNAME, iso639, sizeof (iso639)) && + GetLocaleInfo (lcid, LOCALE_SISO3166CTRYNAME, iso3166, sizeof (iso3166))) + { + if (strcmp (iso639, iso639_to_check) == 0 && + ((iso3166_to_check != NULL && + strcmp (iso3166, iso3166_to_check) == 0) || + (iso3166_to_check == NULL && + SUBLANGID (LANGIDFROMLCID (lcid)) == SUBLANG_DEFAULT))) + { + char language[100], country[100]; + char locale[300]; + + if (script_to_check != NULL) + { + /* If lcid is the "other" script for this language, + * return TRUE, i.e. continue looking. + */ + if (strcmp (script_to_check, "Latn") == 0) + { + switch (LANGIDFROMLCID (lcid)) + { + case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_CYRILLIC): + return TRUE; + case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_CYRILLIC): + return TRUE; + case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC): + return TRUE; + case MAKELANGID (LANG_SERBIAN, 0x07): + /* Serbian in Bosnia and Herzegovina, Cyrillic */ + return TRUE; + } + } + else if (strcmp (script_to_check, "Cyrl") == 0) + { + switch (LANGIDFROMLCID (lcid)) + { + case MAKELANGID (LANG_AZERI, SUBLANG_AZERI_LATIN): + return TRUE; + case MAKELANGID (LANG_UZBEK, SUBLANG_UZBEK_LATIN): + return TRUE; + case MAKELANGID (LANG_SERBIAN, SUBLANG_SERBIAN_LATIN): + return TRUE; + case MAKELANGID (LANG_SERBIAN, 0x06): + /* Serbian in Bosnia and Herzegovina, Latin */ + return TRUE; + } + } + } + + SetThreadLocale (lcid); + + if (GetLocaleInfo (lcid, LOCALE_SENGLANGUAGE, language, sizeof (language)) && + GetLocaleInfo (lcid, LOCALE_SENGCOUNTRY, country, sizeof (country))) + { + strcpy (locale, language); + strcat (locale, "_"); + strcat (locale, country); + + if (setlocale (LC_ALL, locale) != NULL) + setlocale_called = TRUE; + } + + return FALSE; + } + } + + return TRUE; +} + +#endif + static void do_pre_parse_initialization (int *argc, char ***argv) @@ -432,8 +521,66 @@ do_pre_parse_initialization (int *argc, if (do_setlocale) { +#ifdef G_OS_WIN32 + /* If some of the POSIXish environment variables are set, set + * the Win32 thread locale correspondingly. + */ + char *p = getenv ("LC_ALL"); + if (p == NULL) + p = getenv ("LANG"); + + if (p != NULL) + { + p = g_strdup (p); + if (strcmp (p, "C") == 0) + SetThreadLocale (LOCALE_SYSTEM_DEFAULT); + else + { + /* Check if one of the supported locales match the + * environment variable. If so, use that locale. + */ + iso639_to_check = p; + iso3166_to_check = strchr (iso639_to_check, '_'); + if (iso3166_to_check != NULL) + { + *iso3166_to_check++ = '\0'; + + script_to_check = strchr (iso3166_to_check, '@'); + if (script_to_check != NULL) + *script_to_check++ = '\0'; + + /* Handle special cases. */ + + /* The standard code for Serbia and Montenegro was + * "CS", but MSFT uses for some reason "SP". By now + * (October 2006), SP has split into two, "RS" and + * "ME", but don't bother trying to handle those + * yet. Do handle the even older "YU", though. + */ + if (strcmp (iso3166_to_check, "CS") == 0 || + strcmp (iso3166_to_check, "YU") == 0) + iso3166_to_check = "SP"; + } + else + { + script_to_check = strchr (iso639_to_check, '@'); + if (script_to_check != NULL) + *script_to_check++ = '\0'; + /* LANG_SERBIAN == LANG_CROATIAN, recognize just "sr" */ + if (strcmp (iso639_to_check, "sr") == 0) + iso3166_to_check = "SP"; + } + + EnumSystemLocales (enum_locale_proc, LCID_SUPPORTED); + } + g_free (p); + } + if (!setlocale_called) + setlocale (LC_ALL, ""); +#else if (!setlocale (LC_ALL, "")) g_warning ("Locale not supported by C library.\n\tUsing the fallback 'C' locale."); +#endif } gdk_pre_parse_libgtk_only ();