From 8cb7464130634551fd2f043efc14f8f8f8bdf447 Mon Sep 17 00:00:00 2001 From: Stephan Bergmann Date: Thu, 27 Sep 2012 08:31:41 +0200 Subject: [PATCH] No dictionaries were preselected for en_US langpack ...as gm_Langpack_r_en_US was explicitly excluded from langs[] in SelectLanguage, so addMatchingDictionaries was never called for it. (This was only evident in installation sets conaining only few langpacks, as the "official" multi-lang installation set also contains en_GB etc., so appropriate dictionaries were selected through those.) Reworked the logic of chosing which langpacks to preselect (see the comment in SelectLanguage); hope it still works as intended for the various cases (of which the "official" multi-lang installation set is the only truly relevant one, for now). Change-Id: I31f531194c79e49c9c09e33454a7b0a82d9ff02f --- .../win32/customactions/sellang/sellang.cxx | 162 ++++++++---------- 1 file changed, 71 insertions(+), 91 deletions(-) mode change 100644 => 100755 setup_native/source/win32/customactions/sellang/sellang.cxx diff --git a/setup_native/source/win32/customactions/sellang/sellang.cxx b/setup_native/source/win32/customactions/sellang/sellang.cxx old mode 100644 new mode 100755 index af8a9a140851..27623cbab1f3 --- a/setup_native/source/win32/customactions/sellang/sellang.cxx +++ b/setup_native/source/win32/customactions/sellang/sellang.cxx @@ -172,7 +172,7 @@ langid_to_string( LANGID langid ) CASE(sh, SERBIAN, SERBIAN_LATIN); CASE(sr, SERBIAN, SERBIAN_CYRILLIC); #undef CASE - default: return ""; + default: return 0; } } } @@ -183,14 +183,20 @@ langid_to_string( LANGID langid ) static const char *ui_langs[MAX_LANGUAGES]; static int num_ui_langs = 0; +void add_ui_lang(char const * lang) +{ + if (lang != 0 && num_ui_langs != SAL_N_ELEMENTS(ui_langs)) { + ui_langs[num_ui_langs++] = lang; + } +} + BOOL CALLBACK enum_ui_lang_proc (LPTSTR language, LONG_PTR /* unused_lParam */) { long langid = strtol(language, NULL, 16); if (langid > 0xFFFF) return TRUE; - ui_langs[num_ui_langs] = langid_to_string((LANGID) langid); - num_ui_langs++; + add_ui_lang(langid_to_string((LANGID) langid)); if (num_ui_langs == SAL_N_ELEMENTS(ui_langs) ) return FALSE; return TRUE; @@ -207,12 +213,13 @@ present_in_ui_langs(const char *lang) namespace { -struct Dictionary { +struct InstallLocalized { char lang[sizeof("xx_XX")]; bool install; }; -void addMatchingDictionaries(char const * lang, Dictionary * dicts, int ndicts) +void addMatchingDictionaries( + char const * lang, InstallLocalized * dicts, int ndicts) { for (int i = 0; i != SAL_N_ELEMENTS(setup_native::languageDictionaries); ++i) @@ -242,9 +249,9 @@ extern "C" UINT __stdcall SelectLanguage( MSIHANDLE handle ) MSIHANDLE database, view, record; DWORD length; int nlangs = 0; - char langs[MAX_LANGUAGES][6]; + InstallLocalized langs[MAX_LANGUAGES]; int ndicts = 0; - Dictionary dicts[MAX_LANGUAGES]; + InstallLocalized dicts[MAX_LANGUAGES]; database = MsiGetActiveDatabase(handle); @@ -269,11 +276,11 @@ extern "C" UINT __stdcall SelectLanguage( MSIHANDLE handle ) return ERROR_SUCCESS; } - /* Keep track of what languages are included in this installer, if - * it is a multilanguage one. + /* Keep track of what langpacks are included in this installer. */ - if (strcmp(feature, "gm_Langpack_r_en_US") != 0) - strcpy(langs[nlangs++], feature + strlen("gm_Langpack_r_")); + strcpy(langs[nlangs].lang, feature + strlen("gm_Langpack_r_")); + langs[nlangs].install = false; + ++nlangs; MsiCloseHandle(record); } @@ -315,92 +322,65 @@ extern "C" UINT __stdcall SelectLanguage( MSIHANDLE handle ) MsiCloseHandle(view); } - if (nlangs > 0) { - int i; - char* pVal = NULL; - if ( (GetMsiProp( handle, "UI_LANGS", &pVal )) && pVal ) { - /* user gave UI languages explicitely with UI_LANGS property */ - int sel_ui_lang = 0; - strcpy(langs[nlangs++], "en_US"); - char *str_ptr; - str_ptr = strtok(pVal, ","); - for(; str_ptr != NULL ;) { - ui_langs[num_ui_langs] = str_ptr; - num_ui_langs++; - str_ptr = strtok(NULL, ","); - } - for (i = 0; i < nlangs; i++) { - if (!present_in_ui_langs(langs[i])) { - UINT rc; - sprintf(feature, "gm_Langpack_r_%s", langs[i]); - rc = MsiSetFeatureStateA(handle, feature, INSTALLSTATE_ABSENT); - } - else { - addMatchingDictionaries(langs[i], dicts, ndicts); - sel_ui_lang++; - } - } - if ( sel_ui_lang == 0 ) { - /* When UI_LANG property contains only languages that are not present - * in the installer, install at least en_US localization. - */ - MsiSetFeatureStateA(handle, "gm_Langpack_r_en_US", INSTALLSTATE_LOCAL); - addMatchingDictionaries("en_US", dicts, ndicts); + /* Keep track of what UI languages are relevant, either the ones explicitly + * requested with the UI_LANGS property, or all available on the system: + */ + char* pVal = NULL; + if ( (GetMsiProp( handle, "UI_LANGS", &pVal )) && pVal ) { + char *str_ptr; + str_ptr = strtok(pVal, ","); + for(; str_ptr != NULL ;) { + add_ui_lang(str_ptr); + str_ptr = strtok(NULL, ","); + } + } else { + add_ui_lang(langid_to_string(GetSystemDefaultUILanguage())); + add_ui_lang(langid_to_string(LANGIDFROMLCID(GetThreadLocale()))); + //TODO: are the above two explicit additions necessary, or will + // those values always be included in the below EnumUILanguages + // anyway? + EnumUILanguagesA(enum_ui_lang_proc, 0, 0); + } + + // If the set of langpacks that match any of the relevant UI languages is + // non-empty, select just those matching langpacks; otherwise, if an en_US + // langpack is included, select just that langpack (this happens if, e.g., + // a multi-language en-US,de,es,fr,it,pt-BR installation set is installed on + // a Finnish Windows); otherwise, select all langpacks (this happens if, + // e.g., a single-language de installation set is installed on a Finnish + // Windows): + bool matches = false; + for (int i = 0; i < nlangs; i++) { + if (present_in_ui_langs(langs[i].lang)) { + langs[i].install = true; + matches = true; + } + } + if (!matches) { + for (int i = 0; i < nlangs; i++) { + if (strcmp(langs[nlangs].lang, "en_US") == 0) { + langs[i].install = true; + matches = true; + break; } } - else { - /* Deselect those languages that don't match any of the UI languages - * available on the system. - */ - - const char *system_default_lang = langid_to_string(GetSystemDefaultUILanguage()); - const char *user_locale_lang = langid_to_string(LANGIDFROMLCID(GetThreadLocale())); - - EnumUILanguagesA(enum_ui_lang_proc, 0, 0); - - /* If one of the alternative languages in a multi-language installer - * is the system default UI language, deselect those languages that - * aren't among the UI languages available on the system. - * (On most Windows installations, just one UI language is present, - * which obviously is the same as the default UI language. But - * we want to be generic.) - * If none of the languages in a multi-language installer is the - * system default UI language (this happens now in 2.4.0 where we - * cannot put as many UI languages into the installer as we would - * like, but only half a dozen: en-US,de,es,fr,it,pt-BR), pretend - * that English is the system default UI language, - * so that we will by default deselect everything except - * English. We don't want to by default install all half dozen - * languages for an unsuspecting user of a Finnish Windows, for - * instance. Sigh. - */ - bool have_system_default_lang = false; - if (system_default_lang[0]) { - for (i = 0; i < nlangs; i++) { - if (memcmp (system_default_lang, langs[i], 2) == 0) { - have_system_default_lang = true; - break; - } - } - } - if (!have_system_default_lang) { - system_default_lang = "en"; - } - - for (i = 0; i < nlangs; i++) { - if (memcmp(system_default_lang, langs[i], 2) != 0 && - memcmp(user_locale_lang, langs[i], 2) != 0 && - !present_in_ui_langs(langs[i])) { - UINT rc; - sprintf(feature, "gm_Langpack_r_%s", langs[i]); - rc = MsiSetFeatureStateA(handle, feature, INSTALLSTATE_ABSENT); - } else { - addMatchingDictionaries(langs[i], dicts, ndicts); - } + if (!matches) { + for (int i = 0; i < nlangs; i++) { + langs[i].install = true; } } } + for (int i = 0; i < nlangs; i++) { + if (langs[i].install) { + addMatchingDictionaries(langs[i].lang, dicts, ndicts); + } else { + sprintf(feature, "gm_Langpack_r_%s", langs[i].lang); + MsiSetFeatureStateA(handle, feature, INSTALLSTATE_ABSENT); + } + } + + // Select just those dictionaries that match any of the selected langpacks: for (int i = 0; i != ndicts; ++i) { if (!dicts[i].install) { sprintf(feature, "gm_r_ex_Dictionary_%s", dicts[i].lang);