• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Aucun tag

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

The MinGW.org Installation Manager Tool


Commit MetaInfo

Révision2990b9141d2c350af690ee1f40dc4a72e4d18932 (tree)
l'heure2008-11-02 09:13:49
AuteurJohn E. <tdragon@user...>
CommiterJohn E.

Message de Log

UI/functionality separation made more distinct

Change Summary

Modification

--- /dev/null
+++ b/download.c
@@ -0,0 +1,85 @@
1+
2+#include <curl/curl.h>
3+#include "error.hh"
4+
5+
6+typedef struct CallbackInfo
7+{
8+ void (*next_callback)(size_t);
9+ int total_sent;
10+} CallbackInfo;
11+
12+int DLCallback
13+ (void* clientp,
14+ double dltotal,
15+ double dlnow,
16+ double ultotal,
17+ double ulnow)
18+{
19+ CallbackInfo* cbi = (CallbackInfo*)clientp;
20+ if (!cbi->total_sent)
21+ {
22+ cbi->next_callback((size_t)dltotal);
23+ cbi->total_sent = 1;
24+ }
25+ cbi->next_callback((size_t)dlnow);
26+ return 0;
27+}
28+
29+
30+size_t DownloadFile
31+ (const char* url,
32+ const char* local,
33+ void (*prog_callback)(size_t))
34+{
35+ size_t ret = 0;
36+
37+ CURL* curl = curl_easy_init();
38+ if (curl)
39+ {
40+ curl_easy_setopt(curl, CURLOPT_URL, url);
41+ curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
42+ char errbuf[CURL_ERROR_SIZE];
43+ curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
44+
45+ FILE* outfile = fopen(local, "wb");
46+ if (outfile)
47+ {
48+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile);
49+
50+ if (prog_callback)
51+ {
52+ curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, DLCallback);
53+ CallbackInfo info;
54+ info.next_callback = prog_callback;
55+ info.total_sent = 0;
56+ curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &info);
57+ }
58+ else
59+ curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
60+
61+ CURLcode success = curl_easy_perform(curl);
62+ if (success == 0)
63+ {
64+ double dltotal;
65+ curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &dltotal);
66+ ret = dltotal;
67+ }
68+ else
69+ {
70+ DeleteFile(local);
71+ MGSetError("Failed to download '%s':\n%s", url, errbuf);
72+ }
73+
74+ fclose(outfile);
75+ }
76+ else
77+ MGSetError("Couldn't open '%s' for writing.", local);
78+
79+ curl_easy_cleanup(curl);
80+ }
81+ else
82+ MGSetError("Couldn't initialize CURL downloader.");
83+
84+ return ret;
85+}
--- /dev/null
+++ b/error.c
@@ -0,0 +1,22 @@
1+/** \file error.c
2+ *
3+ * Created: JohnE, 2008-10-12
4+ */
5+
6+
7+#include "error.hh"
8+
9+#include <stdarg.h>
10+#include <stdio.h>
11+
12+
13+char mg_last_error[2048] = {'\0'};
14+
15+
16+void MGSetError(const char* fmt, ...)
17+{
18+ va_list ap;
19+ va_start(ap, fmt);
20+ vsnprintf(mg_last_error, 2048, fmt, ap);
21+ va_end(ap);
22+}
--- /dev/null
+++ b/error.hh
@@ -0,0 +1,24 @@
1+#ifndef ERROR_HH_INC
2+#define ERROR_HH_INC
3+
4+#ifdef __cplusplus
5+extern "C" {
6+#endif
7+
8+
9+void MGSetError(const char* fmt, ...);
10+
11+extern char mg_last_error[];
12+
13+
14+static inline const char* MGLastError()
15+{
16+ return mg_last_error;
17+}
18+
19+
20+#ifdef __cplusplus
21+} // extern "C"
22+#endif
23+
24+#endif // ERROR_HH_INC
--- /dev/null
+++ b/getbindir.c
@@ -0,0 +1,29 @@
1+/** \file getbindir.c
2+ *
3+ * Created: JohnE, 2008-10-09
4+ */
5+
6+
7+#define WIN32_LEAN_AND_MEAN
8+#include <windows.h>
9+
10+
11+const char* GetBinDir()
12+{
13+ static char path[1024] = {0};
14+ if (!path[0])
15+ {
16+ GetModuleFileName(0, path, 1024);
17+ int i = strlen(path);
18+ for (; i >= 0; --i)
19+ {
20+ if (path[i] == '/' || path[i] == '\\')
21+ {
22+ path[i] = '\0';
23+ break;
24+ }
25+ path[i] = '\0';
26+ }
27+ }
28+ return path;
29+}
--- a/mainwnd.c
+++ b/mainwnd.c
@@ -9,10 +9,14 @@
99 #include "pkg_const.h"
1010
1111
12+extern HINSTANCE g_hinstance;
13+
14+
15+HWND g_hmainwnd = 0;
16+
1217 static int g_vert_grip_x = 150;
1318 static float g_horz_grip_prop = 0.5f;
1419 static HACCEL g_haccel;
15-static HINSTANCE g_instance = 0;
1620
1721
1822 void TransToClient(HWND hwnd, RECT* rc)
@@ -31,27 +35,27 @@ void TransToClient(HWND hwnd, RECT* rc)
3135 }
3236
3337
34-void NewVertSashPos(int pos, HWND mainwnd)
38+void NewVertSashPos(int pos)
3539 {
3640 g_vert_grip_x = pos;
3741 RECT rc;
38- GetClientRect(mainwnd, &rc);
39- SendMessage(mainwnd, WM_SIZE, SIZE_RESTORED,
42+ GetClientRect(g_hmainwnd, &rc);
43+ SendMessage(g_hmainwnd, WM_SIZE, SIZE_RESTORED,
4044 MAKELPARAM(rc.right - rc.left, rc.bottom - rc.top));
4145 }
4246
4347
44-void NewHorzSashPos(int pos, HWND mainwnd)
48+void NewHorzSashPos(int pos)
4549 {
4650 RECT tbrc, statrc, rc;
47- GetWindowRect(GetDlgItem(mainwnd, IDC_MAINTOOLBAR), &tbrc);
48- TransToClient(mainwnd, &tbrc);
49- GetWindowRect(GetDlgItem(mainwnd, IDC_STATBAR), &statrc);
50- TransToClient(mainwnd, &statrc);
51- GetClientRect(mainwnd, &rc);
51+ GetWindowRect(GetDlgItem(g_hmainwnd, IDC_MAINTOOLBAR), &tbrc);
52+ TransToClient(g_hmainwnd, &tbrc);
53+ GetWindowRect(GetDlgItem(g_hmainwnd, IDC_STATBAR), &statrc);
54+ TransToClient(g_hmainwnd, &statrc);
55+ GetClientRect(g_hmainwnd, &rc);
5256 g_horz_grip_prop = (float)(pos - (tbrc.bottom - tbrc.top) - 6) /
5357 ((rc.bottom - rc.top) - (tbrc.bottom - tbrc.top) - (statrc.bottom - statrc.top) - 6);
54- SendMessage(mainwnd, WM_SIZE, SIZE_RESTORED,
58+ SendMessage(g_hmainwnd, WM_SIZE, SIZE_RESTORED,
5559 MAKELPARAM(rc.right - rc.left, rc.bottom - rc.top));
5660 }
5761
@@ -88,7 +92,7 @@ static void InsertColumn
8892 }
8993
9094
91-void SelectInst(HINSTANCE, HWND);
95+void SelectInstallation();
9296 const char* Pkg_GetSubItemText(LPARAM, int);
9397 void UI_OnCategoryChange(int, HWND);
9498 void UI_SortListView(int, HWND);
@@ -99,6 +103,8 @@ const char* Pkg_GetInstalledVersion(LPARAM);
99103 int Pkg_GetSelectedAction(LPARAM);
100104 void Pkg_SelectAction(LPARAM, int);
101105 int Pkg_GetStateImage(LPARAM);
106+int PkgIndex_DownloadUpdate();
107+void LastError_MsgBox(const char*);
102108
103109 static BOOL CALLBACK MainWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
104110 {
@@ -117,16 +123,16 @@ static BOOL CALLBACK MainWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM
117123 HIMAGELIST il =
118124 ImageList_Create(24, 24, ILC_COLOR32 | ILC_MASK, 6, 0);
119125 HBITMAP tbbuttons =
120- LoadBitmap(g_instance, MAKEINTRESOURCE(IDB_TBBUTTONS));
126+ LoadBitmap(g_hinstance, MAKEINTRESOURCE(IDB_TBBUTTONS));
121127 ImageList_AddMasked(il, tbbuttons, RGB(255, 0, 255));
122128 DeleteObject(tbbuttons);
123129 SendMessage(htb, TB_SETIMAGELIST, (WPARAM)0, (LPARAM)il);
124130 TBBUTTON tbButtons[3] = {
125- { 0, -1, TBSTATE_ENABLED,
131+ { 0, -1, TBSTATE_ENABLED,
126132 TBSTYLE_BUTTON|TBSTYLE_AUTOSIZE, {0}, 0, (INT_PTR)"Update Lists" },
127- { 1, -1, TBSTATE_ENABLED,
133+ { 1, -1, TBSTATE_ENABLED,
128134 TBSTYLE_BUTTON|TBSTYLE_AUTOSIZE, {0}, 0, (INT_PTR)"Mark All Upgrades"},
129- { 2, -1, 0,
135+ { 2, -1, 0,
130136 TBSTYLE_BUTTON|TBSTYLE_AUTOSIZE, {0}, 0, (INT_PTR)"Apply"}
131137 };
132138 SendMessage(htb, TB_BUTTONSTRUCTSIZE,
@@ -151,7 +157,7 @@ static BOOL CALLBACK MainWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM
151157 LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP);
152158 il = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 10, 0);
153159 HBITMAP buttonsbmp =
154- LoadBitmap(g_instance, MAKEINTRESOURCE(IDB_STATES));
160+ LoadBitmap(g_hinstance, MAKEINTRESOURCE(IDB_STATES));
155161 ImageList_AddMasked(il, buttonsbmp, RGB(255, 0, 255));
156162 DeleteObject(buttonsbmp);
157163 (void)ListView_SetImageList(hlv, il, LVSIL_SMALL);
@@ -192,7 +198,11 @@ static BOOL CALLBACK MainWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM
192198 PostQuitMessage(0);
193199 return TRUE;
194200 case IDM_FILE_CHANGEINST:
195- SelectInst(g_instance, hwndDlg);
201+ SelectInstallation();
202+ return TRUE;
203+ case IDM_SOURCES_UPDATELISTS:
204+ if (!PkgIndex_DownloadUpdate())
205+ LastError_MsgBox("Update Failure");
196206 return TRUE;
197207 case IDC_CATLIST:
198208 if (HIWORD(wParam) == LBN_SELCHANGE)
@@ -419,29 +429,35 @@ static int ProcessQueuedMessages(HWND wnd)
419429 }
420430
421431
422-int SashWnd_RegisterClasses(HINSTANCE);
432+int SashWnd_RegisterClasses();
423433
424-HWND CreateMainWnd(HINSTANCE hInstance)
434+int CreateMainWnd()
425435 {
426- g_instance = hInstance;
427-
428436 InitCommonControls();
429437 OleInitialize(0);
430438
431- if (!SashWnd_RegisterClasses(hInstance))
439+ if (!SashWnd_RegisterClasses(g_hinstance))
440+ {
441+ MessageBox(0, "Couldn't register window classes for sashes.",
442+ "Windowing Failure", MB_OK | MB_ICONERROR);
432443 return 0;
444+ }
433445
434- g_haccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDA_MAINACCEL));
446+ g_haccel = LoadAccelerators(g_hinstance, MAKEINTRESOURCE(IDA_MAINACCEL));
435447
436- HWND wnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_MAINDLG), 0,
448+ HWND wnd = CreateDialog(g_hinstance, MAKEINTRESOURCE(IDD_MAINDLG), 0,
437449 MainWndProc);
438450 if (!wnd)
451+ {
452+ MessageBox(0, "Couldn't create the main window.", "Windowing Failure",
453+ MB_OK | MB_ICONERROR);
439454 return 0;
455+ }
440456 ShowWindow(wnd, SW_SHOW);
441457 if (ProcessQueuedMessages(wnd))
442458 return 0;
443459
444- return wnd;
460+ return 1;
445461 }
446462
447463
--- a/mingw-get.cbp
+++ b/mingw-get.cbp
@@ -54,17 +54,16 @@
5454 <Add directory="$(#zlib)" />
5555 </Linker>
5656 <Unit filename="TODO.txt" />
57- <Unit filename="curl_init.cpp" />
58- <Unit filename="download.cpp">
57+ <Unit filename="download.c">
5958 <Option compilerVar="CC" />
6059 </Unit>
61- <Unit filename="getbindir.cpp" />
62- <Unit filename="inst_manager.cpp" />
63- <Unit filename="inst_manager.hpp" />
64- <Unit filename="instselect.cpp">
60+ <Unit filename="error.c">
61+ <Option compilerVar="CC" />
62+ </Unit>
63+ <Unit filename="error.hh" />
64+ <Unit filename="getbindir.c">
6565 <Option compilerVar="CC" />
6666 </Unit>
67- <Unit filename="main.cpp" />
6867 <Unit filename="mainwnd.c">
6968 <Option compilerVar="CC" />
7069 </Unit>
@@ -76,8 +75,8 @@
7675 <Unit filename="package.cpp" />
7776 <Unit filename="package.hpp" />
7877 <Unit filename="pkg_const.h" />
79- <Unit filename="pkg_index.cpp" />
80- <Unit filename="pkg_index.hpp" />
78+ <Unit filename="pkgindex.cpp" />
79+ <Unit filename="pkgindex.hpp" />
8180 <Unit filename="previnstalls.c">
8281 <Option compilerVar="CC" />
8382 </Unit>
@@ -89,6 +88,9 @@
8988 <Unit filename="sash_wnd.c">
9089 <Option compilerVar="CC" />
9190 </Unit>
91+ <Unit filename="selectinst.cpp">
92+ <Option compilerVar="CC" />
93+ </Unit>
9294 <Unit filename="tinyxml\MODIFIED_TINYXML.txt" />
9395 <Unit filename="tinyxml\tinystr.cpp" />
9496 <Unit filename="tinyxml\tinystr.h" />
@@ -99,9 +101,10 @@
99101 <Unit filename="tracked_install.cpp" />
100102 <Unit filename="tracked_install.hpp" />
101103 <Unit filename="ui.cpp" />
102- <Unit filename="versioning.c">
104+ <Unit filename="versioncompare.c">
103105 <Option compilerVar="CC" />
104106 </Unit>
107+ <Unit filename="winmain.cpp" />
105108 <Extensions>
106109 <code_completion />
107110 <debugger />
--- a/package.cpp
+++ b/package.cpp
@@ -3,7 +3,7 @@
33
44 #define WIN32_LEAN_AND_MEAN
55 #include <windows.h>
6-#include "pkg_index.hpp"
6+#include "pkgindex.hpp"
77 #include "pkg_const.h"
88
99
--- /dev/null
+++ b/pkgindex.cpp
@@ -0,0 +1,135 @@
1+/** \file pkgindex.cpp
2+ *
3+ * Created: JohnE, 2008-10-09
4+ */
5+
6+
7+#include "pkgindex.hpp"
8+
9+#include <string>
10+#include <cstdarg>
11+#include "tinyxml/tinyxml.h"
12+#include "package.hpp"
13+#include "error.hh"
14+
15+
16+std::vector< std::string > PkgIndex::sm_index_categories;
17+PkgIndex::StringIntMap PkgIndex::sm_id_categories;
18+PkgIndex::StringPackageMap PkgIndex::sm_id_packages;
19+
20+
21+static const char* NonEmptyAttribute(const TiXmlElement* el, const char* name)
22+{
23+ const char* attr = el->Attribute(name);
24+ if (attr && attr[0])
25+ return attr;
26+ return 0;
27+}
28+
29+
30+extern "C" const char* GetBinDir();
31+extern "C" size_t DownloadFile(const char*, const char*, void (*)(size_t));
32+
33+extern "C" int PkgIndex_DownloadUpdate()
34+{
35+ if (DownloadFile("http://localhost:1330/mingwinst/mingw_avail.mft",
36+ (std::string(GetBinDir()) + "\\mingw_avail.mft").c_str(), 0) <= 0)
37+ return 0;
38+ return 1;
39+}
40+
41+
42+int PkgIndex::NumCategories()
43+{
44+ return sm_index_categories.size();
45+}
46+
47+
48+const char* PkgIndex::GetCategory(int cat)
49+{
50+ return sm_index_categories[cat].c_str();
51+}
52+
53+
54+int PkgIndex::CategoryIndex(const char* cat_id)
55+{
56+ StringIntMap::iterator found = sm_id_categories.find(cat_id);
57+ if (found == sm_id_categories.end())
58+ return -1;
59+ return found->second;
60+}
61+
62+
63+PkgIndex::PackageIter PkgIndex::Packages_Begin()
64+{
65+ return sm_id_packages.begin();
66+}
67+
68+
69+PkgIndex::PackageIter PkgIndex::Packages_End()
70+{
71+ return sm_id_packages.end();
72+}
73+
74+
75+bool PkgIndex::LoadIndex()
76+{
77+ std::string mfile = std::string(GetBinDir()) + "\\mingw_avail.mft";
78+ TiXmlDocument doc(mfile.c_str());
79+ if (!doc.LoadFile())
80+ {
81+ MGSetError("Couldn't load '%s' as XML", mfile.c_str());
82+ return false;
83+ }
84+ for (TiXmlElement* cat_el =
85+ TiXmlHandle(doc.RootElement()->FirstChildElement("package-categories")).
86+ FirstChildElement("category").ToElement();
87+ cat_el;
88+ cat_el = cat_el->NextSiblingElement("category"))
89+ {
90+ const char* id = NonEmptyAttribute(cat_el, "id");
91+ if (!id)
92+ continue;
93+ const char* name = NonEmptyAttribute(cat_el, "name");
94+ if (!name)
95+ continue;
96+ sm_id_categories[id] = sm_index_categories.size();
97+ sm_index_categories.push_back(name);
98+ }
99+ for (TiXmlElement* package_el =
100+ TiXmlHandle(doc.RootElement()->FirstChildElement("package-collection")).
101+ FirstChildElement("package").ToElement();
102+ package_el;
103+ package_el = package_el->NextSiblingElement("package"))
104+ {
105+ const char* id = NonEmptyAttribute(package_el, "id");
106+ if (!id)
107+ continue;
108+ StringPackageMap::iterator found = sm_id_packages.find(id);
109+ if (found != sm_id_packages.end())
110+ continue;
111+ Package::Ref newpkg(new Package(id, package_el));
112+ InsertPackage(newpkg);
113+ }
114+ return true;
115+}
116+
117+
118+bool PkgIndex::SetInstallation(const char* inst_path)
119+{
120+ return true;
121+}
122+
123+
124+void PkgIndex::Clear()
125+{
126+ sm_index_categories.clear();
127+ sm_id_categories.clear();
128+ sm_id_packages.clear();
129+}
130+
131+
132+void PkgIndex::InsertPackage(Package::Ref ins)
133+{
134+ sm_id_packages.insert(std::make_pair(ins->m_id, ins));
135+}
--- /dev/null
+++ b/pkgindex.hpp
@@ -0,0 +1,44 @@
1+/** \file pkgindex.hpp
2+ *
3+ * Created: JohnE, 2008-10-09
4+ */
5+#ifndef PKGINDEX_HPP_INC
6+#define PKGINDEX_HPP_INC
7+
8+
9+#include <list>
10+#include <map>
11+#include <vector>
12+#include "ref.hpp"
13+
14+
15+struct Package;
16+
17+
18+class PkgIndex
19+{
20+public:
21+ static void Clear();
22+ static bool LoadIndex();
23+ static bool SetInstallation(const char* inst_path);
24+
25+ static int NumCategories();
26+ static const char* GetCategory(int cat);
27+ static int CategoryIndex(const char* cat_id);
28+
29+ typedef std::map< std::string, RefType< Package >::Ref > StringPackageMap;
30+ typedef StringPackageMap::const_iterator PackageIter;
31+ static PackageIter Packages_Begin();
32+ static PackageIter Packages_End();
33+
34+private:
35+ static void InsertPackage(RefType< Package >::Ref ins);
36+
37+ static std::vector< std::string > sm_index_categories;
38+ typedef std::map< std::string, int > StringIntMap;
39+ static StringIntMap sm_id_categories;
40+ static StringPackageMap sm_id_packages;
41+};
42+
43+
44+#endif // PKGINDEX_HPP_INC
--- a/previnstalls.c
+++ b/previnstalls.c
@@ -44,11 +44,8 @@ static int GetPrevInstByFolder(int folder, void (*callback)(const char*))
4444
4545 int GetPrevInstalls(void (*callback)(const char*))
4646 {
47- int utype = GetAccountTypeHelper();
48- if (utype < 0)
49- return 0;
5047 int icount = GetPrevInstByFolder(CSIDL_APPDATA, callback);
51- if (utype >= MU_POWER)
48+ if (GetAccountTypeHelper() >= MU_POWER)
5249 icount += GetPrevInstByFolder(CSIDL_COMMON_APPDATA, callback);
5350 return icount;
5451 }
--- a/resource.h
+++ b/resource.h
@@ -38,4 +38,5 @@
3838 #define IDM_FILE_EXIT 1201
3939 #define IDM_FILE_CHANGEINST 1202
4040 #define IDM_EDIT_PREFERENCES 1203
41-#define IDM_SOURCES_MIRRORS 1204
41+#define IDM_SOURCES_UPDATELISTS 1204
42+#define IDM_SOURCES_MIRRORS 1205
--- a/resource.rc
+++ b/resource.rc
@@ -19,6 +19,7 @@ IDA_MAINACCEL ACCELERATORS
1919 BEGIN
2020 "I", IDM_FILE_CHANGEINST, CONTROL, ALT, VIRTKEY
2121 "P", IDM_EDIT_PREFERENCES, CONTROL, VIRTKEY
22+ "U", IDM_SOURCES_UPDATELISTS, CONTROL, VIRTKEY
2223 "M", IDM_SOURCES_MIRRORS, CONTROL, VIRTKEY
2324 END
2425
@@ -36,6 +37,7 @@ BEGIN
3637 END
3738 POPUP "Sour&ces"
3839 BEGIN
40+ MENUITEM "&Update Lists\tCtrl+U", IDM_SOURCES_UPDATELISTS
3941 MENUITEM "&Mirrors...\tCtrl+M", IDM_SOURCES_MIRRORS
4042 END
4143 END
--- /dev/null
+++ b/selectinst.cpp
@@ -0,0 +1,295 @@
1+
2+#define WIN32_LEAN_AND_MEAN
3+#include <windows.h>
4+#include <windowsx.h>
5+#include <shlobj.h>
6+#include <sys/stat.h>
7+#include <string>
8+#include <map>
9+#include "resource.h"
10+#include "error.hh"
11+#include "pkgindex.hpp"
12+
13+
14+extern HINSTANCE g_hinstance;
15+extern HWND g_hmainwnd;
16+
17+
18+extern "C" {
19+char g_inst_loc[MAX_PATH] = {0};
20+}
21+
22+
23+static HWND g_hdlg = 0;
24+static BOOL g_createinst = FALSE;
25+
26+struct CmpStrI
27+{
28+ bool operator () (const std::string& s1, const std::string& s2)
29+ {
30+ return (stricmp(s1.c_str(), s2.c_str()) < 0);
31+ }
32+};
33+typedef std::map< std::string, int, CmpStrI > InstIndexMap;
34+static InstIndexMap prev_insts;
35+
36+
37+static void ValidateInstPath(HWND hdlg, const std::string& path)
38+{
39+ int valid = 0;
40+ if (path.length() > 0)
41+ {
42+ size_t i = path.find_last_of("/\\", path.length() - 2);
43+ if (path[1] == ':' && i != std::string::npos)
44+ {
45+ std::string pdir = (i >= 4) ? path.substr(0, i) : path.substr(0, i + 1);
46+ struct _stat st;
47+ if (_stat(pdir.c_str(), &st) == 0
48+ && _S_ISDIR(st.st_mode))
49+ {
50+ std::string dpath = path;
51+ if (dpath[dpath.length() - 1] == '/'
52+ || dpath[dpath.length() - 1] == '\\')
53+ dpath.erase(dpath.length() - 1);
54+ if (_stat(dpath.c_str(), &st) == 0)
55+ {
56+ if (_S_ISDIR(st.st_mode))
57+ {
58+ if (_stat((dpath + "\\mingwpkg.mft").c_str(),
59+ &st) == 0)
60+ {
61+ valid = 1;
62+ g_createinst = FALSE;
63+ Static_SetText(GetDlgItem(hdlg, IDC_VALTEXT),
64+ "This is an existing installation");
65+ Button_SetCheck(GetDlgItem(hdlg, IDC_EXISTMANAGE),
66+ BST_CHECKED);
67+ EnableWindow(GetDlgItem(hdlg, IDC_PREVINSTLIST),
68+ TRUE);
69+ InstIndexMap::iterator found =
70+ prev_insts.find(dpath);
71+ if (found != prev_insts.end())
72+ {
73+ (void)ListBox_SetCurSel(
74+ GetDlgItem(hdlg, IDC_PREVINSTLIST),
75+ found->second
76+ );
77+ }
78+ else
79+ {
80+ (void)ListBox_SetCurSel(
81+ GetDlgItem(hdlg, IDC_PREVINSTLIST), -1
82+ );
83+ }
84+ }
85+ else
86+ {
87+ valid = 1;
88+ g_createinst = TRUE;
89+ Button_SetCheck(GetDlgItem(hdlg, IDC_EXISTMANAGE),
90+ BST_UNCHECKED);
91+ EnableWindow(GetDlgItem(hdlg, IDC_PREVINSTLIST),
92+ FALSE);
93+ Static_SetText(GetDlgItem(hdlg, IDC_VALTEXT),
94+ "This path exists");
95+ }
96+ }
97+ else
98+ {
99+ Static_SetText(GetDlgItem(hdlg, IDC_VALTEXT),
100+ "This path is not a directory");
101+ }
102+ }
103+ else
104+ {
105+ valid = 1;
106+ g_createinst = TRUE;
107+ Button_SetCheck(GetDlgItem(hdlg, IDC_EXISTMANAGE),
108+ BST_UNCHECKED);
109+ EnableWindow(GetDlgItem(hdlg, IDC_PREVINSTLIST), FALSE);
110+ Static_SetText(GetDlgItem(hdlg, IDC_VALTEXT),
111+ "This directory will be created");
112+ }
113+ }
114+ else
115+ {
116+ Static_SetText(GetDlgItem(hdlg, IDC_VALTEXT),
117+ "The parent directory doesn't exist");
118+ }
119+ }
120+ else
121+ {
122+ Static_SetText(GetDlgItem(hdlg, IDC_VALTEXT),
123+ "Not a valid installation path");
124+ }
125+ }
126+ else
127+ {
128+ Static_SetText(GetDlgItem(hdlg, IDC_VALTEXT),
129+ "Please enter an installation path");
130+ }
131+ EnableWindow(GetDlgItem(hdlg, IDOK), valid ? TRUE : FALSE);
132+}
133+
134+
135+extern "C" int GetPrevInstalls(void (*)(const char*));
136+
137+extern "C" void PrevInstCallback(const char* path)
138+{
139+ int index = ListBox_AddString(GetDlgItem(g_hdlg, IDC_PREVINSTLIST), path);
140+ prev_insts[path] = index;
141+}
142+
143+static int CALLBACK InstBrowseProc
144+ (HWND hwnd,
145+ UINT uMsg,
146+ LPARAM lParam,
147+ LPARAM lpData)
148+{
149+ if (uMsg == BFFM_INITIALIZED)
150+ SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData);
151+ return 0;
152+}
153+
154+static BOOL CALLBACK InstSelProc
155+ (HWND hwndDlg,
156+ UINT uMsg,
157+ WPARAM wParam,
158+ LPARAM lParam)
159+{
160+ switch(uMsg)
161+ {
162+ case WM_INITDIALOG:
163+ {
164+ g_hdlg = hwndDlg;
165+ if (!g_inst_loc[0])
166+ strcpy(g_inst_loc, "C:\\mingwgettest");
167+ if (GetPrevInstalls(PrevInstCallback) > 0)
168+ {
169+ SendMessage(GetDlgItem(hwndDlg, IDC_PREVINSTLIST), LB_SETCURSEL,
170+ 0, 0);
171+ SendMessage(hwndDlg, WM_COMMAND,
172+ MAKEWPARAM(IDC_PREVINSTLIST, LBN_SELCHANGE),
173+ (LPARAM)GetDlgItem(hwndDlg, IDC_PREVINSTLIST));
174+ EnableWindow(GetDlgItem(hwndDlg, IDC_PREVINSTLIST), TRUE);
175+ }
176+ else
177+ {
178+ EnableWindow(GetDlgItem(hwndDlg, IDC_PREVINSTLIST), FALSE);
179+ EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
180+ Edit_SetText(GetDlgItem(hwndDlg, IDC_INSTPATH), g_inst_loc);
181+ }
182+ SetFocus(GetDlgItem(hwndDlg, IDC_INSTPATH));
183+ }
184+ return FALSE;
185+
186+ case WM_COMMAND:
187+ switch(LOWORD(wParam))
188+ {
189+ case IDOK:
190+ {
191+ g_inst_loc[0] = 0;
192+ Edit_GetText(GetDlgItem(hwndDlg, IDC_INSTPATH), g_inst_loc,
193+ MAX_PATH);
194+ EndDialog(hwndDlg, 1);
195+ }
196+ return TRUE;
197+ case IDCANCEL:
198+ EndDialog(hwndDlg, 0);
199+ return TRUE;
200+ case IDC_EXISTMANAGE:
201+ EnableWindow(GetDlgItem(hwndDlg, IDC_PREVINSTLIST),
202+ Button_GetCheck((HWND)lParam) == BST_CHECKED);
203+ return TRUE;
204+ case IDC_BROWSENEWINST:
205+ {
206+ char path[MAX_PATH];
207+ path[0] = 0;
208+ Edit_GetText(GetDlgItem(hwndDlg, IDC_INSTPATH), path, MAX_PATH);
209+ if (!path[0])
210+ strcpy(path, "C:\\");
211+ BROWSEINFO bi;
212+ bi.hwndOwner = hwndDlg;
213+ bi.pidlRoot = 0;
214+ bi.pszDisplayName = 0;
215+ bi.lpszTitle = "Select a Folder";
216+ bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
217+ bi.lpfn = InstBrowseProc;
218+ bi.lParam = reinterpret_cast< LPARAM >(path);
219+ bi.iImage = 0;
220+ LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
221+ if (pidl)
222+ {
223+ char cpath[MAX_PATH];
224+ if (SHGetPathFromIDList(pidl, cpath))
225+ {
226+ std::string path = cpath;
227+ if (path.length() < 5
228+ || stricmp(path.c_str() + path.length() - 5, "mingw")
229+ != 0)
230+ {
231+ if (path[path.length() - 1] != '\\')
232+ path += '\\';
233+ Edit_SetText(GetDlgItem(hwndDlg, IDC_INSTPATH),
234+ (path + "MinGW").c_str());
235+ }
236+ else
237+ {
238+ Edit_SetText(GetDlgItem(hwndDlg, IDC_INSTPATH),
239+ path.c_str());
240+ }
241+ }
242+ CoTaskMemFree(pidl);
243+ }
244+ }
245+ return TRUE;
246+ case IDC_INSTPATH:
247+ if (HIWORD(wParam) == EN_CHANGE)
248+ {
249+ char path[MAX_PATH];
250+ path[0] = 0;
251+ Edit_GetText((HWND)lParam, path, MAX_PATH);
252+ ValidateInstPath(hwndDlg, path);
253+ return TRUE;
254+ }
255+ break;
256+ case IDC_PREVINSTLIST:
257+ if (HIWORD(wParam) == LBN_SELCHANGE)
258+ {
259+ int sel = ListBox_GetCurSel((HWND)lParam);
260+ int len = ListBox_GetTextLen((HWND)lParam, sel);
261+ char* txt = (char*)malloc(len + 1);
262+ if (ListBox_GetText((HWND)lParam, sel, txt) > 0)
263+ Edit_SetText(GetDlgItem(hwndDlg, IDC_INSTPATH), txt);
264+ free(txt);
265+ return TRUE;
266+ }
267+ break;
268+ }
269+ break;
270+
271+ case WM_CLOSE:
272+ EndDialog(hwndDlg, 0);
273+ return TRUE;
274+ }
275+
276+ return FALSE;
277+}
278+
279+
280+extern "C" void LastError_MsgBox(const char*);
281+
282+extern "C" void SelectInstallation()
283+{
284+ if (!DialogBox(g_hinstance, MAKEINTRESOURCE(IDD_INSTSEL), g_hmainwnd,
285+ InstSelProc) || !g_inst_loc[0])
286+ return;
287+ if (!PkgIndex::SetInstallation(g_inst_loc))
288+ {
289+ LastError_MsgBox("Installation Failure");
290+ return;
291+ }
292+ char title[1024];
293+ snprintf(title, 1024, "mingw-get: %s", g_inst_loc);
294+ SetWindowText(g_hmainwnd, title);
295+}
--- a/tracked_install.hpp
+++ b/tracked_install.hpp
@@ -30,7 +30,7 @@ public:
3030 return change.Revert();
3131 }
3232
33- TCHolderBase* Clone() const
33+ virtual TCHolderBase* Clone() const
3434 {
3535 return new TCHolder< T >(change);
3636 }
--- a/ui.cpp
+++ b/ui.cpp
@@ -10,9 +10,13 @@
1010 #include <commctrl.h>
1111 #include <climits>
1212 #include "package.hpp"
13-#include "pkg_index.hpp"
13+#include "pkgindex.hpp"
1414 #include "pkg_const.h"
1515 #include "resource.h"
16+#include "error.hh"
17+
18+
19+extern HWND g_hmainwnd;
1620
1721
1822 static void LVAddPackage(HWND hlist, const Package& pkg)
@@ -220,27 +224,23 @@ extern "C" void UI_SortListView(int column, HWND hmainwnd)
220224 }
221225
222226
223-#if 0
224-void UI::ResetLists()
227+void UI_RefreshCategoryList()
225228 {
226229 ListBox_SetCurSel(GetDlgItem(g_hmainwnd, IDC_CATLIST), 0);
227230 int ct = ListBox_GetCount(GetDlgItem(g_hmainwnd, IDC_CATLIST));
228231 for (; ct > 1; --ct)
229232 ListBox_DeleteString(GetDlgItem(g_hmainwnd, IDC_CATLIST), ct - 1);
230233 ListView_DeleteAllItems(GetDlgItem(g_hmainwnd, IDC_COMPLIST));
234+ for (int i = 0; i < PkgIndex::NumCategories(); ++i)
235+ {
236+ ListBox_AddString(GetDlgItem(g_hmainwnd, IDC_CATLIST),
237+ PkgIndex::GetCategory(i));
238+ }
239+ UI_OnCategoryChange(0, g_hmainwnd);
231240 }
232241
233242
234-void UI::NotifyNewCategory(const char* name)
235-{
236- ListBox_AddString(GetDlgItem(g_hmainwnd, IDC_CATLIST), name);
237-}
238-
239-
240-void UI::NotifyNewPackage(const Package& pkg)
243+extern "C" void LastError_MsgBox(const char* title)
241244 {
242- int sel = ListBox_GetCurSel(GetDlgItem(g_hmainwnd, IDC_CATLIST));
243- if (sel <= 0 || pkg.m_categories.count(sel - 1) > 0)
244- LVAddPackage(pkg);
245+ MessageBox(g_hmainwnd, MGLastError(), title, MB_OK | MB_ICONERROR);
245246 }
246-#endif
--- /dev/null
+++ b/versioncompare.c
@@ -0,0 +1,44 @@
1+
2+#include <string.h>
3+
4+static int IsDigit(char ch)
5+{
6+ return (ch >= '0' && ch <= '9');
7+}
8+
9+int VersionCompare(const char* v1, const char* v2)
10+{
11+ static int at1, at2, num1, num2;
12+ at1 = 0, at2 = 0;
13+ while (v1[at1] && v2[at2])
14+ {
15+ if (v1[at1] != v2[at2])
16+ {
17+ if (IsDigit(v1[at1]) && IsDigit(v2[at2]))
18+ {
19+ num1 = 0;
20+ while (IsDigit(v1[at1]))
21+ {
22+ num1 = num1 * 10 + v1[at1] - '0';
23+ ++at1;
24+ }
25+ num2 = 0;
26+ while (IsDigit(v2[at2]))
27+ {
28+ num2 = num2 * 10 + v2[at2] - '0';
29+ ++at2;
30+ }
31+ if (num1 != num2)
32+ return num1 - num2;
33+ }
34+ else
35+ return v1[at1] - v2[at2];
36+ }
37+ else
38+ {
39+ ++at1;
40+ ++at2;
41+ }
42+ }
43+ return v1[at1] - v2[at2];
44+}
--- /dev/null
+++ b/winmain.cpp
@@ -0,0 +1,37 @@
1+
2+#define WIN32_LEAN_AND_MEAN
3+#include <windows.h>
4+#include <string>
5+#include "pkgindex.hpp"
6+#include <curl/curl.h>
7+
8+
9+extern "C" int CreateMainWnd();
10+extern "C" int MainMessageLoop();
11+extern "C" void SelectInstallation();
12+void UI_RefreshCategoryList();
13+
14+
15+HINSTANCE g_hinstance;
16+
17+
18+int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
19+{
20+ g_hinstance = hInstance;
21+
22+ curl_global_init(CURL_GLOBAL_ALL);
23+
24+ if (!CreateMainWnd())
25+ return 1;
26+
27+ PkgIndex::LoadIndex();
28+ UI_RefreshCategoryList();
29+
30+ SelectInstallation();
31+
32+ int ret = MainMessageLoop();
33+
34+ curl_global_cleanup();
35+
36+ return ret;
37+}