2 * Copyright (c) 2000, Red Hat, Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * A copy of the GNU General Public License can be found at
12 * Written by Andrej Borsenkow <Andrej.Borsenkow@mow.siemens.ru>
13 * based on work and suggestions of DJ Delorie
17 /* The purpose of this file is to ask the user where they want the
18 * locally downloaded package files to be cached
23 #include "LogSingleton.h"
26 #include "filemanip.h"
39 #include "io_stream.h"
42 #include "UserSettings.h"
44 #include "getopt++/StringOption.h"
47 extern ThreeBarProgressPage Progress
;
49 static StringOption
LocalDirOption ("", 'l', "local-package-dir", "Local package directory", false);
51 static ControlAdjuster::ControlInfo LocaldirControlsInfo
[] = {
52 { IDC_LOCALDIR_GRP
, CP_STRETCH
, CP_TOP
},
53 { IDC_LOCAL_DIR
, CP_STRETCH
, CP_TOP
},
54 { IDC_LOCAL_DIR_BROWSE
, CP_RIGHT
, CP_TOP
},
58 LocalDirSetting::LocalDirSetting ()
61 if (std::string (LocalDirOption
).size ())
62 local_dir
= std::string (LocalDirOption
);
63 else if ((fg_ret
= UserSettings::instance().get ("last-cache")))
64 local_dir
= std::string (fg_ret
);
68 LocalDirSetting::save ()
70 UserSettings::instance().set ("last-cache", local_dir
);
71 if (source
== IDC_SOURCE_DOWNLOAD
|| !get_root_dir ().size())
73 const char *sep
= isdirsep (local_dir
[local_dir
.size () - 1]) ? "" : "\\";
74 Logger ().clearFiles();
75 Logger ().setFile (LOG_BABBLE
, local_dir
+ sep
+ "setup.log.full", false);
76 Logger ().setFile (0, local_dir
+ sep
+ "setup.log", true);
80 Logger ().clearFiles();
81 mkdir_p (1, cygpath ("/var/log").c_str (), 01777);
82 Logger ().setFile (LOG_BABBLE
, cygpath ("/var/log/setup.log.full"),
84 Logger ().setFile (0, cygpath ("/var/log/setup.log"), true);
89 check_if_enable_next (HWND h
)
91 EnableWindow (GetDlgItem (h
, IDOK
), local_dir
.size() != 0);
98 if (source
!= IDC_SOURCE_LOCALDIR
)
100 LoadString (hinstance
, IDS_LOCAL_DIR_DOWNLOAD
, descText
, sizeof (descText
));
104 LoadString (hinstance
, IDS_LOCAL_DIR_INSTALL
, descText
, sizeof (descText
));
106 eset (h
, IDC_LOCAL_DIR_DESC
, descText
);
107 eset (h
, IDC_LOCAL_DIR
, local_dir
);
108 check_if_enable_next (h
);
114 local_dir
= egetString (h
, IDC_LOCAL_DIR
);
117 // returns non-zero if refused or error, 0 if accepted and created ok.
119 offer_to_create (HWND h
, const char *dirname
)
121 if (!dirname
|| !*dirname
)
124 if (!unattended_mode
)
126 char msgText
[MAX_PATH
+ 100];
130 LoadString (hinstance
, IDS_MAYBE_MKDIR
, fmtString
, sizeof fmtString
);
131 snprintf (msgText
, sizeof msgText
, fmtString
, dirname
);
133 ret
= MessageBox (h
, msgText
, "Cygwin Setup", MB_ICONSTOP
| MB_YESNO
);
138 int rv
= mkdir_p (true, dirname
, 0);
141 note (h
, IDS_CANT_MKDIR
, dirname
);
147 browse_cb (HWND h
, UINT msg
, LPARAM lp
, LPARAM data
)
149 /* SHGetPathFromIDList doesn't handle path length > MAX_PATH. */
150 static CHAR dirname
[MAX_PATH
];
153 case BFFM_INITIALIZED
:
154 if (local_dir
.size())
155 SendMessage (h
, BFFM_SETSELECTION
, TRUE
, (LPARAM
) local_dir
.c_str());
157 case BFFM_SELCHANGED
:
159 // Make a note of each new dir we successfully select, so that
160 // we know where to create the new directory if an invalid name
161 // is entered in the text box.
162 LPITEMIDLIST pidl
= reinterpret_cast<LPITEMIDLIST
>(lp
);
163 SHGetPathFromIDList (pidl
, dirname
);
166 case BFFM_VALIDATEFAILED
:
167 // See if user wants to create a dir in the last successfully-selected.
168 CHAR tempname
[MAX_PATH
];
169 snprintf (tempname
, sizeof tempname
, "%s\\%s", dirname
, reinterpret_cast<LPTSTR
>(lp
));
170 if (!offer_to_create (h
, tempname
))
172 SendMessage (h
, BFFM_SETSELECTION
, TRUE
, reinterpret_cast<LPARAM
>(tempname
));
175 // Reset to original directory instead.
176 SendMessage (h
, BFFM_SETSELECTION
, TRUE
, reinterpret_cast<LPARAM
>(dirname
));
186 /* SHGetPathFromIDList doesn't handle path length > MAX_PATH. */
189 memset (&bi
, 0, sizeof (bi
));
191 bi
.pszDisplayName
= name
;
192 bi
.lpszTitle
= (source
!= IDC_SOURCE_LOCALDIR
) ? "Select download directory"
193 : "Select local package directory";
194 bi
.ulFlags
= BIF_RETURNONLYFSDIRS
| BIF_NEWDIALOGSTYLE
195 | ((source
!= IDC_SOURCE_LOCALDIR
) ? (BIF_EDITBOX
| BIF_VALIDATE
)
198 pidl
= SHBrowseForFolder (&bi
);
201 if (SHGetPathFromIDList (pidl
, name
))
202 eset (h
, IDC_LOCAL_DIR
, name
);
207 dialog_cmd (HWND h
, int id
, HWND hwndctl
, UINT code
)
214 check_if_enable_next (h
);
217 case IDC_LOCAL_DIR_BROWSE
:
224 LocalDirPage::LocalDirPage ()
226 sizeProcessor
.AddControlInfo (LocaldirControlsInfo
);
230 LocalDirPage::Create ()
232 return PropertyPage::Create (NULL
, dialog_cmd
, IDD_LOCAL_DIR
);
236 LocalDirPage::OnActivate ()
238 load_dialog (GetHWND ());
242 LocalDirPage::OnNext ()
247 while (local_dir
[local_dir
.size() - 1] == '\\' || local_dir
[local_dir
.size() - 1] == '/')
248 local_dir
.erase (local_dir
.size() - 1, 1);
249 LocalDirSetting::save ();
250 Log (LOG_PLAIN
) << "Selected local directory: " << local_dir
<< endLog
;
252 bool tryLocalDir
= true;
256 /* FIXME: As for almost any other string, we should store local_dir
257 as UNICODE string to avoid the whole conversion mess.
258 We call GetFileAttributesW because our own version implies
259 FILE_OPEN_FOR_BACKUP_INTENT. We don't try to change CWD for
261 size_t len
= local_dir
.size () + 7;
263 mklongpath (wlocal
, local_dir
.c_str (), len
);
264 DWORD attr
= GetFileAttributesW (wlocal
);
265 if (attr
!= INVALID_FILE_ATTRIBUTES
&& (attr
& FILE_ATTRIBUTE_DIRECTORY
))
267 if (source
== IDC_SOURCE_LOCALDIR
)
269 do_from_local_dir (GetInstance (), GetHWND (), local_dir
);
270 Progress
.SetActivateTask (WM_APP_START_SETUP_INI_DOWNLOAD
);
274 else if (attr
== INVALID_FILE_ATTRIBUTES
275 && (GetLastError () == ERROR_FILE_NOT_FOUND
276 || GetLastError () == ERROR_PATH_NOT_FOUND
))
278 if (source
== IDC_SOURCE_LOCALDIR
)
280 if (!unattended_mode
)
282 // Check the user really wants only to uninstall.
284 LoadString (hinstance
, IDS_NO_LOCALDIR
, msgText
,
286 char msg
[1000 + local_dir
.size ()];
287 snprintf (msg
, sizeof (msg
), msgText
, local_dir
.c_str ());
288 int ret
= MessageBox (h
, msg
, "Cygwin Setup", MB_ICONEXCLAMATION
| MB_OKCANCEL
);
292 Progress
.SetActivateTask (WM_APP_START_SETUP_INI_DOWNLOAD
);
295 else if (offer_to_create (GetHWND (), local_dir
.c_str ()))
301 DWORD err
= GetLastError ();
303 LoadString (hinstance
, IDS_ERR_CHDIR
, msgText
, sizeof (msgText
));
306 if (FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
|
307 FORMAT_MESSAGE_ALLOCATE_BUFFER
, 0, err
, LANG_NEUTRAL
,
308 (LPSTR
)&buf
, 0, 0) != 0)
310 snprintf (msg
, sizeof (msg
), msgText
, local_dir
.c_str(),
315 snprintf (msg
, sizeof (msg
), msgText
, local_dir
.c_str(),
316 "(unknown error)", err
);
317 int ret
= mbox (h
, msg
, "Cygwin Setup", MB_ICONEXCLAMATION
| MB_ABORTRETRYIGNORE
);
321 tryLocalDir
= (ret
== IDRETRY
);
325 if (source
== IDC_SOURCE_LOCALDIR
)
332 LocalDirPage::OnBack ()
334 save_dialog (GetHWND ());