This is the mail archive of the cygwin-apps mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Setup.exe: Nicer local package dir browser.


    Are we having fun yet?

  This patch makes the local package dir browsing experience nicer.  (It also
rolls up the previous patch about fixing the localdir option, sorry for being
lazy; just ignore that very first hunk for the moment.  I could have manually
chopped it out but then the line numbers would have been off-by-two and I
could have manually fixed the line numbers but basically I don't like
falsifying patches because nasty surprises can result!  Chopping off the top
hunk - or several - of a patch on its own, as I did to generate the other
patch, is as far as I'm comfortable with post-editing diffs.)

  To do this, it adds a couple of style flags that cause the common controls
directory browser dialog to adopt the newer styles available on all 2k and
later OSs, and a browser callback hook in support.  I believe on NT it will
just harmlessly fall back to the old-style dialog, but hope someone can check
for me.

  It also resolves the what-to-do-when-the-directory-doesn't-exist problem
slightly differently.  I didn't want to just automatically create the
directory, because I think one of the very common reasons for a directory that
someone has typed into a textbox not to exist is that they typed it wrong, so
I wanted to implement a dialog to offer them the choice of creating it or not.
 This dialog can also be conveniently reused from within the browser, where
there's also an editbox to type directory names.

	* localdir.cc (offer_to_create): New function.
	(browse_cb): Use it to optionally create a directory if the name
	entered in the textbox fails validation.
	(browse): Add new dialog style flags and validated editbox.
	(LocalDirPage::OnNext): Don't automatically create local package
	dir if it doesn't already exist; offer to instead.
	* resource.h (IDS_MAYBE_MKDIR): Define new string resource ID.
	* res.rc (IDS_MAYBE_MKDIR): Define new string resource text.


  Overall I think this is a much more friendly user experience.  OK for head?

    cheers,
      DaveK
Index: localdir.cc
===================================================================
RCS file: /cvs/cygwin-apps/setup/localdir.cc,v
retrieving revision 2.29
diff -p -u -r2.29 localdir.cc
--- localdir.cc	4 Nov 2009 15:14:51 -0000	2.29
+++ localdir.cc	4 Nov 2009 16:46:46 -0000
@@ -64,6 +64,8 @@ LocalDirSetting::LocalDirSetting ()
   const char *fg_ret;
   if ((fg_ret = UserSettings::instance().get ("last-cache")))
     local_dir = std::string (fg_ret);
+  else if (std::string (LocalDirOption).size ())
+    local_dir = std::string (LocalDirOption);
 }
 
 void
@@ -114,16 +116,57 @@ save_dialog (HWND h)
   local_dir = egetString (h, IDC_LOCAL_DIR);
 }
 
+// returns non-zero if refused or error, 0 if accepted and created ok.
+static int
+offer_to_create (HWND h, const char *dirname)
+{
+  if (!dirname || !*dirname)
+    return -1;
+
+  if (!unattended_mode)
+    {
+      char msgText[MAX_PATH + 100];
+      char fmtString[100];
+      DWORD ret;
+
+      LoadString (hinstance, IDS_MAYBE_MKDIR, fmtString, sizeof fmtString);
+      snprintf (msgText, sizeof msgText, fmtString, dirname);
+
+      ret = MessageBox (h, msgText, 0, MB_ICONSTOP | MB_YESNO);
+      if (ret == IDNO)
+	return -1;
+    }
+
+  return mkdir_p (true, dirname, 0755);
+}
 
 static int CALLBACK
 browse_cb (HWND h, UINT msg, LPARAM lp, LPARAM data)
 {
+  static CHAR dirname[MAX_PATH];
   switch (msg)
     {
     case BFFM_INITIALIZED:
       if (local_dir.size())
 	SendMessage (h, BFFM_SETSELECTION, TRUE, (LPARAM) local_dir.c_str());
       break;
+    case BFFM_SELCHANGED:
+      // Make a note of each new dir we successfully select, so that
+      // we know where to create the new directory if an invalid name
+      // is entered in the text box.
+      LPITEMIDLIST pidl = reinterpret_cast<LPITEMIDLIST>(lp);
+      SHGetPathFromIDList (pidl, dirname);
+      break;
+    case BFFM_VALIDATEFAILED:
+      // See if user wants to create a dir in the last successfully-selected.
+      CHAR tempname[MAX_PATH];
+      snprintf (tempname, sizeof tempname, "%s\\%s", dirname, reinterpret_cast<LPTSTR>(lp));
+      if (!offer_to_create (h, tempname))
+	{
+	  SendMessage (h, BFFM_SETSELECTION, TRUE, reinterpret_cast<LPARAM>(tempname));
+	  return -1;
+	}
+      return -1;
     }
   return 0;
 }
@@ -139,7 +182,7 @@ browse (HWND h)
   bi.pszDisplayName = name;
   bi.lpszTitle = (source != IDC_SOURCE_CWD) ? "Select download directory"
 					    : "Select local package directory";
-  bi.ulFlags = BIF_RETURNONLYFSDIRS;
+  bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE | BIF_EDITBOX | BIF_VALIDATE;
   bi.lpfn = browse_cb;
   pidl = SHBrowseForFolder (&bi);
   if (pidl)
@@ -197,10 +240,6 @@ LocalDirPage::OnNext ()
   while (trySetCurDir)
     {
       trySetCurDir = false;
-      /* If we just install from local directory, the directory must already
-         exist.  Otherwise, we just try to create it before we cd into it. */
-      if (source != IDC_SOURCE_CWD)
-	mkdir_p (1, local_dir.c_str (), 0755);
       if (SetCurrentDirectoryA (local_dir.c_str()))
 	{
 	  if (source == IDC_SOURCE_CWD)
@@ -213,6 +252,12 @@ LocalDirPage::OnNext ()
 	      return IDD_CHOOSE;
 	    }
 	}
+      else if (GetLastError () == ERROR_FILE_NOT_FOUND)
+	{
+	  if (offer_to_create (GetHWND (), local_dir.c_str()))
+	    return -1;
+	  trySetCurDir = true;
+	}
       else
 	{
 	  DWORD err = GetLastError ();
Index: res.rc
===================================================================
RCS file: /cvs/cygwin-apps/setup/res.rc,v
retrieving revision 2.81
diff -p -u -r2.81 res.rc
--- res.rc	19 Sep 2009 03:38:50 -0000	2.81
+++ res.rc	4 Nov 2009 16:46:46 -0000
@@ -527,4 +527,5 @@ BEGIN
        "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?"
 END
Index: resource.h
===================================================================
RCS file: /cvs/cygwin-apps/setup/resource.h,v
retrieving revision 2.39
diff -p -u -r2.39 resource.h
--- resource.h	11 May 2009 20:32:59 -0000	2.39
+++ resource.h	4 Nov 2009 16:46:46 -0000
@@ -36,6 +36,7 @@
 #define IDS_SEARCH_TOOLTIP                133
 #define IDS_LOCAL_DIR_DOWNLOAD            134
 #define IDS_LOCAL_DIR_INSTALL             135
+#define IDS_MAYBE_MKDIR                   136
 
 // Dialogs
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]