[setup - the official Cygwin setup program] branch master, updated. release_2.911

Jon TURNEY jturney@sourceware.org
Sun Dec 19 14:06:44 GMT 2021




https://sourceware.org/git/gitweb.cgi?p=cygwin-apps/setup.git;h=b63da9d41520afe3cf380630ed41056ed4416adc

commit b63da9d41520afe3cf380630ed41056ed4416adc
Author: Jon Turney <jon.turney@dronecode.org.uk>
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 <jon.turney@dronecode.org.uk>
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 <jon.turney@dronecode.org.uk>
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 <jon.turney@dronecode.org.uk>
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 <jon.turney@dronecode.org.uk>
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 <jon.turney@dronecode.org.uk>
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 <jon.turney@dronecode.org.uk>
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 <jon.turney@dronecode.org.uk>
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 <jon.turney@dronecode.org.uk>
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 <jon.turney@dronecode.org.uk>
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 <jon.turney@dronecode.org.uk>
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<std::string> erase;
+      std::vector<std::wstring> 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<std::string>::const_iterator i = erase.begin ();
+      for (std::vector<std::wstring>::const_iterator i = erase.begin ();
            i != erase.end(); i++)
         s += *i;
     }
 
   // then list things downloaded or installed
-  std::vector<std::string> install;
+  std::vector<std::wstring> 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<std::string>::const_iterator i = install.begin ();
+  for (std::vector<std::wstring>::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 ();



More information about the Cygwin-apps-cvs mailing list