https://sourceware.org/git/gitweb.cgi?p=cygwin-apps/setup.git;h=b63da9d41520afe3cf380630ed41056ed4416adc commit b63da9d41520afe3cf380630ed41056ed4416adc Author: Jon Turney Date: Sat Dec 4 14:25:09 2021 +0000 Push some dynamic dialog text into IDD_FILE_INUSE resource Can't use that approach for the label for the IDRETRY button (since it needs a fixed ID), so move that to string resources. Also make text placed in IDC_FILE_INUSE_MSG localizable. https://sourceware.org/git/gitweb.cgi?p=cygwin-apps/setup.git;h=dfd97f99febea198819697c7cb73e4e1c8140b05 commit dfd97f99febea198819697c7cb73e4e1c8140b05 Author: Jon Turney Date: Sat Dec 4 14:04:39 2021 +0000 Move download progress message to string resources https://sourceware.org/git/gitweb.cgi?p=cygwin-apps/setup.git;h=6bcfadf121e02d64503b168b899c9e6e0bba4d5c commit 6bcfadf121e02d64503b168b899c9e6e0bba4d5c Author: Jon Turney Date: Fri Dec 3 23:17:09 2021 +0000 Move confirm report strings to string resources https://sourceware.org/git/gitweb.cgi?p=cygwin-apps/setup.git;h=c2f99cb1bcc85613df3b7183a8400030ae78c5f3 commit c2f99cb1bcc85613df3b7183a8400030ae78c5f3 Author: Jon Turney Date: Fri Dec 3 22:06:50 2021 +0000 Move hash checking progress message to string resources https://sourceware.org/git/gitweb.cgi?p=cygwin-apps/setup.git;h=c156d59f49b79a72a3be15714e5245faf2656c3b commit c156d59f49b79a72a3be15714e5245faf2656c3b Author: Jon Turney Date: Fri Dec 3 21:25:31 2021 +0000 Use string resource for progress windows title https://sourceware.org/git/gitweb.cgi?p=cygwin-apps/setup.git;h=7409282c51cb071f4b4ed1dcfccc62dab3ec773c commit 7409282c51cb071f4b4ed1dcfccc62dab3ec773c Author: Jon Turney Date: Fri Dec 3 20:25:15 2021 +0000 Move local package directory browser title to string resources Also improve LoadStringW to handle a missing translation by falling back to untranslated string. https://sourceware.org/git/gitweb.cgi?p=cygwin-apps/setup.git;h=195864cef702b8c32da987ae934682343b27c4d9 commit 195864cef702b8c32da987ae934682343b27c4d9 Author: Jon Turney Date: Fri Dec 3 20:07:13 2021 +0000 Move root directory browser title to string resources Note: IFileDialog now recommended over SHBrowseForFolder. There's something a little wonky here: The browser is shown by OnMessageCmd(), so a simple click on the unfocused button isn't enough? https://sourceware.org/git/gitweb.cgi?p=cygwin-apps/setup.git;h=7f85e28044a2de00021f00672d1c13bd34615d65 commit 7f85e28044a2de00021f00672d1c13bd34615d65 Author: Jon Turney Date: Fri Dec 3 18:26:53 2021 +0000 Move localizable 'empty chooser' text to string resources https://sourceware.org/git/gitweb.cgi?p=cygwin-apps/setup.git;h=b08f9c71f6df2d643d67608c5eba3454b26d5a5d commit b08f9c71f6df2d643d67608c5eba3454b26d5a5d Author: Jon Turney Date: Fri Dec 3 18:07:51 2021 +0000 Don't localize logged 'exit message' set via setExitMsg() https://sourceware.org/git/gitweb.cgi?p=cygwin-apps/setup.git;h=477a6ff52ec52e558188033d9f3128ac6ef7ef27 commit 477a6ff52ec52e558188033d9f3128ac6ef7ef27 Author: Jon Turney Date: Thu Sep 10 17:31:56 2020 +0100 Don't localize mbox strings written to log Add LoadStringWEx to access string resource for a specifc locale. Use that in mbox when formatting string for log. https://sourceware.org/git/gitweb.cgi?p=cygwin-apps/setup.git;h=15befbf1b0047258896c243a22d3395cd0146a9d commit 15befbf1b0047258896c243a22d3395cd0146a9d Author: Jon Turney Date: Thu Dec 2 22:28:32 2021 +0000 Push some dynamic download/install dialog text into IDD_LOCAL_DIR DIALOG resource Move the localizable dialog text which is dynamically modified depending on install or download mode into the IDD_LOCAL_DIR DIALOG resource, and show or hide it as appropriate. Diff: --- ListView.cc | 10 +++------- ListView.h | 4 ++-- LogFile.cc | 13 +++++-------- String++.cc | 10 ++++++++++ String++.h | 1 + choose.cc | 7 ++++--- confirm.cc | 56 ++++++++++++++++++++++++++++++++----------------------- desktop.cc | 10 +++------- dialog.cc | 6 ++++++ dialog.h | 1 + geturl.cc | 7 +++++-- install.cc | 29 ++++++++++++++-------------- localdir.cc | 29 ++++++++++++++++------------ msg.cc | 12 ++++++++++-- package_source.cc | 8 ++++++-- res.rc | 41 ++++++++++++++++++++++++++++++++-------- res/fr/res.rc | 45 ++++++++++++++++++++++++++++++++++---------- resource.h | 25 +++++++++++++++++++++---- root.cc | 18 +++++++++++------- threebar.cc | 16 ++++++++++++---- threebar.h | 3 ++- win32.cc | 35 +++++++++++++++++++++++++++++++++- win32.h | 2 ++ window.cc | 4 ++-- window.h | 2 +- 25 files changed, 274 insertions(+), 120 deletions(-) diff --git a/ListView.cc b/ListView.cc index dc420e2c..62a37ab1 100644 --- a/ListView.cc +++ b/ListView.cc @@ -345,11 +345,7 @@ ListView::OnNotify (NMHDR *pNmHdr, LRESULT *pResult) case LVN_GETEMPTYMARKUP: { NMLVEMPTYMARKUP *pNmMarkup = (NMLVEMPTYMARKUP*) pNmHdr; - - MultiByteToWideChar(CP_UTF8, 0, - empty_list_text, -1, - pNmMarkup->szMarkup, L_MAX_URL_LENGTH); - + wcsncpy(pNmMarkup->szMarkup, empty_list_text.c_str(), L_MAX_URL_LENGTH); *pResult = true; return true; } @@ -645,9 +641,9 @@ ListView::empty(void) } void -ListView::setEmptyText(const char *text) +ListView::setEmptyText(unsigned int text) { - empty_list_text = text; + empty_list_text = LoadStringW(text); } int diff --git a/ListView.h b/ListView.h index 8c43fcc7..95dd9ee6 100644 --- a/ListView.h +++ b/ListView.h @@ -73,7 +73,7 @@ class ListView void resizeColumns(void); void setContents(ListViewContents *contents, bool tree = false); - void setEmptyText(const char *text); + void setEmptyText(unsigned int text); bool OnNotify (NMHDR *pNmHdr, LRESULT *pResult); @@ -87,7 +87,7 @@ class ListView ListViewContents *contents; HeaderList headers; - const char *empty_list_text; + std::wstring empty_list_text; int iRow_track; int iCol_track; diff --git a/LogFile.cc b/LogFile.cc index 0bcf6073..0a83159f 100644 --- a/LogFile.cc +++ b/LogFile.cc @@ -125,17 +125,14 @@ LogFile::exit (int exit_code, bool show_end_install_msg) if (been_here) ::exit (exit_code); been_here = 1; - + if (exit_msg) { - char buf[1000], fmt[1000]; - if (LoadString (hinstance, exit_msg, fmt, sizeof (fmt)) > 0) - { - snprintf (buf, 1000, fmt, backslash(getFileName(LOG_BABBLE)).c_str()); - Log (LOG_PLAIN) << "note: " << buf << endLog; - } + std::wstring fmt = LoadStringWEx(exit_msg, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)); + std::wstring buf = format(fmt, backslash(getFileName(LOG_BABBLE)).c_str()); + Log (LOG_PLAIN) << "note: " << wstring_to_string(buf) << endLog; } - + /* ... in that it skips the boring log messages. Exit code -1 is used when just printing the help output and when we're self-elevating. */ if (show_end_install_msg) diff --git a/String++.cc b/String++.cc index de2b48f9..a5649759 100644 --- a/String++.cc +++ b/String++.cc @@ -152,3 +152,13 @@ vformat(const std::wstring &fmt, va_list ap) return str; } + +std::wstring +format(const std::wstring &fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + std::wstring res = vformat(fmt, ap); + va_end(ap); + return res; +} diff --git a/String++.h b/String++.h index 0851f4e8..af32611c 100644 --- a/String++.h +++ b/String++.h @@ -47,5 +47,6 @@ std::string wstring_to_string(const std::wstring &w); // produce a std::string using formatting like sprintf std::wstring vformat(const std::wstring &fmt, va_list ap); +std::wstring format(const std::wstring &fmt, ...); #endif /* SETUP_STRING___H */ diff --git a/choose.cc b/choose.cc index cc3fa07c..1b18bbd0 100644 --- a/choose.cc +++ b/choose.cc @@ -335,11 +335,12 @@ ChooserPage::OnActivate() packagedb::categoriesType::iterator it = db.categories.find("All"); if (it == db.categories.end ()) - listview->setEmptyText("No packages found."); + listview->setEmptyText(IDS_CHOOSER_EMPTY_NO_PACKAGES); + if (source == IDC_SOURCE_DOWNLOAD) - listview->setEmptyText("Nothing to download."); + listview->setEmptyText(IDS_CHOOSER_EMPTY_DOWNLOAD); else - listview->setEmptyText("Nothing to install or update."); + listview->setEmptyText(IDS_CHOOSER_EMPTY_INSTALL); chooser->build_category_tree(); chooser->init_headers(); diff --git a/confirm.cc b/confirm.cc index d0a84206..55ab1c13 100644 --- a/confirm.cc +++ b/confirm.cc @@ -55,7 +55,7 @@ void ConfirmPage::OnActivate() { // generate a report on actions we're going to take - std::string s = ""; + std::wstring s = L""; packagedb db; const SolverTransactionList & trans = db.solution.transactions (); @@ -63,34 +63,36 @@ ConfirmPage::OnActivate() // first list things we will erase if (source != IDC_SOURCE_DOWNLOAD) { - std::vector erase; + std::vector erase; for (SolverTransactionList::const_iterator i = trans.begin (); i != trans.end (); i++) { if (i->type == SolverTransaction::transErase) { - std::string line; packageversion pv = i->version; packagemeta *pkg = db.findBinary (PackageSpecification (pv.Name ())); - line += "Uninstall "; - line += i->version.Name(); - line += " "; - line += i->version.Canonical_version(); + std::wstring action = LoadStringW(IDS_CONFIRM_UNINSTALL); + std::wstring line = format(L"%ls %s %s", action.c_str(), + i->version.Name().c_str(), + i->version.Canonical_version().c_str()); if (pkg && pkg->desired) - line += " (automatically added)"; - line += "\r\n"; + { + line += L" "; + line += LoadStringW(IDS_CONFIRM_AUTO_ADD); + } + line += L"\r\n"; erase.push_back (line); } } sort (erase.begin(), erase.end()); - for (std::vector::const_iterator i = erase.begin (); + for (std::vector::const_iterator i = erase.begin (); i != erase.end(); i++) s += *i; } // then list things downloaded or installed - std::vector install; + std::vector install; for (SolverTransactionList::const_iterator i = trans.begin (); i != trans.end (); i++) { @@ -99,32 +101,40 @@ ConfirmPage::OnActivate() if (i->type == SolverTransaction::transInstall) { - std::string line; + std::wstring action; if (source != IDC_SOURCE_DOWNLOAD) - line += "Install "; + action = LoadStringW(IDS_CONFIRM_INSTALL); else - line += "Download "; - line += i->version.Name(); - line += " "; - line += i->version.Canonical_version(); + action = LoadStringW(IDS_CONFIRM_DOWNLOAD); + + std::wstring line = format(L"%ls %s %s", action.c_str(), + i->version.Name().c_str(), + i->version.Canonical_version().c_str()); + if (i->version.Type() == package_source) - line += " (source)"; + { + line += L" "; + line += LoadStringW(IDS_CONFIRM_SOURCE); + } else if (pkg && pkg->desired != pv) - line += " (automatically added)"; - line += "\r\n"; + { + line += L" "; + line += LoadStringW(IDS_CONFIRM_AUTO_ADD); + } + line += L"\r\n"; install.push_back (line); } } sort (install.begin(), install.end()); - for (std::vector::const_iterator i = install.begin (); + for (std::vector::const_iterator i = install.begin (); i != install.end(); i++) s += *i; // be explicit about doing nothing if (s.empty()) - s += "No changes"; + s += LoadStringW(IDS_CONFIRM_NOTHING); - SetDlgItemText (GetHWND (), IDC_CONFIRM_EDIT, s.c_str ()); + SetDlgItemTextW (GetHWND (), IDC_CONFIRM_EDIT, s.c_str ()); // move focus to 'next' button, so enter doesn't get eaten by edit control HWND nextButton = ::GetDlgItem(::GetParent(GetHWND()), 0x3024 /* ID_WIZNEXT */); diff --git a/desktop.cc b/desktop.cc index 4f692b8a..aa1f9019 100644 --- a/desktop.cc +++ b/desktop.cc @@ -236,13 +236,9 @@ check_if_enable_next (HWND h) static void set_status (HWND h) { - char buf[1000], fmt[1000]; - if (LoadString (hinstance, Logger ().getExitMsg (), fmt, sizeof (fmt)) > 0) - { - snprintf (buf, 1000, fmt, - backslash (Logger ().getFileName (LOG_BABBLE)).c_str ()); - eset (h, IDC_STATUS, buf); - } + std::wstring fmt = LoadStringW(Logger ().getExitMsg ()); + std::wstring buf = format(fmt, backslash (Logger ().getFileName (LOG_BABBLE)).c_str ()); + eset (h, IDC_STATUS, buf); } static void diff --git a/dialog.cc b/dialog.cc index dd12fc44..2ca57df8 100644 --- a/dialog.cc +++ b/dialog.cc @@ -71,6 +71,12 @@ eset (HWND h, int id, const std::string aString) SetDlgItemText (h, id, aString.c_str()); } +void +eset (HWND h, int id, const std::wstring &aString) +{ + SetDlgItemTextW (h, id, aString.c_str()); +} + void eset (HWND h, int id, int val) { diff --git a/dialog.h b/dialog.h index 47212e3e..63c98ee6 100644 --- a/dialog.h +++ b/dialog.h @@ -59,6 +59,7 @@ int eget (HWND h, int id); void eset (HWND h, int id, const char *var); void eset (HWND h, int id, const std::string); +void eset (HWND h, int id, const std::wstring &); void eset (HWND h, int id, int var); /* RadioButtons. ids is a null-terminated list of IDs. Get diff --git a/geturl.cc b/geturl.cc index 321259e8..e82cb16b 100644 --- a/geturl.cc +++ b/geturl.cc @@ -63,8 +63,11 @@ init_dialog (const std::string &url, int length) std::string::size_type divide = url.find_last_of('/'); max_bytes = length; Progress.SetText1(IDS_PROGRESS_DOWNLOADING); - Progress.SetText2((url.substr(divide + 1) + " from " - + url.substr(0, divide)).c_str()); + std::wstring fmt = LoadStringW(IDS_PROGRESS_DOWNLOADING_FROM); + std::wstring s = format(fmt, + url.substr(divide + 1).c_str(), + url.substr(0, divide).c_str()); + Progress.SetText2(s.c_str()); Progress.SetText3(IDS_PROGRESS_CONNECTING); Progress.SetBar1(0); start_tics = GetTickCount (); diff --git a/install.cc b/install.cc index 9bb08203..beb15c74 100644 --- a/install.cc +++ b/install.cc @@ -268,7 +268,7 @@ Installer::replaceOnRebootSucceeded (const std::string& fn, bool &rebootneeded) typedef struct { - const char *msg; + const wchar_t *msg; const char *processlist; int iteration; } FileInuseDlgData; @@ -282,29 +282,30 @@ FileInuseDlgProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { FileInuseDlgData *dlg_data = (FileInuseDlgData *)lParam; - SetDlgItemText (hwndDlg, IDC_FILE_INUSE_MSG, dlg_data->msg); + SetDlgItemTextW (hwndDlg, IDC_FILE_INUSE_MSG, dlg_data->msg); SetDlgItemText (hwndDlg, IDC_FILE_INUSE_EDIT, dlg_data->processlist); switch (dlg_data->iteration) { case 0: - break; // show the dialog the way it is in the resource + ShowWindow (GetDlgItem(hwndDlg, IDC_FILE_INUSE_HELP_0), SW_SHOW); + ShowWindow (GetDlgItem(hwndDlg, IDC_FILE_INUSE_HELP_1), SW_HIDE); + ShowWindow (GetDlgItem(hwndDlg, IDC_FILE_INUSE_HELP_2), SW_HIDE); + break; case 1: - SetDlgItemText (hwndDlg, IDRETRY, "&Kill Processes"); - SetDlgItemText (hwndDlg, IDC_FILE_INUSE_HELP, - "Select 'Retry' to retry, " - "Select 'Kill' to kill processes and retry, or " - "select 'Continue' to go on anyway (the file will be updated after a reboot)."); + ShowWindow (GetDlgItem(hwndDlg, IDC_FILE_INUSE_HELP_0), SW_HIDE); + ShowWindow (GetDlgItem(hwndDlg, IDC_FILE_INUSE_HELP_1), SW_SHOW); + ShowWindow (GetDlgItem(hwndDlg, IDC_FILE_INUSE_HELP_2), SW_HIDE); + SetDlgItemTextW (hwndDlg, IDRETRY, LoadStringW(IDS_FILE_INUSE_KILL).c_str()); break; default: case 2: - SetDlgItemText (hwndDlg, IDRETRY, "&Kill Processes"); - SetDlgItemText (hwndDlg, IDC_FILE_INUSE_HELP, - "Select 'Retry' to retry, " - "select 'Kill' to forcibly kill all processes and retry, or " - "select 'Continue' to go on anyway (the file will be updated after a reboot)."); + ShowWindow (GetDlgItem(hwndDlg, IDC_FILE_INUSE_HELP_0), SW_HIDE); + ShowWindow (GetDlgItem(hwndDlg, IDC_FILE_INUSE_HELP_1), SW_HIDE); + ShowWindow (GetDlgItem(hwndDlg, IDC_FILE_INUSE_HELP_2), SW_SHOW); + SetDlgItemTextW (hwndDlg, IDRETRY, LoadStringW(IDS_FILE_INUSE_KILL).c_str()); } } return TRUE; // automatically set focus, please @@ -608,7 +609,7 @@ Installer::_installOne (packagemeta &pkgm, // listed processes, or just ignore the problem and schedule the file to be // replaced after a reboot FileInuseDlgData dlg_data; - std::string msg = "Unable to extract /" + fn; + std::wstring msg = LoadStringW(IDS_FILE_INUSE_MSG) + L" /" + string_to_wstring(fn); dlg_data.msg = msg.c_str (); dlg_data.processlist = plm.c_str (); dlg_data.iteration = iteration; diff --git a/localdir.cc b/localdir.cc index 7a01e117..7130a17c 100644 --- a/localdir.cc +++ b/localdir.cc @@ -94,16 +94,16 @@ check_if_enable_next (HWND h) static void load_dialog (HWND h) { - char descText[1000]; if (source != IDC_SOURCE_LOCALDIR) { - LoadString (hinstance, IDS_LOCAL_DIR_DOWNLOAD, descText, sizeof (descText)); + ShowWindow (GetDlgItem(h, IDC_LOCAL_DIR_DOWNLOAD_DESC), SW_SHOW); + ShowWindow (GetDlgItem(h, IDC_LOCAL_DIR_INSTALL_DESC), SW_HIDE); } else { - LoadString (hinstance, IDS_LOCAL_DIR_INSTALL, descText, sizeof (descText)); + ShowWindow (GetDlgItem(h, IDC_LOCAL_DIR_DOWNLOAD_DESC), SW_HIDE); + ShowWindow (GetDlgItem(h, IDC_LOCAL_DIR_INSTALL_DESC), SW_SHOW); } - eset (h, IDC_LOCAL_DIR_DESC, descText); eset (h, IDC_LOCAL_DIR, local_dir); check_if_enable_next (h); } @@ -176,22 +176,27 @@ browse_cb (HWND h, UINT msg, LPARAM lp, LPARAM data) static void browse (HWND h) { - BROWSEINFO bi; - /* SHGetPathFromIDList doesn't handle path length > MAX_PATH. */ - CHAR name[MAX_PATH]; - LPITEMIDLIST pidl; + std::wstring title = LoadStringW((source != IDC_SOURCE_LOCALDIR) ? + IDS_LOCALDIR_BROWSE_DOWNLOAD_TITLE : + IDS_LOCALDIR_BROWSE_PACKAGE_TITLE); + + wchar_t wname[MAX_PATH]; + BROWSEINFOW bi; memset (&bi, 0, sizeof (bi)); bi.hwndOwner = h; - bi.pszDisplayName = name; - bi.lpszTitle = (source != IDC_SOURCE_LOCALDIR) ? "Select download directory" - : "Select local package directory"; + bi.pszDisplayName = wname; + bi.lpszTitle = title.c_str(); bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE | ((source != IDC_SOURCE_LOCALDIR) ? (BIF_EDITBOX | BIF_VALIDATE) : 0); bi.lpfn = browse_cb; - pidl = SHBrowseForFolder (&bi); + + /* SHGetPathFromIDList doesn't handle path length > MAX_PATH. */ + LPITEMIDLIST pidl; + pidl = SHBrowseForFolderW (&bi); if (pidl) { + CHAR name[MAX_PATH]; if (SHGetPathFromIDList (pidl, name)) eset (h, IDC_LOCAL_DIR, name); } diff --git a/msg.cc b/msg.cc index 5badcc3c..00eaf5aa 100644 --- a/msg.cc +++ b/msg.cc @@ -129,7 +129,7 @@ LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam) { int mbox(HWND owner, unsigned int format_id, int mb_type, ...) { - std::wstring fmt = LoadStringW(format_id); + std::wstring fmt = LoadStringWEx(format_id, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)); if (fmt.empty()) fmt = L"Internal error: format string resource not found"; @@ -138,12 +138,20 @@ mbox(HWND owner, unsigned int format_id, int mb_type, ...) std::wstring buf = vformat(fmt, args); va_end(args); - // write to log as UTF8 + // write unlocalized to log as UTF8 Log (LOG_PLAIN) << "mbox " << ": " << wstring_to_string(buf) << endLog; if (unattended_mode) return unattended_result(mb_type); + fmt = LoadStringW(format_id); + if (fmt.empty()) + fmt = L"Internal error: format string resource not found"; + + va_start(args, mb_type); + buf = vformat(fmt, args); + va_end(args); + bool retry_continue = (mb_type & MB_TYPEMASK) == MB_RETRYCONTINUE; if (retry_continue) { mb_type &= ~MB_TYPEMASK; diff --git a/package_source.cc b/package_source.cc index 9ae08cb7..2b5909bf 100644 --- a/package_source.cc +++ b/package_source.cc @@ -113,7 +113,9 @@ packagesource::check_sha512 (const std::string fullname) const Log (LOG_BABBLE) << "Checking SHA512 for " << fullname << endLog; - Progress.SetText1 (("Checking SHA512 for " + shortname).c_str ()); + std::wstring fmt = LoadStringW(IDS_PROGRESS_CHECKING_HASH); + std::wstring s = format(fmt, "SHA512", shortname.c_str()); + Progress.SetText1 (s.c_str()); Progress.SetText4 (IDS_PROGRESS_PROGRESS); Progress.SetBar1 (0); @@ -162,7 +164,9 @@ packagesource::check_md5 (const std::string fullname) const Log (LOG_BABBLE) << "Checking MD5 for " << fullname << endLog; - Progress.SetText1 (("Checking MD5 for " + shortname).c_str ()); + std::wstring fmt = LoadStringW(IDS_PROGRESS_CHECKING_HASH); + std::wstring s = format(fmt, "MD5", shortname); + Progress.SetText1 (s.c_str()); Progress.SetText4 (IDS_PROGRESS_PROGRESS); Progress.SetBar1 (0); diff --git a/res.rc b/res.rc index febf357a..83d83393 100644 --- a/res.rc +++ b/res.rc @@ -90,7 +90,13 @@ FONT 8, "MS Shell Dlg" BEGIN LTEXT "Select Local Package Directory",IDC_STATIC_HEADER_TITLE, 7,0,258,8,NOT WS_GROUP - LTEXT "",IDC_LOCAL_DIR_DESC,21,9,248,16,NOT WS_GROUP + LTEXT "Select a directory where you want Setup to store " + "the installation files it downloads. The directory will be " + "created if it does not already exist.", + IDC_LOCAL_DIR_DOWNLOAD_DESC,21,9,248,16,NOT WS_GROUP + LTEXT "Select a directory where Setup should look for " + "downloaded installation files.", + IDC_LOCAL_DIR_INSTALL_DESC,21,9,248,16,NOT WS_GROUP ICON IDI_CYGWIN,IDC_HEADICON,SETUP_HEADICON_X,0,21,20 CONTROL "",IDC_HEADSEPARATOR,"Static",SS_BLACKFRAME | SS_SUNKEN,0,28, SETUP_STANDARD_DIALOG_W,1 @@ -493,7 +499,7 @@ CAPTION "In-use file detected" FONT 8, "MS Shell Dlg" BEGIN ICON IDI_WARNING,IDC_HEADICON,10,10 - LTEXT "Unable to extract %s", + LTEXT "Unable to extract", IDC_FILE_INUSE_MSG,33,10,234,8,SS_PATHELLIPSIS LTEXT "The file is in use by the following processes:", IDC_STATIC,33,28,234,8 @@ -503,7 +509,15 @@ BEGIN LTEXT "Select 'Retry' to retry, " "select 'Stop' to stop processes and retry, or " "select 'Continue' to go on anyway (the file will be updated after a reboot).", - IDC_FILE_INUSE_HELP,33,80,234,24,NOT WS_GROUP + IDC_FILE_INUSE_HELP_0,33,80,234,24,NOT WS_GROUP + LTEXT "Select 'Retry' to retry, " + "select 'Kill' to kill processes and retry, or " + "select 'Continue' to go on anyway (the file will be updated after a reboot).", + IDC_FILE_INUSE_HELP_1,33,80,234,24,NOT WS_GROUP + LTEXT "Select 'Retry' to retry, " + "select 'Kill' to forcibly kill all processes and retry, or " + "select 'Continue' to go on anyway (the file will be updated after a reboot).", + IDC_FILE_INUSE_HELP_2,33,80,234,24,NOT WS_GROUP PUSHBUTTON "&Retry",IDIGNORE,45,112,55,15 DEFPUSHBUTTON "&Stop Processes",IDRETRY,111,112,55,15 PUSHBUTTON "&Continue",IDCONTINUE,177,112,55,15 @@ -603,11 +617,6 @@ BEGIN IDS_SIG_INVALID "Mirror Error: Setup.ini signature %s from %s failed to verify.\nPossible corrupt mirror? Setup.ini rejected." IDS_CRYPTO_ERROR "Internal Error: gcrypt library error %d %s" IDS_SEARCH_TOOLTIP "Search for this string in package names." - IDS_LOCAL_DIR_DOWNLOAD "Select a directory where you want Setup to store " - "the installation files it downloads. The directory will be " - "created if it does not already exist." - IDS_LOCAL_DIR_INSTALL "Select a directory where Setup should look for " - "downloaded installation files." IDS_MAYBE_MKDIR "Directory %s does not exist, would you like me to create it?" IDS_CANT_MKDIR "Couldn't create directory %s, sorry. (Is drive full or read-only?)" IDS_NO_LOCALDIR "Local package directory %s not found.\nYou can still remove installed\npackages, but there " @@ -688,6 +697,22 @@ BEGIN "Make sure your network settings are correct and try again." IDS_CONFIRM_EXIT "Are you sure you want to exit setup? Any current download or installation will be aborted." IDS_CONTINUE "Continue" + IDS_CHOOSER_EMPTY_NO_PACKAGES "No packages found." + IDS_CHOOSER_EMPTY_DOWNLOAD "Nothing to download." + IDS_CHOOSER_EMPTY_INSTALL "Nothing to install or update." + IDS_ROOT_BROWSE_TITLE "Select an installation root directory" + IDS_LOCALDIR_BROWSE_DOWNLOAD_TITLE "Select download directory" + IDS_LOCALDIR_BROWSE_PACKAGE_TITLE "Select local package directory" + IDS_PROGRESS_CHECKING_HASH "Checking %s for %s" + IDS_PROGRESS_DOWNLOADING_FROM "%s from %s" + IDS_CONFIRM_UNINSTALL "Uninstall" + IDS_CONFIRM_INSTALL "Install" + IDS_CONFIRM_DOWNLOAD "Download" + IDS_CONFIRM_NOTHING "No changes" + IDS_CONFIRM_AUTO_ADD "(automatically added)" + IDS_CONFIRM_SOURCE "(source)" + IDS_FILE_INUSE_KILL "&Kill Processes" + IDS_FILE_INUSE_MSG "Unable to extract" END ///////////////////////////////////////////////////////////////////////////// diff --git a/res/fr/res.rc b/res/fr/res.rc index 0b365e2f..0b4fad15 100644 --- a/res/fr/res.rc +++ b/res/fr/res.rc @@ -64,7 +64,12 @@ FONT 8, "MS Shell Dlg" BEGIN LTEXT "Sélection du dossier local des paquets",IDC_STATIC_HEADER_TITLE, 7,0,258,8,NOT WS_GROUP - LTEXT "",IDC_LOCAL_DIR_DESC,21,9,248,16,NOT WS_GROUP + LTEXT "Choisir un dossier pour enregistrer les fichiers " + "téléchargés. Ce dossier sera créé s'il n'existe pas.", + IDC_LOCAL_DIR_DOWNLOAD_DESC,21,9,248,16,NOT WS_GROUP + LTEXT "Choisir un dossier où l'assistant ira chercher les " + "fichiers téléchargés.", + IDC_LOCAL_DIR_INSTALL_DESC,21,9,248,16,NOT WS_GROUP ICON IDI_CYGWIN,IDC_HEADICON,SETUP_HEADICON_X,0,21,20 CONTROL "",IDC_HEADSEPARATOR,"Static",SS_BLACKFRAME | SS_SUNKEN,0,28, SETUP_STANDARD_DIALOG_W,1 @@ -438,17 +443,25 @@ CAPTION "Détection d'un fichier en cours d'utilisation" FONT 8, "MS Shell Dlg" BEGIN ICON IDI_WARNING,IDC_HEADICON,10,10 - LTEXT "Impossible d'extraire %s", + LTEXT "Impossible d'extraire", IDC_FILE_INUSE_MSG,33,10,234,8,SS_PATHELLIPSIS LTEXT "Ce fichier est en cours d'utilisation par : ", IDC_STATIC,33,28,234,8 EDITTEXT IDC_FILE_INUSE_EDIT,33,40,234,32,WS_VSCROLL | ES_LEFT | ES_MULTILINE | ES_READONLY | ES_AUTOVSCROLL | NOT WS_TABSTOP - LTEXT "Choisir 'Recommencer' pour recommencer, " - "Choisir 'Stop' pour arrêter les process et recommencer, ou " - "Choisir 'Continuer' pour procéder (un reboot sera nécessaire).", - IDC_FILE_INUSE_HELP,33,80,234,24,NOT WS_GROUP + LTEXT "Choisir «Recommencer» pour recommencer, " + "choisir «Stop» pour arrêter les process et recommencer, ou " + "choisir «Continuer» pour procéder (un reboot sera nécessaire).", + IDC_FILE_INUSE_HELP_0,33,80,234,24,NOT WS_GROUP + LTEXT "Choisir «Recommencer» pour ré-essayer, " + "choisir «Tuer» pour tuer les processus et ré-essayer, ou " + "choisir «Continuer» pour poursuivre (le fichier sera mis à jour après un redémarrage).", + IDC_FILE_INUSE_HELP_1,33,80,234,24,NOT WS_GROUP + LTEXT "Choisir «Recommencer» pour ré-essayer, " + "choisir «Tuer» pour forcer la fin des processus et ré-essayer, ou " + "choisir «Continuer» pour poursuivre (le fichier sera mis à jour après un redémarrage).", + IDC_FILE_INUSE_HELP_2,33,80,234,24,NOT WS_GROUP PUSHBUTTON "&Recommencer",IDIGNORE,45,112,55,15 DEFPUSHBUTTON "&Stop",IDRETRY,111,112,55,15 PUSHBUTTON "&Continuer",IDCONTINUE,177,112,55,15 @@ -518,10 +531,6 @@ BEGIN IDS_SIG_INVALID "Erreur pour le miroir : la signature de Setup.ini %s de %s est impossible à vérifier.\nLe miroir est peut-être corrompu ? Setup.ini rejeté." IDS_CRYPTO_ERROR "Erreur interne : erreur %d %s de la librairie gcrypt" IDS_SEARCH_TOOLTIP "Chercher cette valeur dans les noms des paquets." - IDS_LOCAL_DIR_DOWNLOAD "Choisir un dossier pour enregistrer les fichiers " - "téléchargés. Ce dossier sera créé s'il n'existe pas." - IDS_LOCAL_DIR_INSTALL "Choisir un dossier où l'assistant ira chercher les " - "fichiers téléchargés." IDS_MAYBE_MKDIR "Dossier %s absent, voulez-vous le créer ?" IDS_CANT_MKDIR "Impossible de créer le dossier %s, désolé. (Disque plein ou uniquement en lecture ?)" IDS_NO_LOCALDIR "Dossier local des paquets %s absent.\nVoulez-vous efface les paquets, \n" @@ -602,4 +611,20 @@ BEGIN "Vérifiez que vos paramètres réseau sont corrects et réessayez." IDS_CONFIRM_EXIT "Voulez-vous vraiment quitter l'assistant ? Les téléchargements ou installations en cours seront annulés." IDS_CONTINUE "Continuer" + IDS_CHOOSER_EMPTY_NO_PACKAGES "Pas de paquet trouvé." + IDS_CHOOSER_EMPTY_DOWNLOAD "Rien à télécharger." + IDS_CHOOSER_EMPTY_INSTALL "Rien à installer ou mettre à jour." + IDS_ROOT_BROWSE_TITLE "Choisissez le dossier racine de l'installation" + // IDS_LOCALDIR_BROWSE_DOWNLOAD_TITLE "XXX: missing translation" + // IDS_LOCALDIR_BROWSE_PACKAGE_TITLE "XXX: missing translation" + IDS_PROGRESS_CHECKING_HASH "Vérification %s pour %s" + IDS_PROGRESS_DOWNLOADING_FROM "%s depuis %s" + IDS_CONFIRM_UNINSTALL "Désinstalle" + IDS_CONFIRM_INSTALL "Installe" + IDS_CONFIRM_DOWNLOAD "Télécharge" + IDS_CONFIRM_NOTHING "Pas de changement" + IDS_CONFIRM_AUTO_ADD "(ajouté automatiquement)" + IDS_CONFIRM_SOURCE "(source)" + IDS_FILE_INUSE_KILL "&Tuer les processus" + IDS_FILE_INUSE_MSG "Incapable d'extraire" END diff --git a/resource.h b/resource.h index 7b46a2ab..0a10f648 100644 --- a/resource.h +++ b/resource.h @@ -30,8 +30,6 @@ #define IDS_SIG_INVALID 131 #define IDS_CRYPTO_ERROR 132 #define IDS_SEARCH_TOOLTIP 133 -#define IDS_LOCAL_DIR_DOWNLOAD 134 -#define IDS_LOCAL_DIR_INSTALL 135 #define IDS_MAYBE_MKDIR 136 #define IDS_CANT_MKDIR 137 #define IDS_NO_LOCALDIR 138 @@ -89,6 +87,22 @@ #define IDS_CONFIRM_EXIT 190 #define IDS_EXTRACTION_INUSE 191 #define IDS_CONTINUE 192 +#define IDS_CHOOSER_EMPTY_NO_PACKAGES 193 +#define IDS_CHOOSER_EMPTY_DOWNLOAD 194 +#define IDS_CHOOSER_EMPTY_INSTALL 195 +#define IDS_ROOT_BROWSE_TITLE 196 +#define IDS_LOCALDIR_BROWSE_DOWNLOAD_TITLE 197 +#define IDS_LOCALDIR_BROWSE_PACKAGE_TITLE 198 +#define IDS_PROGRESS_CHECKING_HASH 199 +#define IDS_CONFIRM_UNINSTALL 1200 +#define IDS_CONFIRM_INSTALL 1201 +#define IDS_CONFIRM_DOWNLOAD 1202 +#define IDS_CONFIRM_NOTHING 1203 +#define IDS_CONFIRM_AUTO_ADD 1204 +#define IDS_CONFIRM_SOURCE 1205 +#define IDS_PROGRESS_DOWNLOADING_FROM 1206 +#define IDS_FILE_INUSE_KILL 1207 +#define IDS_FILE_INUSE_MSG 1208 // Dialogs @@ -211,11 +225,9 @@ #define IDC_CHOOSE_SEARCH_EDIT 585 #define IDC_CHOOSE_SEARCH_LABEL 586 #define IDC_CHOOSE_CLEAR_SEARCH 587 -#define IDC_LOCAL_DIR_DESC 588 #define IDC_POSTINSTALL_EDIT 589 #define IDC_FILE_INUSE_EDIT 590 #define IDC_FILE_INUSE_MSG 591 -#define IDC_FILE_INUSE_HELP 592 #define IDC_DOWNLOAD_EDIT 594 #define IDC_CHOOSE_DO_SEARCH 595 #define IDC_CHOOSE_SYNC 596 @@ -225,3 +237,8 @@ #define IDC_DESKTOP_HEADER_TITLE_DOWNLOAD 600 #define IDC_DESKTOP_HEADER_INSTALL 601 #define IDC_DESKTOP_HEADER_TITLE_INSTALL 602 +#define IDC_LOCAL_DIR_DOWNLOAD_DESC 603 +#define IDC_LOCAL_DIR_INSTALL_DESC 604 +#define IDC_FILE_INUSE_HELP_0 605 +#define IDC_FILE_INUSE_HELP_1 606 +#define IDC_FILE_INUSE_HELP_2 607 diff --git a/root.cc b/root.cc index 6fc25b9e..ddff3f0f 100644 --- a/root.cc +++ b/root.cc @@ -98,19 +98,23 @@ browse_cb (HWND h, UINT msg, LPARAM lp, LPARAM data) static void browse (HWND h) { - BROWSEINFO bi; - /* SHGetPathFromIDList doesn't handle path length > MAX_PATH. */ - CHAR name[MAX_PATH]; - LPITEMIDLIST pidl; + std::wstring title = LoadStringW(IDS_ROOT_BROWSE_TITLE); + + wchar_t wname[MAX_PATH]; + BROWSEINFOW bi; memset (&bi, 0, sizeof (bi)); bi.hwndOwner = h; - bi.pszDisplayName = name; - bi.lpszTitle = "Select an installation root directory"; + bi.pszDisplayName = wname; + bi.lpszTitle = title.c_str(); bi.ulFlags = BIF_RETURNONLYFSDIRS; bi.lpfn = browse_cb; - pidl = SHBrowseForFolder (&bi); + + /* SHGetPathFromIDList doesn't handle path length > MAX_PATH. */ + LPITEMIDLIST pidl; + pidl = SHBrowseForFolderW (&bi); if (pidl) { + CHAR name[MAX_PATH]; if (SHGetPathFromIDList (pidl, name)) eset (h, IDC_ROOT_DIR, name); } diff --git a/threebar.cc b/threebar.cc index 739ca524..ff4c5cb3 100644 --- a/threebar.cc +++ b/threebar.cc @@ -76,9 +76,15 @@ ThreeBarProgressPage::OnInit () } void -ThreeBarProgressPage::SetText1 (const TCHAR * t) +ThreeBarProgressPage::SetText1 (const wchar_t * t) { - ::SetWindowText (ins_action, t); + ::SetWindowTextW (ins_action, t); +} + +void +ThreeBarProgressPage::SetText2 (const wchar_t * t) +{ + ::SetWindowTextW (ins_pkgname, t); } void @@ -135,8 +141,10 @@ ThreeBarProgressPage::SetBar2 (long long progress, long long max) { int percent = (int) (100.0 * ((double) progress) / (double) max); SendMessage (ins_iprogress, PBM_SETPOS, (WPARAM) percent, 0); - std::string s = stringify(percent); - s += "% - Cygwin Setup"; + + // also update window title to show progress + std::wstring caption = LoadStringW(IDS_MBOX_CAPTION); + std::wstring s = format(L"%d%% - %ls", percent, caption.c_str()); GetOwner ()->SetWindowText (s.c_str()); } diff --git a/threebar.h b/threebar.h index 8f03f6bc..c361eed8 100644 --- a/threebar.h +++ b/threebar.h @@ -69,7 +69,8 @@ public: return -1; }; - void SetText1 (const TCHAR * t); + void SetText1 (const wchar_t * t); + void SetText2 (const wchar_t * t); void SetText2 (const TCHAR * t); void SetText3 (const TCHAR * t); void SetText4 (const TCHAR * t); diff --git a/win32.cc b/win32.cc index b6e7c947..35a28c6b 100644 --- a/win32.cc +++ b/win32.cc @@ -462,6 +462,38 @@ WowNativeMachine () #endif } +const std::wstring +LoadStringWEx(UINT uID, UINT langId) +{ + HINSTANCE hInstance = GetModuleHandle(NULL); + + // Convert the string ID into a bundle number + LPCSTR bundle = MAKEINTRESOURCE(uID / 16 + 1); + HRSRC hRes = ::FindResourceEx(hInstance, RT_STRING, bundle, langId); + if (hRes) + { + HGLOBAL h = ::LoadResource(hInstance, hRes); + if (h) + { + HGLOBAL hGlob = ::LockResource(h); + + // walk string bundle + wchar_t *buf = (wchar_t *)hGlob; + for (unsigned int i = 0; i < (uID & 15); i++) + { + buf += 1 + (UINT)*buf; + } + + int len = *buf; + return std::wstring(buf + 1, len); + } + } + // N.B.: Due to the way string bundles are encoded, there's no difference + // between an absent string resource whose bundle is present, and a string + // resource containing the null string. + return L""; +} + const std::wstring LoadStringW(unsigned int uID) { @@ -471,7 +503,8 @@ LoadStringW(unsigned int uID) if (len > 0) return std::wstring(buf, len); - return L""; + // if empty or absent, fallback to the untranslated string + return LoadStringWEx(uID, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)); } bool diff --git a/win32.h b/win32.h index 05f931c8..dcaa2511 100644 --- a/win32.h +++ b/win32.h @@ -195,6 +195,8 @@ SetDlgItemRect (HWND h, int item, LPRECT r) } const std::wstring LoadStringW(unsigned int uID); +const std::wstring LoadStringWEx(UINT uID, UINT langId); + bool is_developer_mode(void); #endif /* SETUP_WIN32_H */ diff --git a/window.cc b/window.cc index c4006d61..f13dafc4 100644 --- a/window.cc +++ b/window.cc @@ -347,9 +347,9 @@ Window::SetDlgItemFont (int id, const TCHAR * fontname, int Pointsize, } void -Window::SetWindowText (const std::string& s) +Window::SetWindowText (const std::wstring& s) { - ::SetWindowText (WindowHandle, s.c_str ()); + ::SetWindowTextW (WindowHandle, s.c_str ()); } RECT diff --git a/window.h b/window.h index d8b712b8..1dfb2a9f 100644 --- a/window.h +++ b/window.h @@ -156,7 +156,7 @@ public: bool MoveWindow(const RECTWrapper &r, bool Repaint = true); // Set the title of the window. - void SetWindowText (const std::string& s); + void SetWindowText (const std::wstring& s); RECT ScreenToClient(const RECT &r) const; void ActivateTooltips ();