Suggest URLs for updated setup based on build architecture
[cygwin-setup.git] / localdir.cc
blob52bf734e93be5daf4208a87204e90928c0276e58
1 /*
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
10 * http://www.gnu.org/
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
21 #include "localdir.h"
23 #include "LogSingleton.h"
24 #include "LogFile.h"
25 #include "win32.h"
26 #include "filemanip.h"
28 #include <shlobj.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <ctype.h>
33 #include "ini.h"
34 #include "dialog.h"
35 #include "resource.h"
36 #include "state.h"
37 #include "msg.h"
38 #include "mount.h"
39 #include "io_stream.h"
40 #include "mkdir.h"
42 #include "UserSettings.h"
44 #include "getopt++/StringOption.h"
46 #include "threebar.h"
47 extern ThreeBarProgressPage Progress;
49 static StringOption LocalDirOption ("", 'l', "local-package-dir", IDS_HELPTEXT_LOCAL_PACKAGE_DIR, 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 },
55 {0, CP_LEFT, CP_TOP}
58 LocalDirSetting::LocalDirSetting ()
60 const char *fg_ret;
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);
67 void
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);
78 else
80 Logger ().clearFiles();
81 mkdir_p (1, cygpath ("/var/log").c_str (), 01777);
82 Logger ().setFile (LOG_BABBLE, cygpath ("/var/log/setup.log.full"),
83 false);
84 Logger ().setFile (0, cygpath ("/var/log/setup.log"), true);
88 static void
89 check_if_enable_next (HWND h)
91 EnableWindow (GetDlgItem (h, IDOK), local_dir.size() != 0);
94 static void
95 load_dialog (HWND h)
97 if (source != IDC_SOURCE_LOCALDIR)
99 ShowWindow (GetDlgItem(h, IDC_LOCAL_DIR_DOWNLOAD_DESC), SW_SHOW);
100 ShowWindow (GetDlgItem(h, IDC_LOCAL_DIR_INSTALL_DESC), SW_HIDE);
102 else
104 ShowWindow (GetDlgItem(h, IDC_LOCAL_DIR_DOWNLOAD_DESC), SW_HIDE);
105 ShowWindow (GetDlgItem(h, IDC_LOCAL_DIR_INSTALL_DESC), SW_SHOW);
107 eset (h, IDC_LOCAL_DIR, local_dir);
108 check_if_enable_next (h);
111 static void
112 save_dialog (HWND h)
114 local_dir = egetString (h, IDC_LOCAL_DIR);
117 // returns non-zero if refused or error, 0 if accepted and created ok.
118 static int
119 offer_to_create (HWND h, const char *dirname)
121 if (!dirname || !*dirname)
122 return -1;
124 if (!unattended_mode)
126 DWORD ret;
127 ret = mbox (h, IDS_MAYBE_MKDIR, MB_ICONSTOP | MB_YESNO, dirname);
128 if (ret == IDNO)
129 return -1;
132 int rv = mkdir_p (true, dirname, 0);
134 if (rv)
135 note (h, IDS_CANT_MKDIR, dirname);
137 return rv;
140 static int CALLBACK
141 browse_cb (HWND h, UINT msg, LPARAM lp, LPARAM data)
143 /* SHGetPathFromIDList doesn't handle path length > MAX_PATH. */
144 static CHAR dirname[MAX_PATH];
145 switch (msg)
147 case BFFM_INITIALIZED:
148 if (local_dir.size())
149 SendMessage (h, BFFM_SETSELECTION, TRUE, (LPARAM) local_dir.c_str());
150 break;
151 case BFFM_SELCHANGED:
153 // Make a note of each new dir we successfully select, so that
154 // we know where to create the new directory if an invalid name
155 // is entered in the text box.
156 LPITEMIDLIST pidl = reinterpret_cast<LPITEMIDLIST>(lp);
157 SHGetPathFromIDList (pidl, dirname);
158 break;
160 case BFFM_VALIDATEFAILED:
161 // See if user wants to create a dir in the last successfully-selected.
162 CHAR tempname[MAX_PATH];
163 snprintf (tempname, sizeof tempname, "%s\\%s", dirname, reinterpret_cast<LPTSTR>(lp));
164 if (!offer_to_create (h, tempname))
166 SendMessage (h, BFFM_SETSELECTION, TRUE, reinterpret_cast<LPARAM>(tempname));
167 return -1;
169 // Reset to original directory instead.
170 SendMessage (h, BFFM_SETSELECTION, TRUE, reinterpret_cast<LPARAM>(dirname));
171 return -1;
173 return 0;
176 static void
177 browse (HWND h)
179 std::wstring title = LoadStringW((source != IDC_SOURCE_LOCALDIR) ?
180 IDS_LOCALDIR_BROWSE_DOWNLOAD_TITLE :
181 IDS_LOCALDIR_BROWSE_PACKAGE_TITLE);
183 wchar_t wname[MAX_PATH];
184 BROWSEINFOW bi;
185 memset (&bi, 0, sizeof (bi));
186 bi.hwndOwner = h;
187 bi.pszDisplayName = wname;
188 bi.lpszTitle = title.c_str();
189 bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE
190 | ((source != IDC_SOURCE_LOCALDIR) ? (BIF_EDITBOX | BIF_VALIDATE)
191 : 0);
192 bi.lpfn = browse_cb;
194 /* SHGetPathFromIDList doesn't handle path length > MAX_PATH. */
195 LPITEMIDLIST pidl;
196 pidl = SHBrowseForFolderW (&bi);
197 if (pidl)
199 CHAR name[MAX_PATH];
200 if (SHGetPathFromIDList (pidl, name))
201 eset (h, IDC_LOCAL_DIR, name);
205 static BOOL
206 dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
208 switch (id)
211 case IDC_LOCAL_DIR:
212 save_dialog (h);
213 check_if_enable_next (h);
214 break;
216 case IDC_LOCAL_DIR_BROWSE:
217 browse (h);
218 break;
220 return 0;
223 LocalDirPage::LocalDirPage ()
225 sizeProcessor.AddControlInfo (LocaldirControlsInfo);
228 bool
229 LocalDirPage::Create ()
231 return PropertyPage::Create (NULL, dialog_cmd, IDD_LOCAL_DIR);
234 void
235 LocalDirPage::OnActivate ()
237 load_dialog (GetHWND ());
240 long
241 LocalDirPage::OnNext ()
243 HWND h = GetHWND ();
245 save_dialog (h);
246 while (local_dir[local_dir.size() - 1] == '\\' || local_dir[local_dir.size() - 1] == '/')
247 local_dir.erase (local_dir.size() - 1, 1);
248 LocalDirSetting::save ();
249 Log (LOG_PLAIN) << "Selected local directory: " << local_dir << endLog;
251 bool tryLocalDir = true;
252 while (tryLocalDir)
254 tryLocalDir = false;
255 /* FIXME: As for almost any other string, we should store local_dir
256 as UNICODE string to avoid the whole conversion mess.
257 We call GetFileAttributesW because our own version implies
258 FILE_OPEN_FOR_BACKUP_INTENT. We don't try to change CWD for
259 the same reason. */
260 size_t len = local_dir.size () + 7;
261 WCHAR wlocal[len];
262 mklongpath (wlocal, local_dir.c_str (), len);
263 DWORD attr = GetFileAttributesW (wlocal);
264 if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY))
266 if (source == IDC_SOURCE_LOCALDIR)
268 do_from_local_dir (GetInstance (), GetHWND (), local_dir);
269 Progress.SetActivateTask (WM_APP_START_SETUP_INI_DOWNLOAD);
270 return IDD_INSTATUS;
273 else if (attr == INVALID_FILE_ATTRIBUTES
274 && (GetLastError () == ERROR_FILE_NOT_FOUND
275 || GetLastError () == ERROR_PATH_NOT_FOUND))
277 if (source == IDC_SOURCE_LOCALDIR)
279 if (!unattended_mode)
281 // Check the user really wants only to uninstall.
282 int ret = mbox(h, IDS_NO_LOCALDIR,
283 MB_ICONEXCLAMATION | MB_OKCANCEL,
284 local_dir.c_str ());
285 if (ret == IDCANCEL)
286 return -1;
288 Progress.SetActivateTask (WM_APP_START_SETUP_INI_DOWNLOAD);
289 return IDD_INSTATUS;
291 else if (offer_to_create (GetHWND (), local_dir.c_str ()))
292 return -1;
293 tryLocalDir = true;
295 else
297 DWORD err = GetLastError ();
298 char* buf;
299 char msg[1000];
300 if (FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
301 0, err, LANG_NEUTRAL, (LPSTR)&buf, 0, 0) != 0)
303 snprintf (msg, sizeof (msg), "%s", buf);
304 LocalFree (buf);
306 else
307 snprintf (msg, sizeof (msg), "%s", "(unknown error)");
308 int ret = mbox (h, IDS_ERR_CHDIR,
309 MB_ICONEXCLAMATION | MB_ABORTRETRYIGNORE,
310 local_dir.c_str(), msg, err);
311 if (ret == IDABORT)
312 return -1;
313 else
314 tryLocalDir = (ret == IDRETRY);
318 if (source == IDC_SOURCE_LOCALDIR)
319 return IDD_INSTATUS;
321 return 0; // IDD_NET
324 long
325 LocalDirPage::OnBack ()
327 save_dialog (GetHWND ());
328 return 0;