]> cygwin.com Git - cygwin-apps/setup.git/blob - site.cc
2005-05-21 Brian Dessent <brian@dessent.net>
[cygwin-apps/setup.git] / site.cc
1 /*
2 * Copyright (c) 2000, Red Hat, Inc.
3 *
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.
8 *
9 * A copy of the GNU General Public License can be found at
10 * http://www.gnu.org/
11 *
12 * Written by DJ Delorie <dj@cygnus.com>
13 *
14 */
15
16 /* The purpose of this file is to get the list of mirror sites and ask
17 the user which mirror site they want to download from. */
18
19 #if 0
20 static const char *cvsid =
21 "\n%%% $Id$\n";
22 #endif
23
24 #include "site.h"
25 #include "win32.h"
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <process.h>
30 #include <algorithm>
31
32 #include "dialog.h"
33 #include "resource.h"
34 #include "state.h"
35 #include "geturl.h"
36 #include "msg.h"
37 #include "LogSingleton.h"
38 #include "io_stream.h"
39 #include "site.h"
40
41 #include "propsheet.h"
42
43 #include "threebar.h"
44 #include "ControlAdjuster.h"
45 #include "Exception.h"
46
47 extern ThreeBarProgressPage Progress;
48
49 /*
50 Sizing information.
51 */
52 static ControlAdjuster::ControlInfo SiteControlsInfo[] = {
53 {IDC_URL_LIST, CP_STRETCH, CP_STRETCH},
54 {IDC_EDIT_USER_URL, CP_STRETCH, CP_BOTTOM},
55 {IDC_BUTTON_ADD_URL, CP_RIGHT, CP_BOTTOM},
56 {IDC_SITE_USERURL, CP_LEFT, CP_BOTTOM},
57 {0, CP_LEFT, CP_TOP}
58 };
59
60 SitePage::SitePage ()
61 {
62 sizeProcessor.AddControlInfo (SiteControlsInfo);
63 }
64
65 #include "getopt++/StringOption.h"
66 #include "UserSettings.h"
67
68 using namespace std;
69
70 SiteList site_list;
71 SiteList all_site_list;
72
73 StringOption SiteOption("", 's', "site", "Download site", false);
74
75 /* XXX make into a singleton? */
76 static SiteSetting ChosenSites;
77
78 void
79 SiteSetting::load()
80 {
81 string SiteOptionString = SiteOption;
82 if (SiteOptionString.size())
83 registerSavedSite (SiteOptionString.c_str());
84 else
85 getSavedSites ();
86 }
87
88 void
89 SiteSetting::save()
90 {
91 io_stream *f = UserSettings::Instance().settingFileForSave("last-mirror");
92 if (f)
93 {
94 for (SiteList::const_iterator n = site_list.begin ();
95 n != site_list.end (); ++n)
96 f->write ((n->url + "\n").c_str(), n->url.size() + 1);
97 delete f;
98 }
99 }
100
101 void
102 site_list_type::init (String const &newurl)
103 {
104 url = newurl;
105
106 char *dots = new_cstr_char_array (newurl);
107 char *dot = strchr (dots, '.');
108 if (dot)
109 {
110 dot = strchr (dot, '/');
111 if (dot)
112 *dot = 0;
113 }
114 displayed_url = String (dots);
115
116
117 dot = dots + strlen (dots);
118 char *dpsave, *dp = new char[2 * newurl.size() + 3];
119 dpsave = dp;
120 while (dot != dots)
121 {
122 if (*dot == '.' || *dot == '/')
123 {
124 char *sp;
125 if (dot[3] == 0)
126 *dp++ = '~'; /* sort .com/.edu/.org together */
127 for (sp = dot + 1; *sp && *sp != '.' && *sp != '/';)
128 *dp++ = *sp++;
129 *dp++ = ' ';
130 }
131 --dot;
132 }
133 *dp++ = ' ';
134 strcpy (dp, dots);
135 delete[] dots;
136 key = String (dp);
137 delete[] dpsave;
138 }
139
140 site_list_type::site_list_type (String const &newurl)
141 {
142 init (newurl);
143 }
144
145 site_list_type::site_list_type (site_list_type const &rhs)
146 {
147 key = rhs.key;
148 url = rhs.url;
149 displayed_url = rhs.displayed_url;
150 }
151
152 site_list_type &
153 site_list_type::operator= (site_list_type const &rhs)
154 {
155 key = rhs.key;
156 url = rhs.url;
157 displayed_url = rhs.displayed_url;
158 return *this;
159 }
160
161 bool
162 site_list_type::operator == (site_list_type const &rhs) const
163 {
164 return key.casecompare (rhs.key) == 0;
165 }
166
167 bool
168 site_list_type::operator < (site_list_type const &rhs) const
169 {
170 return key.casecompare (rhs.key) < 0;
171 }
172
173 static void
174 save_dialog (HWND h)
175 {
176 // Remove anything that was previously in the selected site list.
177 site_list.clear ();
178
179 HWND listbox = GetDlgItem (h, IDC_URL_LIST);
180 int sel_count = SendMessage (listbox, LB_GETSELCOUNT, 0, 0);
181 if (sel_count > 0)
182 {
183 int sel_buffer[sel_count];
184 SendMessage (listbox, LB_GETSELITEMS, sel_count, (LPARAM) sel_buffer);
185 for (int n = 0; n < sel_count; n++)
186 {
187 int mirror =
188 SendMessage (listbox, LB_GETITEMDATA, sel_buffer[n], 0);
189 site_list.push_back (all_site_list[mirror]);
190 }
191 }
192 }
193
194 static int
195 get_site_list (HINSTANCE h, HWND owner)
196 {
197 char mirror_url[1000];
198
199 if (LoadString (h, IDS_MIRROR_LST, mirror_url, sizeof (mirror_url)) <= 0)
200 return 1;
201 char *bol, *eol, *nl, *theString;
202 {
203 String mirrors = get_url_to_string (mirror_url, owner);
204 if (!mirrors.size())
205 return 1;
206
207 theString = new_cstr_char_array (mirrors);
208 nl = theString;
209 }
210
211 while (*nl)
212 {
213 bol = nl;
214 for (eol = bol; *eol && *eol != '\n'; eol++);
215 if (*eol)
216 nl = eol + 1;
217 else
218 nl = eol;
219 while (eol > bol && eol[-1] == '\r')
220 eol--;
221 *eol = 0;
222 if (*bol == '#' || !*bol)
223 continue;
224 /* Accept only the URL schemes we can understand. */
225 if (strncmp(bol, "http://", 7) == 0 ||
226 strncmp(bol, "ftp://", 6) == 0)
227 {
228 char *semi = strchr (bol, ';');
229 if (semi)
230 *semi = 0;
231 site_list_type newsite (bol);
232 SiteList::iterator i = find (all_site_list.begin(),
233 all_site_list.end(), newsite);
234 if (i == all_site_list.end())
235 {
236 SiteList result;
237 merge (all_site_list.begin(), all_site_list.end(),
238 &newsite, &newsite + 1,
239 inserter (result, result.begin()));
240 all_site_list = result;
241 }
242 else
243 //TODO: remove and remerge
244 *i = newsite;
245 }
246 }
247 delete[] theString;
248
249 return 0;
250 }
251
252 /* List of machines that should not be used by default when saved
253 in "last-mirror". */
254 #define NOSAVE1 "ftp://sources.redhat.com/"
255 #define NOSAVE1_LEN (sizeof ("ftp://sources.redhat.com/") - 1)
256 #define NOSAVE2 "ftp://sourceware.cygnus.com/"
257 #define NOSAVE2_LEN (sizeof ("ftp://sourceware.cygnus.com/") - 1)
258 #define NOSAVE3 "ftp://gcc.gnu.org/"
259 #define NOSAVE3_LEN (sizeof ("ftp://gcc.gnu.org/") - 1)
260
261 void
262 SiteSetting::registerSavedSite (const char * site)
263 {
264 site_list_type tempSite(site);
265 SiteList::iterator i = find (all_site_list.begin(),
266 all_site_list.end(), tempSite);
267 if (i == all_site_list.end())
268 {
269 /* Don't default to certain machines ever since they suffer
270 from bandwidth limitations. */
271 if (strnicmp (site, NOSAVE1, NOSAVE1_LEN) == 0
272 || strnicmp (site, NOSAVE2, NOSAVE2_LEN) == 0
273 || strnicmp (site, NOSAVE3, NOSAVE3_LEN) == 0)
274 return;
275 SiteList result;
276 merge (all_site_list.begin(), all_site_list.end(),
277 &tempSite, &tempSite + 1,
278 inserter (result, result.begin()));
279 all_site_list = result;
280 site_list.push_back (tempSite);
281 }
282 else
283 site_list.push_back (tempSite);
284 }
285
286 void
287 SiteSetting::getSavedSites ()
288 {
289 io_stream *f = UserSettings::Instance().settingFileForLoad("last-mirror");
290 if (!f)
291 return;
292
293 char site[1000];
294 char *fg_ret;
295 while ((fg_ret = f->gets (site, 1000)))
296 {
297
298 char *eos = site + strlen (site) - 1;
299 while (eos >= site && (*eos == '\n' || *eos == '\r'))
300 *eos-- = '\0';
301
302 if (eos < site)
303 continue;
304
305 registerSavedSite (site);
306
307 }
308 delete f;
309
310 }
311
312 static DWORD WINAPI
313 do_download_site_info_thread (void *p)
314 {
315 HANDLE *context;
316 HINSTANCE hinst;
317 HWND h;
318 context = (HANDLE *) p;
319
320 try
321 {
322 hinst = (HINSTANCE) (context[0]);
323 h = (HWND) (context[1]);
324 static bool downloaded = false;
325 if (!downloaded && get_site_list (hinst, h))
326 {
327 // Error: Couldn't download the site info.
328 // Go back to the Net setup page.
329 MessageBox (h, TEXT ("Can't get list of download sites.\n")
330 TEXT("Make sure your network settings are correct and try again."),
331 NULL, MB_OK);
332
333 // Tell the progress page that we're done downloading
334 Progress.PostMessage (WM_APP_SITE_INFO_DOWNLOAD_COMPLETE, 0, IDD_NET);
335 }
336 else
337 {
338 downloaded = true;
339 // Everything worked, go to the site select page
340 // Tell the progress page that we're done downloading
341 Progress.PostMessage (WM_APP_SITE_INFO_DOWNLOAD_COMPLETE, 0, IDD_SITE);
342 }
343 }
344 TOPLEVEL_CATCH("site");
345
346 ExitThread(0);
347 }
348
349 static HANDLE context[2];
350
351 void
352 do_download_site_info (HINSTANCE hinst, HWND owner)
353 {
354
355 context[0] = hinst;
356 context[1] = owner;
357
358 DWORD threadID;
359 CreateThread (NULL, 0, do_download_site_info_thread, context, 0, &threadID);
360 }
361
362 bool SitePage::Create ()
363 {
364 return PropertyPage::Create (IDD_SITE);
365 }
366
367 long
368 SitePage::OnNext ()
369 {
370 HWND h = GetHWND ();
371
372 save_dialog (h);
373 ChosenSites.save ();
374
375 // Log all the selected URLs from the list.
376 for (SiteList::const_iterator n = site_list.begin ();
377 n != site_list.end (); ++n)
378 log (LOG_PLAIN) << "site: " << n->url << endLog;
379
380 Progress.SetActivateTask (WM_APP_START_SETUP_INI_DOWNLOAD);
381 return IDD_INSTATUS;
382
383 return 0;
384 }
385
386 long
387 SitePage::OnBack ()
388 {
389 HWND h = GetHWND ();
390
391 save_dialog (h);
392
393 // Go back to the net connection type page
394 return 0;
395 }
396
397 void
398 SitePage::OnActivate ()
399 {
400 // Fill the list box with all known sites.
401 PopulateListBox ();
402
403 // Load the user URL box with nothing - it is in the list already.
404 eset (GetHWND (), IDC_EDIT_USER_URL, "");
405
406 // Get the enabled/disabled states of the controls set accordingly.
407 CheckControlsAndDisableAccordingly ();
408 }
409
410 long
411 SitePage::OnUnattended ()
412 {
413 if (SendMessage (GetDlgItem (IDC_URL_LIST), LB_GETSELCOUNT, 0, 0) > 0)
414 return OnNext ();
415 else
416 return -2;
417 }
418
419 void
420 SitePage::CheckControlsAndDisableAccordingly () const
421 {
422 DWORD ButtonFlags = PSWIZB_BACK;
423
424 // Check that at least one download site is selected.
425 if (SendMessage (GetDlgItem (IDC_URL_LIST), LB_GETSELCOUNT, 0, 0) > 0)
426 {
427 // At least one site selected, enable "Next".
428 ButtonFlags |= PSWIZB_NEXT;
429 }
430 GetOwner ()->SetButtons (ButtonFlags);
431 }
432
433 void
434 SitePage::PopulateListBox ()
435 {
436 int j;
437 HWND listbox = GetDlgItem (IDC_URL_LIST);
438
439 // Populate the list box with the URLs.
440 SendMessage (listbox, LB_RESETCONTENT, 0, 0);
441 for (SiteList::const_iterator i = all_site_list.begin ();
442 i != all_site_list.end (); ++i)
443 {
444 j = SendMessage (listbox, LB_ADDSTRING, 0,
445 (LPARAM) i->displayed_url.c_str());
446 SendMessage (listbox, LB_SETITEMDATA, j, j);
447 }
448
449 // Select the selected ones.
450 for (SiteList::const_iterator n = site_list.begin ();
451 n != site_list.end (); ++n)
452 {
453 int index = SendMessage (listbox, LB_FINDSTRING, (WPARAM) - 1,
454 (LPARAM) n->displayed_url.c_str());
455 if (index != LB_ERR)
456 {
457 // Highlight the selected item
458 SendMessage (listbox, LB_SELITEMRANGE, TRUE, (index << 16) | index);
459 // Make sure it's fully visible
460 SendMessage (listbox, LB_SETCARETINDEX, index, FALSE);
461 }
462 }
463 }
464
465 bool SitePage::OnMessageCmd (int id, HWND hwndctl, UINT code)
466 {
467 switch (id)
468 {
469 case IDC_EDIT_USER_URL:
470 {
471 // FIXME: Make Enter here cause an ADD, not a NEXT.
472 break;
473 }
474 case IDC_URL_LIST:
475 {
476 if (code == LBN_SELCHANGE)
477 {
478 CheckControlsAndDisableAccordingly ();
479 save_dialog (GetHWND ());
480 }
481 break;
482 }
483 case IDC_BUTTON_ADD_URL:
484 {
485 if (code == BN_CLICKED)
486 {
487 // User pushed the Add button.
488 String other_url = egetString (GetHWND (), IDC_EDIT_USER_URL);
489 if (other_url.size())
490 {
491 site_list_type newsite (other_url);
492 SiteList::iterator i = find (all_site_list.begin(),
493 all_site_list.end(), newsite);
494 if (i == all_site_list.end())
495 {
496 all_site_list.push_back (newsite);
497 log (LOG_BABBLE) << "Adding site: " << other_url << endLog;
498 }
499 else
500 {
501 *i = newsite;
502 log (LOG_BABBLE) << "Replacing site: " << other_url << endLog;
503 }
504
505 // Assume the user wants to use it and select it for him.
506 site_list.push_back (newsite);
507
508 // Update the list box.
509 PopulateListBox ();
510 // And allow the user to continue
511 CheckControlsAndDisableAccordingly ();
512 eset (GetHWND (), IDC_EDIT_USER_URL, "");
513 }
514 }
515 break;
516 }
517 default:
518 // Wasn't recognized or handled.
519 return false;
520 }
521
522 // Was handled since we never got to default above.
523 return true;
524 }
This page took 0.057741 seconds and 5 git commands to generate.