The MinGW.org Installation Manager Tool
Révision | 2990b9141d2c350af690ee1f40dc4a72e4d18932 (tree) |
---|---|
l'heure | 2008-11-02 09:13:49 |
Auteur | John E. <tdragon@user...> |
Commiter | John E. |
UI/functionality separation made more distinct
@@ -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 | +} |
@@ -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 | +} |
@@ -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 |
@@ -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 | +} |
@@ -9,10 +9,14 @@ | ||
9 | 9 | #include "pkg_const.h" |
10 | 10 | |
11 | 11 | |
12 | +extern HINSTANCE g_hinstance; | |
13 | + | |
14 | + | |
15 | +HWND g_hmainwnd = 0; | |
16 | + | |
12 | 17 | static int g_vert_grip_x = 150; |
13 | 18 | static float g_horz_grip_prop = 0.5f; |
14 | 19 | static HACCEL g_haccel; |
15 | -static HINSTANCE g_instance = 0; | |
16 | 20 | |
17 | 21 | |
18 | 22 | void TransToClient(HWND hwnd, RECT* rc) |
@@ -31,27 +35,27 @@ void TransToClient(HWND hwnd, RECT* rc) | ||
31 | 35 | } |
32 | 36 | |
33 | 37 | |
34 | -void NewVertSashPos(int pos, HWND mainwnd) | |
38 | +void NewVertSashPos(int pos) | |
35 | 39 | { |
36 | 40 | g_vert_grip_x = pos; |
37 | 41 | 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, | |
40 | 44 | MAKELPARAM(rc.right - rc.left, rc.bottom - rc.top)); |
41 | 45 | } |
42 | 46 | |
43 | 47 | |
44 | -void NewHorzSashPos(int pos, HWND mainwnd) | |
48 | +void NewHorzSashPos(int pos) | |
45 | 49 | { |
46 | 50 | 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); | |
52 | 56 | g_horz_grip_prop = (float)(pos - (tbrc.bottom - tbrc.top) - 6) / |
53 | 57 | ((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, | |
55 | 59 | MAKELPARAM(rc.right - rc.left, rc.bottom - rc.top)); |
56 | 60 | } |
57 | 61 |
@@ -88,7 +92,7 @@ static void InsertColumn | ||
88 | 92 | } |
89 | 93 | |
90 | 94 | |
91 | -void SelectInst(HINSTANCE, HWND); | |
95 | +void SelectInstallation(); | |
92 | 96 | const char* Pkg_GetSubItemText(LPARAM, int); |
93 | 97 | void UI_OnCategoryChange(int, HWND); |
94 | 98 | void UI_SortListView(int, HWND); |
@@ -99,6 +103,8 @@ const char* Pkg_GetInstalledVersion(LPARAM); | ||
99 | 103 | int Pkg_GetSelectedAction(LPARAM); |
100 | 104 | void Pkg_SelectAction(LPARAM, int); |
101 | 105 | int Pkg_GetStateImage(LPARAM); |
106 | +int PkgIndex_DownloadUpdate(); | |
107 | +void LastError_MsgBox(const char*); | |
102 | 108 | |
103 | 109 | static BOOL CALLBACK MainWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) |
104 | 110 | { |
@@ -117,16 +123,16 @@ static BOOL CALLBACK MainWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM | ||
117 | 123 | HIMAGELIST il = |
118 | 124 | ImageList_Create(24, 24, ILC_COLOR32 | ILC_MASK, 6, 0); |
119 | 125 | HBITMAP tbbuttons = |
120 | - LoadBitmap(g_instance, MAKEINTRESOURCE(IDB_TBBUTTONS)); | |
126 | + LoadBitmap(g_hinstance, MAKEINTRESOURCE(IDB_TBBUTTONS)); | |
121 | 127 | ImageList_AddMasked(il, tbbuttons, RGB(255, 0, 255)); |
122 | 128 | DeleteObject(tbbuttons); |
123 | 129 | SendMessage(htb, TB_SETIMAGELIST, (WPARAM)0, (LPARAM)il); |
124 | 130 | TBBUTTON tbButtons[3] = { |
125 | - { 0, -1, TBSTATE_ENABLED, | |
131 | + { 0, -1, TBSTATE_ENABLED, | |
126 | 132 | TBSTYLE_BUTTON|TBSTYLE_AUTOSIZE, {0}, 0, (INT_PTR)"Update Lists" }, |
127 | - { 1, -1, TBSTATE_ENABLED, | |
133 | + { 1, -1, TBSTATE_ENABLED, | |
128 | 134 | TBSTYLE_BUTTON|TBSTYLE_AUTOSIZE, {0}, 0, (INT_PTR)"Mark All Upgrades"}, |
129 | - { 2, -1, 0, | |
135 | + { 2, -1, 0, | |
130 | 136 | TBSTYLE_BUTTON|TBSTYLE_AUTOSIZE, {0}, 0, (INT_PTR)"Apply"} |
131 | 137 | }; |
132 | 138 | SendMessage(htb, TB_BUTTONSTRUCTSIZE, |
@@ -151,7 +157,7 @@ static BOOL CALLBACK MainWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM | ||
151 | 157 | LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP); |
152 | 158 | il = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 10, 0); |
153 | 159 | HBITMAP buttonsbmp = |
154 | - LoadBitmap(g_instance, MAKEINTRESOURCE(IDB_STATES)); | |
160 | + LoadBitmap(g_hinstance, MAKEINTRESOURCE(IDB_STATES)); | |
155 | 161 | ImageList_AddMasked(il, buttonsbmp, RGB(255, 0, 255)); |
156 | 162 | DeleteObject(buttonsbmp); |
157 | 163 | (void)ListView_SetImageList(hlv, il, LVSIL_SMALL); |
@@ -192,7 +198,11 @@ static BOOL CALLBACK MainWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM | ||
192 | 198 | PostQuitMessage(0); |
193 | 199 | return TRUE; |
194 | 200 | 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"); | |
196 | 206 | return TRUE; |
197 | 207 | case IDC_CATLIST: |
198 | 208 | if (HIWORD(wParam) == LBN_SELCHANGE) |
@@ -419,29 +429,35 @@ static int ProcessQueuedMessages(HWND wnd) | ||
419 | 429 | } |
420 | 430 | |
421 | 431 | |
422 | -int SashWnd_RegisterClasses(HINSTANCE); | |
432 | +int SashWnd_RegisterClasses(); | |
423 | 433 | |
424 | -HWND CreateMainWnd(HINSTANCE hInstance) | |
434 | +int CreateMainWnd() | |
425 | 435 | { |
426 | - g_instance = hInstance; | |
427 | - | |
428 | 436 | InitCommonControls(); |
429 | 437 | OleInitialize(0); |
430 | 438 | |
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); | |
432 | 443 | return 0; |
444 | + } | |
433 | 445 | |
434 | - g_haccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDA_MAINACCEL)); | |
446 | + g_haccel = LoadAccelerators(g_hinstance, MAKEINTRESOURCE(IDA_MAINACCEL)); | |
435 | 447 | |
436 | - HWND wnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_MAINDLG), 0, | |
448 | + HWND wnd = CreateDialog(g_hinstance, MAKEINTRESOURCE(IDD_MAINDLG), 0, | |
437 | 449 | MainWndProc); |
438 | 450 | if (!wnd) |
451 | + { | |
452 | + MessageBox(0, "Couldn't create the main window.", "Windowing Failure", | |
453 | + MB_OK | MB_ICONERROR); | |
439 | 454 | return 0; |
455 | + } | |
440 | 456 | ShowWindow(wnd, SW_SHOW); |
441 | 457 | if (ProcessQueuedMessages(wnd)) |
442 | 458 | return 0; |
443 | 459 | |
444 | - return wnd; | |
460 | + return 1; | |
445 | 461 | } |
446 | 462 | |
447 | 463 |
@@ -54,17 +54,16 @@ | ||
54 | 54 | <Add directory="$(#zlib)" /> |
55 | 55 | </Linker> |
56 | 56 | <Unit filename="TODO.txt" /> |
57 | - <Unit filename="curl_init.cpp" /> | |
58 | - <Unit filename="download.cpp"> | |
57 | + <Unit filename="download.c"> | |
59 | 58 | <Option compilerVar="CC" /> |
60 | 59 | </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"> | |
65 | 65 | <Option compilerVar="CC" /> |
66 | 66 | </Unit> |
67 | - <Unit filename="main.cpp" /> | |
68 | 67 | <Unit filename="mainwnd.c"> |
69 | 68 | <Option compilerVar="CC" /> |
70 | 69 | </Unit> |
@@ -76,8 +75,8 @@ | ||
76 | 75 | <Unit filename="package.cpp" /> |
77 | 76 | <Unit filename="package.hpp" /> |
78 | 77 | <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" /> | |
81 | 80 | <Unit filename="previnstalls.c"> |
82 | 81 | <Option compilerVar="CC" /> |
83 | 82 | </Unit> |
@@ -89,6 +88,9 @@ | ||
89 | 88 | <Unit filename="sash_wnd.c"> |
90 | 89 | <Option compilerVar="CC" /> |
91 | 90 | </Unit> |
91 | + <Unit filename="selectinst.cpp"> | |
92 | + <Option compilerVar="CC" /> | |
93 | + </Unit> | |
92 | 94 | <Unit filename="tinyxml\MODIFIED_TINYXML.txt" /> |
93 | 95 | <Unit filename="tinyxml\tinystr.cpp" /> |
94 | 96 | <Unit filename="tinyxml\tinystr.h" /> |
@@ -99,9 +101,10 @@ | ||
99 | 101 | <Unit filename="tracked_install.cpp" /> |
100 | 102 | <Unit filename="tracked_install.hpp" /> |
101 | 103 | <Unit filename="ui.cpp" /> |
102 | - <Unit filename="versioning.c"> | |
104 | + <Unit filename="versioncompare.c"> | |
103 | 105 | <Option compilerVar="CC" /> |
104 | 106 | </Unit> |
107 | + <Unit filename="winmain.cpp" /> | |
105 | 108 | <Extensions> |
106 | 109 | <code_completion /> |
107 | 110 | <debugger /> |
@@ -3,7 +3,7 @@ | ||
3 | 3 | |
4 | 4 | #define WIN32_LEAN_AND_MEAN |
5 | 5 | #include <windows.h> |
6 | -#include "pkg_index.hpp" | |
6 | +#include "pkgindex.hpp" | |
7 | 7 | #include "pkg_const.h" |
8 | 8 | |
9 | 9 |
@@ -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 | +} |
@@ -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 |
@@ -44,11 +44,8 @@ static int GetPrevInstByFolder(int folder, void (*callback)(const char*)) | ||
44 | 44 | |
45 | 45 | int GetPrevInstalls(void (*callback)(const char*)) |
46 | 46 | { |
47 | - int utype = GetAccountTypeHelper(); | |
48 | - if (utype < 0) | |
49 | - return 0; | |
50 | 47 | int icount = GetPrevInstByFolder(CSIDL_APPDATA, callback); |
51 | - if (utype >= MU_POWER) | |
48 | + if (GetAccountTypeHelper() >= MU_POWER) | |
52 | 49 | icount += GetPrevInstByFolder(CSIDL_COMMON_APPDATA, callback); |
53 | 50 | return icount; |
54 | 51 | } |
@@ -38,4 +38,5 @@ | ||
38 | 38 | #define IDM_FILE_EXIT 1201 |
39 | 39 | #define IDM_FILE_CHANGEINST 1202 |
40 | 40 | #define IDM_EDIT_PREFERENCES 1203 |
41 | -#define IDM_SOURCES_MIRRORS 1204 | |
41 | +#define IDM_SOURCES_UPDATELISTS 1204 | |
42 | +#define IDM_SOURCES_MIRRORS 1205 |
@@ -19,6 +19,7 @@ IDA_MAINACCEL ACCELERATORS | ||
19 | 19 | BEGIN |
20 | 20 | "I", IDM_FILE_CHANGEINST, CONTROL, ALT, VIRTKEY |
21 | 21 | "P", IDM_EDIT_PREFERENCES, CONTROL, VIRTKEY |
22 | + "U", IDM_SOURCES_UPDATELISTS, CONTROL, VIRTKEY | |
22 | 23 | "M", IDM_SOURCES_MIRRORS, CONTROL, VIRTKEY |
23 | 24 | END |
24 | 25 |
@@ -36,6 +37,7 @@ BEGIN | ||
36 | 37 | END |
37 | 38 | POPUP "Sour&ces" |
38 | 39 | BEGIN |
40 | + MENUITEM "&Update Lists\tCtrl+U", IDM_SOURCES_UPDATELISTS | |
39 | 41 | MENUITEM "&Mirrors...\tCtrl+M", IDM_SOURCES_MIRRORS |
40 | 42 | END |
41 | 43 | END |
@@ -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 | +} |
@@ -30,7 +30,7 @@ public: | ||
30 | 30 | return change.Revert(); |
31 | 31 | } |
32 | 32 | |
33 | - TCHolderBase* Clone() const | |
33 | + virtual TCHolderBase* Clone() const | |
34 | 34 | { |
35 | 35 | return new TCHolder< T >(change); |
36 | 36 | } |
@@ -10,9 +10,13 @@ | ||
10 | 10 | #include <commctrl.h> |
11 | 11 | #include <climits> |
12 | 12 | #include "package.hpp" |
13 | -#include "pkg_index.hpp" | |
13 | +#include "pkgindex.hpp" | |
14 | 14 | #include "pkg_const.h" |
15 | 15 | #include "resource.h" |
16 | +#include "error.hh" | |
17 | + | |
18 | + | |
19 | +extern HWND g_hmainwnd; | |
16 | 20 | |
17 | 21 | |
18 | 22 | static void LVAddPackage(HWND hlist, const Package& pkg) |
@@ -220,27 +224,23 @@ extern "C" void UI_SortListView(int column, HWND hmainwnd) | ||
220 | 224 | } |
221 | 225 | |
222 | 226 | |
223 | -#if 0 | |
224 | -void UI::ResetLists() | |
227 | +void UI_RefreshCategoryList() | |
225 | 228 | { |
226 | 229 | ListBox_SetCurSel(GetDlgItem(g_hmainwnd, IDC_CATLIST), 0); |
227 | 230 | int ct = ListBox_GetCount(GetDlgItem(g_hmainwnd, IDC_CATLIST)); |
228 | 231 | for (; ct > 1; --ct) |
229 | 232 | ListBox_DeleteString(GetDlgItem(g_hmainwnd, IDC_CATLIST), ct - 1); |
230 | 233 | 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); | |
231 | 240 | } |
232 | 241 | |
233 | 242 | |
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) | |
241 | 244 | { |
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); | |
245 | 246 | } |
246 | -#endif |
@@ -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 | +} |
@@ -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 | +} |