summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Werkema <sean@werkema.com>2020-06-23 09:43:05 -0400
committerSean Werkema <sean@werkema.com>2020-06-23 09:43:05 -0400
commit4d0596a2530134383f231b2c7d22be6fa8c6a846 (patch)
tree538482a55afb3ee2bf4623a1ede59b7bbbcecd3f
Initial import into version control.v1.4
-rw-r--r--AboutDialog.cpp34
-rw-r--r--AboutDialog.h15
-rw-r--r--DriveDialog.cpp136
-rw-r--r--DriveDialog.h34
-rw-r--r--E.H30
-rw-r--r--FolderTree.cpp644
-rw-r--r--FolderTree.h122
-rw-r--r--FolderView.cpp1131
-rw-r--r--FolderView.h101
-rw-r--r--Freedoc.cpp122
-rw-r--r--Freeview.cpp74
-rw-r--r--Mainfrm.cpp281
-rw-r--r--Mainfrm.h59
-rw-r--r--README.TXT185
-rw-r--r--SetupDlg.cpp310
-rw-r--r--SetupDlg.h32
-rw-r--r--SpaceMonger.cpp527
-rw-r--r--SpaceMonger.dsp249
-rw-r--r--SpaceMonger.dsw29
-rw-r--r--SpaceMonger.h90
-rw-r--r--SpaceMonger.ncbbin0 -> 99328 bytes
-rw-r--r--SpaceMonger.optbin0 -> 48640 bytes
-rw-r--r--SpaceMonger.rc330
-rw-r--r--StdAfx.cpp5
-rw-r--r--Stdafx.h25
-rw-r--r--TipWnd.cpp789
-rw-r--r--TipWnd.h203
-rw-r--r--lang.h51
-rw-r--r--lang_en.cpp109
-rw-r--r--lang_fr.cpp58
-rw-r--r--res/SpaceMonger.icobin0 -> 1398 bytes
-rw-r--r--res/scan1.bmpbin0 -> 3190 bytes
-rw-r--r--res/scan2.bmpbin0 -> 3190 bytes
-rw-r--r--res/scan3.bmpbin0 -> 3190 bytes
-rw-r--r--res/scan4.bmpbin0 -> 3190 bytes
-rw-r--r--res/toolbar_en.bmpbin0 -> 3418 bytes
-rw-r--r--res/toolbar_fr.bmpbin0 -> 3418 bytes
-rw-r--r--resource.h99
-rw-r--r--xapp.h248
39 files changed, 6122 insertions, 0 deletions
diff --git a/AboutDialog.cpp b/AboutDialog.cpp
new file mode 100644
index 0000000..d180f61
--- /dev/null
+++ b/AboutDialog.cpp
@@ -0,0 +1,34 @@
1
2#include "stdafx.h"
3#include "spacemonger.h"
4#include "AboutDialog.h"
5#include "Lang.h"
6
7#ifdef _DEBUG
8#define new DEBUG_NEW
9#undef THIS_FILE
10static char THIS_FILE[] = __FILE__;
11#endif
12
13CAboutDialog::CAboutDialog(CWnd* pParent)
14 : CDialog(IDD_ABOUT, pParent)
15{
16}
17
18BEGIN_MESSAGE_MAP(CAboutDialog, CDialog)
19 //{{AFX_MSG_MAP(CAboutDialog)
20 //}}AFX_MSG_MAP
21END_MESSAGE_MAP()
22
23BOOL CAboutDialog::OnInitDialog()
24{
25 CDialog::OnInitDialog();
26
27 SetWindowText(CurLang->about_spacemonger);
28 SetDlgItemText(IDC_STATIC_FREEWARE, CurLang->freeware);
29 SetDlgItemText(IDC_STATIC_WARRANTY, CurLang->warranty);
30 SetDlgItemText(IDC_STATIC_EMAIL, CurLang->email);
31 SetDlgItemText(IDOK, CurLang->ok);
32
33 return TRUE;
34}
diff --git a/AboutDialog.h b/AboutDialog.h
new file mode 100644
index 0000000..f1f9e59
--- /dev/null
+++ b/AboutDialog.h
@@ -0,0 +1,15 @@
1#ifndef ABOUTDIALOG_H
2#define ABOUTDIALOG_H
3
4class CAboutDialog : public CDialog {
5public:
6 CAboutDialog(CWnd* pParent = NULL);
7
8protected:
9 //{{AFX_MSG(CAboutDialog)
10 virtual BOOL OnInitDialog();
11 //}}AFX_MSG
12 DECLARE_MESSAGE_MAP()
13};
14
15#endif
diff --git a/DriveDialog.cpp b/DriveDialog.cpp
new file mode 100644
index 0000000..8d1132d
--- /dev/null
+++ b/DriveDialog.cpp
@@ -0,0 +1,136 @@
1#include "stdafx.h"
2#include "spacemonger.h"
3#include "DriveDialog.h"
4#include "Lang.h"
5
6CDriveDialog::CDriveDialog(CWnd* pParent)
7 : CDialog(IDD_OPEN_DIALOG, pParent)
8{
9}
10
11BEGIN_MESSAGE_MAP(CDriveDialog, CDialog)
12 //{{AFX_MSG_MAP(CDriveDialog)
13 ON_NOTIFY(NM_DBLCLK, IDC_DRIVE_LIST, OnDriveDblClk)
14 //}}AFX_MSG_MAP
15END_MESSAGE_MAP()
16
17void CDriveDialog::OnDriveDblClk(NMHDR *pNotifyStruct, LRESULT *result)
18{
19 CListCtrl *lc = (CListCtrl *)GetDlgItem(IDC_DRIVE_LIST);
20 if (lc == NULL) return;
21 if (lc->GetSelectedCount() != 1) return;
22
23 int i, max = lc->GetItemCount();
24 for (i = 0; i < max; i++) {
25 if (lc->GetItemState(i, LVIS_SELECTED)) {
26 EndDialog(lc->GetItemData(i));
27 }
28 }
29}
30
31void CDriveDialog::OnOK()
32{
33 CListCtrl *lc = (CListCtrl *)GetDlgItem(IDC_DRIVE_LIST);
34 if (lc == NULL) EndDialog(-1);
35 if (lc->GetSelectedCount() != 1) return;
36
37 int i, max = lc->GetItemCount();
38 for (i = 0; i < max; i++) {
39 if (lc->GetItemState(i, LVIS_SELECTED)) {
40 EndDialog(lc->GetItemData(i));
41 }
42 }
43}
44
45void CDriveDialog::OnCancel()
46{
47 EndDialog(-1);
48}
49
50BOOL CDriveDialog::OnInitDialog()
51{
52 CWaitCursor wait;
53
54 CDialog::OnInitDialog();
55
56 CDriveInfo driveinfo[26];
57 HIMAGELIST imagelist;
58 int i, index;
59 LV_ITEM item;
60
61 imagelist = ImageList_Create(32, 32, TRUE, 0, 26);
62
63 CListCtrl *lc = (CListCtrl *)GetDlgItem(IDC_DRIVE_LIST);
64 ::SendMessage(lc->m_hWnd, LVM_SETIMAGELIST, (WPARAM)LVSIL_NORMAL, (LPARAM)(HIMAGELIST)imagelist);
65
66 SetWindowText(CurLang->selectdrive);
67 SetDlgItemText(IDOK, CurLang->ok);
68 SetDlgItemText(IDCANCEL, CurLang->cancel);
69
70 lc->InsertColumn(0, "Name");
71 if (lc != NULL) {
72 lc->SetItemCount(26);
73 index = 0;
74 for (i = 'A'; i <= 'Z'; i++) {
75 driveinfo[i-'A'].LoadDriveInfo(i);
76 if (driveinfo[i-'A'].avail) {
77 ImageList_AddIcon(imagelist, driveinfo[i-'A'].icon);
78 item.mask = LVIF_STATE|LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM;
79 item.iItem = index;
80 item.iSubItem = 0;
81 item.state = 0;
82 item.stateMask = LVIS_SELECTED;
83 item.pszText = driveinfo[i-'A'].longname;
84 item.cchTextMax = strlen(driveinfo[i-'A'].longname);
85 item.iImage = index;
86 item.lParam = i - 'A';
87 ::SendMessage(lc->m_hWnd, LVM_INSERTITEM, (WPARAM)0, (LPARAM)(&item));
88 index++;
89 }
90 driveinfo[i-'A'].Free();
91 }
92 }
93
94 return TRUE;
95}
96
97//////////////////////////////////////////////////////////////////////////////
98
99void CDriveInfo::Free(void)
100{
101 if (longname != NULL) delete[] longname;
102}
103
104void CDriveInfo::LoadDriveInfo(char let)
105{
106 char name[8];
107 UINT type;
108
109 if (let >= 'a' && let <= 'z') let -= 32;
110 name[0] = let;
111 name[1] = ':';
112 name[2] = '\\';
113 name[3] = '\0';
114
115 type = GetDriveType(name);
116
117 if (type != 0 && type != 1) {
118 SHFILEINFO fileinfo;
119 memset(&fileinfo, sizeof(SHFILEINFO), 0);
120
121 SHGetFileInfo(name, 0, &fileinfo, sizeof(SHFILEINFO),
122 SHGFI_DISPLAYNAME|SHGFI_ICON);
123
124 avail = 1;
125 letter = let;
126 icon = fileinfo.hIcon;
127 longname = new char[strlen(fileinfo.szDisplayName)+1];
128 strcpy(longname, fileinfo.szDisplayName);
129 }
130 else {
131 avail = 0;
132 letter = let;
133 icon = NULL;
134 longname = NULL;
135 }
136}
diff --git a/DriveDialog.h b/DriveDialog.h
new file mode 100644
index 0000000..088d3a3
--- /dev/null
+++ b/DriveDialog.h
@@ -0,0 +1,34 @@
1
2#ifndef DRIVEDIALOG_H
3#define DRIVEDIALOG_H
4
5struct CDriveInfo {
6 void Free(void);
7 void LoadDriveInfo(char letter);
8
9 char letter;
10 BOOL avail;
11 HICON icon;
12 char *longname;
13};
14
15class CDriveDialog : public CDialog {
16public:
17 CDriveDialog(CWnd* pParent = NULL);
18
19 //{{AFX_VIRTUAL(CDriveDialog)
20 virtual void OnOK();
21 virtual void OnCancel();
22 //}}AFX_VIRTUAL
23
24protected:
25 //{{AFX_MSG(CDriveDialog)
26 afx_msg BOOL OnInitDialog();
27 afx_msg void OnDriveDblClk(NMHDR *pNotifyStruct, LRESULT *result);
28 //}}AFX_MSG
29 DECLARE_MESSAGE_MAP()
30
31 CDriveInfo *driveinfo;
32};
33
34#endif
diff --git a/E.H b/E.H
new file mode 100644
index 0000000..8aa41e9
--- /dev/null
+++ b/E.H
@@ -0,0 +1,30 @@
1
2#ifndef E_H
3#define E_H
4
5#define ui64 unsigned __int64
6#define si64 signed __int64
7#define ui32 unsigned long int
8#define si32 signed long int
9#define ui16 unsigned short int
10#define si16 signed short int
11#define ui8 unsigned char
12#define si8 signed char
13
14#define real32 float
15#define real64 double
16
17typedef short int sym;
18
19#define until(n) while (!(n))
20#define unless(n) if (!(n))
21
22#define true 1
23#define TRUE 1
24#define True 1
25#define false 0
26#define FALSE 0
27#define False 0
28
29#endif
30
diff --git a/FolderTree.cpp b/FolderTree.cpp
new file mode 100644
index 0000000..93c6254
--- /dev/null
+++ b/FolderTree.cpp
@@ -0,0 +1,644 @@
1
2#include "stdafx.h"
3#include "spacemonger.h"
4#include "FolderTree.h"
5#include "Lang.h"
6
7#include <io.h>
8#include <sys/types.h>
9#include <sys/stat.h>
10#include <errno.h>
11#include <winioctl.h>
12
13//////////////////////////////////////////////////////////////////////////////
14// Reparse points are utterly undocumented in Win2K, but can wreak havoc
15// in SpaceMonger. We try hard to deal with them anyway.
16
17#if (_WIN32_WINNT < 0x500)
18
19// Maximum reparse buffer info size. The max user defined reparse
20// data is 16KB, plus there's a header.
21//
22#define MAX_REPARSE_SIZE 17000
23
24// Undocumented FSCTL_SET_REPARSE_POINT structure definition
25#define REPARSE_MOUNTPOINT_HEADER_SIZE 8
26typedef struct {
27 DWORD ReparseTag;
28 DWORD ReparseDataLength;
29 WORD Reserved;
30 WORD ReparseTargetLength;
31 WORD ReparseTargetMaximumLength;
32 WORD Reserved1;
33 WCHAR ReparseTarget[1];
34} REPARSE_MOUNTPOINT_DATA_BUFFER, *PREPARSE_MOUNTPOINT_DATA_BUFFER;
35
36#define FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) // , REPARSE_DATA_BUFFER
37
38#endif
39
40//////////////////////////////////////////////////////////////////////////////
41
42CFolderTree::CFolderTree()
43{
44 root = cur = NULL;
45 freespace = usedspace = totalspace = 0;
46 m_path = "";
47}
48
49CFolderTree::~CFolderTree()
50{
51 if (root != NULL) delete root;
52}
53
54static void PseudoSleep(ui32 time)
55{
56 ui32 starttime = GetTickCount();
57 MSG msg;
58 while (GetTickCount() - starttime < time) {
59 while (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
60 ::TranslateMessage(&msg);
61 ::DispatchMessage(&msg);
62 }
63 }
64}
65
66BOOL CFolderTree::LoadTree(const CString &path, BOOL includespace, CWnd *modalwin)
67{
68 CFolderDialog dialog;
69
70 if (path == "") return 1;
71
72 dialog.Create(IDD_SCAN_DIALOG, modalwin);
73 dialog.Reset();
74
75 m_path = path;
76 GetSpace(path);
77 if (root != NULL) delete root;
78 root = new CFolder;
79 cur = root;
80 filespace = 0;
81
82 if (!root->LoadFolderInitial(this, path, clustersize, &dialog)) {
83 root->Finalize();
84 if (root != NULL) delete root;
85 root = cur = NULL;
86 freespace = usedspace = totalspace = 0;
87 m_path = "";
88 return 0;
89 }
90 else {
91 dialog.ForcedUpdate(this);
92 numfiles = dialog.numfiles;
93 numfolders = dialog.numfolders;
94 if (includespace)
95 root->AddFile(this, "<<<<<<<<<<<<<<<<<<<<", 1, freespace, freespace, 0);
96 root->Finalize();
97 ::PseudoSleep(1000);
98 modalwin->SetWindowPos(&CWnd::wndTop, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
99 return 1;
100 }
101}
102
103void CFolderTree::GetSpace(const CString &path)
104{
105 DWORD SecPerClus, BytesPerSec, ClusPerDisk, FreeClus;
106 ui64 oddfree, total, totalfree;
107
108 typedef BOOL (WINAPI *GetFreeDiskSpaceExFunc)(LPCTSTR pathname,
109 ui64 *oddfree, ui64 *total, ui64 *totalfree);
110
111 // First, compute the cluster size (which will be needed later)
112 GetDiskFreeSpace(path, &SecPerClus, &BytesPerSec, &FreeClus, &ClusPerDisk);
113 clustersize = (ui64)BytesPerSec * (ui64)SecPerClus;
114
115 // Next, load in Kernel32 and use GetDiskFreeSpaceEx to find out
116 // the size of the disk. If GetDiskFreeSpaceEx doesn't exist, then
117 // fall back on the values from GetDiskFreeSpace.
118 HINSTANCE hLibrary = LoadLibrary("KERNEL32.DLL");
119 GetFreeDiskSpaceExFunc getfreediskspaceex =
120 (GetFreeDiskSpaceExFunc)GetProcAddress(hLibrary, "GetDiskFreeSpaceExA");
121 if (hLibrary != NULL && getfreediskspaceex != NULL) {
122 getfreediskspaceex(path, &oddfree, &total, &totalfree);
123 freespace = totalfree;
124 totalspace = total;
125 }
126 else {
127 freespace = clustersize * (ui64)FreeClus;
128 totalspace = clustersize * (ui64)ClusPerDisk;
129 }
130 FreeLibrary(hLibrary);
131
132 usedspace = totalspace - freespace;
133}
134
135CFolder *CFolderTree::GetRoot(void)
136{
137 return(root);
138}
139
140CFolder *CFolderTree::SetCur(const CString &path)
141{
142 return(cur);
143}
144
145CFolder *CFolderTree::GetCur(void)
146{
147 return(cur);
148}
149
150CFolder *CFolderTree::Down(unsigned int index)
151{
152 if (index < cur->cur) {
153 CFolder *newfolder = cur->children[index];
154 if (newfolder != NULL) {
155 cur = newfolder;
156 return(cur);
157 }
158 }
159 return(NULL);
160}
161
162CFolder *CFolderTree::Up(void)
163{
164 if (cur != root) {
165 cur = cur->parent;
166 return(cur);
167 }
168 return(NULL);
169}
170
171//////////////////////////////////////////////////////////////////////////////
172
173static char *cpp_strdup(const char *string, int stringlen)
174{
175 char *newstr = (char *)malloc(stringlen+1 * sizeof(char));
176 if (newstr == NULL) return(NULL);
177
178 char *src;
179 char c;
180 BOOL allupper = 1;
181 src = newstr;
182 while (stringlen--) {
183 c = *src++ = *string++;
184 if (c >= 'a' && c <= 'z') allupper = 0;
185 }
186 *src = '\0';
187 if (allupper && src != newstr) {
188 src = newstr+1;
189 while ((c = *src) != '\0') {
190 if (c >= 'A' && c <= 'Z') *src += 32;
191 src++;
192 }
193 }
194
195 return(newstr);
196}
197
198CFolder::CFolder()
199{
200 cur = 0;
201 max = 2;
202 names = (char **)malloc(sizeof(char *) * max);
203 sizes = (ui64 *)malloc(sizeof(ui64) * max);
204 actualsizes = (ui64 *)malloc(sizeof(ui64) * max);
205 children = (CFolder **)malloc(sizeof(CFolder *) * max);
206 times = (ui64 *)malloc(sizeof(ui64) * max);
207 size_self = size_children = 0;
208 parent = NULL;
209 parentindex = 0;
210}
211
212CFolder::~CFolder()
213{
214 unsigned int i;
215
216 for (i = 0; i < cur; i++) {
217 if (names[i] != NULL) free(names[i]);
218 if (children[i] != NULL) delete children[i];
219 }
220
221 free(names);
222 free(children);
223 free(sizes);
224 free(actualsizes);
225 free(times);
226
227 cur = max = 0;
228 size_self = size_children = 0;
229 parent = NULL;
230 parentindex = 0;
231}
232
233void CFolder::MoreEntries(void)
234{
235 int newmax = max * 2;
236 char **newnames = (char **)malloc(sizeof(char *) * newmax);
237 ui64 *newsizes = (ui64 *)malloc(sizeof(ui64) * newmax);
238 ui64 *newactualsizes = (ui64 *)malloc(sizeof(ui64) * newmax);
239 ui64 *newtimes = (ui64 *)malloc(sizeof(ui64) * newmax);
240 CFolder **newkids = (CFolder **)malloc(sizeof(CFolder *) * newmax);
241
242 memcpy(newnames, names, max * sizeof(char *));
243 memcpy(newsizes, sizes, max * sizeof(ui64));
244 memcpy(newtimes, times, max * sizeof(ui64));
245 memcpy(newactualsizes, actualsizes, max * sizeof(ui64));
246 memcpy(newkids, children, max * sizeof(CFolder *));
247 free(names);
248 free(sizes);
249 free(times);
250 free(actualsizes);
251 free(children);
252 names = newnames;
253 sizes = newsizes;
254 times = newtimes;
255 actualsizes = newactualsizes;
256 children = newkids;
257
258 max = newmax;
259}
260
261void CFolder::AddFile(CFolderTree *tree, const char *name, ui32 namelen, ui64 size,
262 ui64 actual_size, ui64 time)
263{
264 if (cur >= max) MoreEntries();
265
266 names[cur] = cpp_strdup(name, namelen);
267 actualsizes[cur] = actual_size;
268 times[cur] = time;
269 size_self += (sizes[cur] = size);
270 children[cur] = NULL;
271 cur++;
272 tree->filespace += size;
273}
274
275void CFolder::AddFolder(CFolderTree *tree, const char *name, ui32 namelen, CFolder *folder,
276 ui64 time)
277{
278 if (cur >= max) MoreEntries();
279
280 names[cur] = cpp_strdup(name, namelen);
281 size_children += (sizes[cur] = folder->SizeTotal());
282 actualsizes[cur] = sizes[cur];
283 times[cur] = time;
284 children[cur] = folder;
285 folder->parent = this;
286 folder->parentindex = cur;
287 cur++;
288}
289
290// EightBitCountingSort
291// Performs an 8-bit counting sort on the given data. O(n).
292
293void CFolder::EightBitCountingSort(ui64 *dsize, ui64 *ssize, ui32 count, ui32 bitpos,
294 char **dnames, char **snames, CFolder **dkids, CFolder **skids,
295 ui64 *dasize, ui64 *sasize, ui64 *dtimes, ui64 *stimes)
296{
297 ui32 countarray[257];
298 ui32 i, dest;
299
300#define VALUE(size) (0xFF - (ui32)((size) >> bitpos) & 0xFF)
301
302 // Initially, zero offsets for each
303 for (i = 0; i < 256; i++)
304 countarray[i] = 0;
305
306 // Count how many of each value we have
307 for (i = 0; i < count; i++)
308 countarray[VALUE(ssize[i]) + 1]++;
309
310 // Create array offsets for each
311 for (i = 1; i < 256; i++)
312 countarray[i] += countarray[i-1];
313
314 // Now move them into place
315 for (i = 0; i < count; i++) {
316 dest = countarray[VALUE(ssize[i])]++;
317 dsize[dest] = ssize[i];
318 dnames[dest] = snames[i];
319 dkids[dest] = skids[i];
320 dasize[dest] = sasize[i];
321 dtimes[dest] = stimes[i];
322 if (dkids[dest] != NULL) dkids[dest]->parentindex = i;
323 }
324}
325
326// Finalize
327// Sorts the directory by file size. O(n)!
328
329void CFolder::Finalize(void)
330{
331 if (cur <= 1) return;
332
333 char **newnames = (char **)malloc(sizeof(char *) * cur);
334 ui64 *newsizes = (ui64 *)malloc(sizeof(ui64) * cur);
335 ui64 *newactualsizes = (ui64 *)malloc(sizeof(ui64) * cur);
336 CFolder **newkids = (CFolder **)malloc(sizeof(CFolder *) * cur);
337 ui64 *newtimes = (ui64 *)malloc(sizeof(ui64) * cur);
338
339 // We do a radix sort with internal counting sort. This means
340 // that we pass over the source data exactly 16*cur times to sort it.
341 EightBitCountingSort(newsizes, sizes, cur, 0, newnames, names, newkids, children, newactualsizes, actualsizes, newtimes, times);
342 EightBitCountingSort(sizes, newsizes, cur, 8, names, newnames, children, newkids, actualsizes, newactualsizes, times, newtimes);
343 EightBitCountingSort(newsizes, sizes, cur, 16, newnames, names, newkids, children, newactualsizes, actualsizes, newtimes, times);
344 EightBitCountingSort(sizes, newsizes, cur, 24, names, newnames, children, newkids, actualsizes, newactualsizes, times, newtimes);
345 EightBitCountingSort(newsizes, sizes, cur, 32, newnames, names, newkids, children, newactualsizes, actualsizes, newtimes, times);
346 EightBitCountingSort(sizes, newsizes, cur, 40, names, newnames, children, newkids, actualsizes, newactualsizes, times, newtimes);
347 EightBitCountingSort(newsizes, sizes, cur, 48, newnames, names, newkids, children, newactualsizes, actualsizes, newtimes, times);
348 EightBitCountingSort(sizes, newsizes, cur, 56, names, newnames, children, newkids, actualsizes, newactualsizes, times, newtimes);
349
350 free(newtimes);
351 free(newnames);
352 free(newsizes);
353 free(newactualsizes);
354 free(newkids);
355}
356
357static ui32 strxcpy(char *dest, const char *src)
358{
359 ui32 len = 0;
360 while ((*dest++ = *src++) != '\0') len++;
361 return len;
362}
363
364BOOL CFolder::LoadFolderInitial(CFolderTree *tree, const char *name, ui64 clustersize, CFolderDialog *dialog)
365{
366 // First, fix up the pathname so that it's canonical and complete.
367 int len;
368 char path[MAX_PATH+270];
369 _fullpath(path, name, MAX_PATH);
370 if (dialog != NULL)
371 dialog->SetPath(tree, path, this);
372 if ((len = strlen(path)) < 1 || path[len-1] != '\\')
373 path[len++] = '\\';
374
375 // Next, compute a bit-field to use when computing the cluster size. This
376 // saves us the work of having to do a real modulus later on.
377 int clusterbits;
378 ui64 clustermod;
379 ui64 temp = clustersize;
380 BOOL aligned;
381 clusterbits = 0;
382 while (temp != 0) {
383 temp >>= 1;
384 clusterbits++;
385 }
386 clustermod = 1;
387 while (clusterbits--) clustermod <<= 1;
388 aligned = (clustermod == clustersize);
389
390 // Thus aligned will be set to TRUE if clustersize is a power of two,
391 // which, if it is, it saves a lot of computation work by letting us use
392 // bitwise-and instead of true modulus. We also subtract 1 from the
393 // cluster size here because it saves extra work in the recursive part.
394
395 return LoadFolder(tree, path, len, clustersize-1, aligned, dialog);
396}
397
398BOOL CFolder::LoadFolder(CFolderTree *tree, char *name, ui32 namelen, ui64 clustersize, BOOL aligned, CFolderDialog *dialog)
399{
400 WIN32_FIND_DATA finddata;
401 BOOL gotfile;
402 HANDLE handle;
403 ui64 size;
404 static DWORD last_tick = 0;
405 ui32 newlen;
406
407 name[namelen] = '*';
408 name[namelen+1] = '.';
409 name[namelen+2] = '*';
410 name[namelen+3] = '\0';
411
412 // "name" now contains something like "C:\Windows\System\*.*"
413
414 handle = FindFirstFile(name, &finddata);
415 gotfile = (handle != INVALID_HANDLE_VALUE);
416 while (gotfile && !dialog->cancelled) {
417 newlen = namelen + strxcpy(name+namelen, finddata.cFileName);
418
419 // Handle (i.e., IGNORE) any junction points, mount points, or symbolic links.
420 // This is a lot messier than it would be with Unix soft-links, but a lot
421 // simpler than Unix mount points.
422 if (finddata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
423
424 // Open a handle to the object. This should never be able to fail.
425 HANDLE fileHandle = CreateFile(name, 0, FILE_SHARE_READ, NULL,
426 OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT, 0);
427
428 // Retrieve the reparse information for the object.
429 BYTE reparseBuffer[MAX_REPARSE_SIZE];
430 PREPARSE_GUID_DATA_BUFFER reparseInfo = (PREPARSE_GUID_DATA_BUFFER)reparseBuffer;
431 DWORD returnedLength;
432 DWORD result = DeviceIoControl(fileHandle, FSCTL_GET_REPARSE_POINT,
433 NULL, 0, reparseInfo, sizeof(reparseBuffer),
434 &returnedLength, NULL);
435
436 if (result) {
437 // If the reparse information indicated this was a mount point, junction
438 // point, or symbolic link, skip the file. Its size will be small enough
439 // that failing to factor it into the overall size computations will not
440 // yield invalid results.
441 ULONG msresult = IsReparseTagMicrosoft(reparseInfo->ReparseTag);
442 if (msresult) {
443 switch (reparseInfo->ReparseTag) {
444 case 0x80000000|IO_REPARSE_TAG_SYMBOLIC_LINK:
445 case IO_REPARSE_TAG_MOUNT_POINT:
446 CloseHandle(fileHandle);
447 goto nextfile;
448 }
449 }
450 }
451 CloseHandle(fileHandle);
452 }
453
454 // Process directories, except for the ".." directory.
455 if (finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
456 if (!(finddata.cFileName[0] == '.' && (finddata.cFileName[1] == '\0'
457 || (finddata.cFileName[1] == '.' && finddata.cFileName[2] == '\0')))) {
458 if (dialog != NULL)
459 dialog->IncFolders();
460 name[newlen++] = '\\';
461 name[newlen] = '\0';
462 CFolder *newfolder = new CFolder;
463 newfolder->LoadFolder(tree, name, newlen, clustersize, aligned, dialog);
464 AddFolder(tree, finddata.cFileName, newlen-namelen-1, newfolder,
465 *(ui64 *)&finddata.ftLastWriteTime);
466 }
467 }
468 else {
469 // Process files.
470 if (dialog != NULL) dialog->IncFiles();
471 // We round up to the cluster size because that's the
472 // smallest the file can get
473 ui64 actualsize = (ui64)finddata.nFileSizeLow + ((ui64)finddata.nFileSizeHigh << 32);
474 if (aligned) size = (actualsize+clustersize) & clustersize;
475 else size = actualsize - (actualsize % (clustersize+1));
476 AddFile(tree, finddata.cFileName, newlen-namelen, size, actualsize,
477 *(ui64 *)&finddata.ftLastWriteTime);
478 }
479
480 nextfile:
481 gotfile = FindNextFile(handle, &finddata);
482
483 // Only poll the system event queue every 1/5 of a second or so.
484 // That's enough to ensure quick response, but it won't bog
485 // down the scan.
486 DWORD tick = ::GetTickCount();
487 if (tick > last_tick + 200) {
488 last_tick = tick;
489 MSG msg;
490 if (dialog != NULL) {
491 name[namelen] = '\0';
492 dialog->SetPath(tree, name, this);
493 }
494 while (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
495 ::TranslateMessage(&msg);
496 ::DispatchMessage(&msg);
497 }
498 }
499 }
500 FindClose(handle);
501 Finalize();
502
503 return !dialog->cancelled;
504}
505
506void CFolder::DelFile(unsigned int index)
507{
508}
509
510void CFolder::RenameFile(unsigned int index, const CString &name)
511{
512}
513
514unsigned int CFolder::FindFile(const CString &name)
515{
516 return((unsigned int)-1);
517}
518
519//////////////////////////////////////////////////////////////////////////////
520
521IMPLEMENT_DYNCREATE(CFolderDialog, CDialog)
522
523BEGIN_MESSAGE_MAP(CFolderDialog, CDialog)
524 //{{AFX_MSG_MAP(CFolderDialog)
525 //}}AFX_MSG_MAP
526END_MESSAGE_MAP()
527
528CFolderDialog::CFolderDialog()
529{
530 last_tick = last_redraw = 0;
531 path = "";
532 numfiles = 0;
533 numfolders = 0;
534 chg_path = chg_numfiles = chg_numfolders = 0;
535 cur_frame = 0;
536
537 cancelled = 0;
538}
539
540CFolderDialog::~CFolderDialog()
541{
542}
543
544void CFolderDialog::OnCancel(void)
545{
546 cancelled = 1;
547 CDialog::OnCancel();
548}
549
550void CFolderDialog::Reset(void)
551{
552 if (!IsWindow(m_hWnd)) return;
553
554 last_tick = last_redraw = 0;
555 path = "";
556 numfiles = 0;
557 numfolders = 0;
558 chg_path = chg_numfiles = chg_numfolders = 0;
559 cur_frame = 0;
560
561 cancelled = 0;
562
563 SetWindowText(CurLang->scanning);
564 SetDlgItemText(IDC_STATIC_FILESFOUND, CurLang->files_found);
565 SetDlgItemText(IDC_STATIC_FOLDERSFOUND, CurLang->folders_found);
566 SetDlgItemText(IDCANCEL, CurLang->cancel);
567 SetDlgItemText(IDC_PATH, path);
568 SetDlgItemInt(IDC_FILES, numfiles);
569 SetDlgItemInt(IDC_FOLDERS, numfolders);
570 CProgressCtrl *progress = (CProgressCtrl *)GetDlgItem(IDC_LOAD_PROGRESS);
571 if (progress != NULL) {
572 progress->SetRange(0, 4096);
573 progress->SetPos(0);
574 }
575
576 CClientDC dc(this);
577 CDC srcdc;
578 srcdc.CreateCompatibleDC(&dc);
579 ::SelectObject(srcdc.m_hDC, theApp.m_scan_animation[0]);
580 CRect rect;
581 GetClientRect(&rect);
582 dc.BitBlt(8, rect.bottom - rect.top - (48 + 8) - 12, 128, 48, &srcdc, 0, 0, SRCCOPY);
583}
584
585void CFolderDialog::UpdateDisplay(CFolderTree *tree, CFolder *folder)
586{
587 // Guarantee that we don't update more often than 1/5 of a second
588 DWORD tick = ::GetTickCount();
589 if (tick > last_tick + 200) {
590 last_tick = tick;
591
592 if (!IsWindow(m_hWnd)) return;
593
594 if (chg_path) SetDlgItemText(IDC_PATH, path);
595 if (chg_numfiles) SetDlgItemInt(IDC_FILES, numfiles);
596 if (chg_numfolders) SetDlgItemInt(IDC_FOLDERS, numfolders);
597 CProgressCtrl *progress = (CProgressCtrl *)GetDlgItem(IDC_LOAD_PROGRESS);
598 if (progress != NULL) {
599 ui64 filespace = tree->filespace/16384;
600 ui64 usedspace = tree->usedspace/16384;
601 if (usedspace <= 0) usedspace = 1;
602 progress->SetRange(0, 4096);
603 progress->SetPos((int)(filespace*4096/usedspace));
604 }
605 chg_path = chg_numfiles = chg_numfolders = 0;
606
607 cur_frame = (cur_frame + 1) & 7;
608 if (!(cur_frame & 1)) {
609 CClientDC dc(this);
610 CDC srcdc;
611 srcdc.CreateCompatibleDC(&dc);
612 ::SelectObject(srcdc.m_hDC, theApp.m_scan_animation[cur_frame >> 1]);
613 CRect rect;
614 GetClientRect(&rect);
615 dc.BitBlt(8, rect.bottom - rect.top - (48 + 8) - 12, 128, 48, &srcdc, 0, 0, SRCCOPY);
616 }
617 }
618#if 0
619 // Redraws the display during the scan. Very ugly-looking.
620 if (tick > last_redraw + 1000) {
621 last_redraw = tick;
622 while (folder != NULL) {
623 folder->Finalize();
624 folder = folder->parent;
625 }
626 tree->UpdateAllViews();
627 }
628#endif
629}
630
631void CFolderDialog::ForcedUpdate(CFolderTree *tree)
632{
633 if (!IsWindow(m_hWnd)) return;
634
635 SetDlgItemText(IDC_PATH, path);
636 SetDlgItemInt(IDC_FILES, numfiles);
637 SetDlgItemInt(IDC_FOLDERS, numfolders);
638 CProgressCtrl *progress = (CProgressCtrl *)GetDlgItem(IDC_LOAD_PROGRESS);
639 if (progress != NULL) {
640 progress->SetRange(0, 4096);
641 progress->SetPos(4096);
642 }
643}
644
diff --git a/FolderTree.h b/FolderTree.h
new file mode 100644
index 0000000..cd2df79
--- /dev/null
+++ b/FolderTree.h
@@ -0,0 +1,122 @@
1
2#ifndef FOLDERTREE_H
3#define FOLDERTREE_H
4
5class CFolderTree;
6class CFolderDialog;
7struct CFolder;
8
9struct CFolder {
10public:
11 CFolder();
12 ~CFolder();
13
14 void AddFile(CFolderTree *tree, const char *name, ui32 namelen, ui64 size, ui64 actual_size, ui64 time);
15 void AddFolder(CFolderTree *tree, const char *name, ui32 namelen, CFolder *folder, ui64 time);
16 void Finalize(void);
17 void DelFile(unsigned int index);
18 void RenameFile(unsigned int index, const CString &name);
19 unsigned int FindFile(const CString &name);
20 BOOL LoadFolderInitial(CFolderTree *tree, const char *name, ui64 clustersize, CFolderDialog *dialog);
21 inline ui64 SizeFiles() { return(size_self); }
22 inline ui64 SizeSub() { return(size_children); }
23 inline ui64 SizeTotal() { return(size_self + size_children); }
24
25private:
26 void MoreEntries(void);
27 void EightBitCountingSort(ui64 *dsize, ui64 *ssize, ui32 count, ui32 bitpos,
28 char **dnames, char **snames, CFolder **dkids, CFolder **skids,
29 ui64 *dasize, ui64 *sasize, ui64 *dtimes, ui64 *stimes);
30 BOOL LoadFolder(CFolderTree *tree, char *name, ui32 namelen, ui64 clustersize, BOOL aligned, CFolderDialog *dialog);
31
32public:
33 CFolder *parent;
34 unsigned int parentindex;
35
36 char **names;
37 CFolder **children;
38 ui64 *sizes;
39 ui64 *actualsizes;
40 ui64 *times;
41 ui64 size_self, size_children;
42
43 unsigned int cur, max;
44};
45
46class CFolderTree : public CFreeDoc {
47public:
48 CFolderTree();
49 virtual ~CFolderTree();
50
51 BOOL LoadTree(const CString &path, BOOL includespace, CWnd *modalwin);
52 void GetSpace(const CString &path);
53 CFolder *GetRoot(void);
54
55 CFolder *SetCur(const CString &path);
56 CFolder *GetCur(void);
57 CFolder *Down(unsigned int index);
58 CFolder *Up(void);
59
60protected:
61 CFolder *root, *cur;
62
63public:
64 CString m_path;
65 ui64 freespace, usedspace, totalspace, clustersize;
66 ui64 numfiles, numfolders;
67 ui64 filespace;
68};
69
70class CFolderDialog : public CDialog {
71public:
72 CFolderDialog();
73 DECLARE_DYNCREATE(CFolderDialog)
74 virtual ~CFolderDialog();
75
76 virtual void Reset(void);
77 virtual void UpdateDisplay(CFolderTree *tree, CFolder *folder);
78 virtual void ForcedUpdate(CFolderTree *tree);
79
80 void IncFiles(void);
81 void IncFolders(void);
82 void SetPath(CFolderTree *tree, const CString &string, CFolder *folder);
83
84 virtual void OnCancel(void);
85
86protected:
87 //{{AFX_MSG(CFolderDialog)
88 //}}AFX_MSG
89 DECLARE_MESSAGE_MAP()
90
91public:
92 ui32 numfiles, numfolders;
93 CString path;
94
95 BOOL cancelled;
96
97protected:
98 BOOL chg_numfiles, chg_numfolders, chg_path;
99 DWORD last_tick, last_redraw;
100 ui32 cur_frame;
101};
102
103inline void CFolderDialog::IncFiles(void)
104{
105 numfiles++;
106 chg_numfiles = 1;
107}
108
109inline void CFolderDialog::IncFolders(void)
110{
111 numfolders++;
112 chg_numfolders = 1;
113}
114
115inline void CFolderDialog::SetPath(CFolderTree *tree, const CString &string, CFolder *folder)
116{
117 path = string;
118 chg_path = 1;
119 UpdateDisplay(tree, folder);
120}
121
122#endif
diff --git a/FolderView.cpp b/FolderView.cpp
new file mode 100644
index 0000000..b70c187
--- /dev/null
+++ b/FolderView.cpp
@@ -0,0 +1,1131 @@
1#include "stdafx.h"
2#include "spacemonger.h"
3#include "FolderView.h"
4#include "MainFrm.h"
5#include "TipWnd.h"
6#include "Lang.h"
7
8IMPLEMENT_DYNCREATE(CFolderView, CFreeView)
9
10static COLORREF BoxColors[] = {
11 PALETTERGB(0xFF, 0x7F, 0x7F),
12 PALETTERGB(0xFF, 0xBF, 0x7F),
13 PALETTERGB(0xFF, 0xFF, 0x00),
14 PALETTERGB(0x7F, 0xFF, 0x7F),
15 PALETTERGB(0x7F, 0xFF, 0xFF),
16 PALETTERGB(0xBF, 0xBF, 0xFF),
17 PALETTERGB(0xBF, 0xBF, 0xBF),
18 PALETTERGB(0xFF, 0x7F, 0xFF),
19
20 PALETTERGB(0xFF, 0xBF, 0xBF),
21 PALETTERGB(0xFF, 0xDF, 0xBF),
22 PALETTERGB(0xFF, 0xFF, 0xBF),
23 PALETTERGB(0xBF, 0xFF, 0xBF),
24 PALETTERGB(0xDF, 0xFF, 0xFF),
25 PALETTERGB(0xDF, 0xDF, 0xFF),
26 PALETTERGB(0xDF, 0xDF, 0xDF),
27 PALETTERGB(0xFF, 0xBF, 0xFF),
28
29 PALETTERGB(0xBF, 0x7F, 0x7F),
30 PALETTERGB(0xBF, 0x9F, 0x5F),
31 PALETTERGB(0xBF, 0xBF, 0x3F),
32 PALETTERGB(0x7F, 0xBF, 0x7F),
33 PALETTERGB(0x7F, 0xBF, 0xBF),
34 PALETTERGB(0x9F, 0x9F, 0xFF),
35 PALETTERGB(0x9F, 0x9F, 0x9F),
36 PALETTERGB(0xBF, 0x7F, 0xBF),
37
38 PALETTERGB(0x00, 0x00, 0x00),
39 PALETTERGB(0xFF, 0xFF, 0xFF),
40};
41
42// These colors are used for specifically-chosen folder colors.
43static COLORREF FixedColors[] = {
44 PALETTERGB(0xFF, 0xFF, 0xFF),
45 PALETTERGB(0xBF, 0xBF, 0xBF),
46 PALETTERGB(0x7F, 0x7F, 0x7F),
47
48 PALETTERGB(0xFF, 0x7F, 0x7F),
49 PALETTERGB(0xFF, 0xBF, 0x7F),
50 PALETTERGB(0xFF, 0xFF, 0x00),
51 PALETTERGB(0x7F, 0xFF, 0x7F),
52 PALETTERGB(0x7F, 0xFF, 0xFF),
53 PALETTERGB(0xBF, 0xBF, 0xFF),
54 PALETTERGB(0xFF, 0x7F, 0xFF),
55
56 PALETTERGB(0xFF, 0xFF, 0xFF),
57 PALETTERGB(0xFF, 0xFF, 0xFF),
58 PALETTERGB(0xBF, 0xBF, 0xBF),
59
60 PALETTERGB(0xFF, 0x9F, 0x9F),
61 PALETTERGB(0xFF, 0xDF, 0xBF),
62 PALETTERGB(0xFF, 0xFF, 0xBF),
63 PALETTERGB(0xBF, 0xFF, 0xBF),
64 PALETTERGB(0xDF, 0xFF, 0xFF),
65 PALETTERGB(0xDF, 0xDF, 0xFF),
66 PALETTERGB(0xFF, 0xBF, 0xFF),
67
68 PALETTERGB(0xBF, 0xBF, 0xBF),
69 PALETTERGB(0x7F, 0x7F, 0x7F),
70 PALETTERGB(0x3F, 0x3F, 0x3F),
71
72 PALETTERGB(0xBF, 0x7F, 0x7F),
73 PALETTERGB(0xBF, 0x9F, 0x9F),
74 PALETTERGB(0xBF, 0xBF, 0x3F),
75 PALETTERGB(0x7F, 0xBF, 0x7F),
76 PALETTERGB(0x7F, 0xBF, 0xBF),
77 PALETTERGB(0x9F, 0x9F, 0xFF),
78 PALETTERGB(0xBF, 0x7F, 0xBF),
79};
80
81CFolderView::CFolderView()
82{
83 rootfolder = NULL;
84 selected = NULL;
85 displayfolders = displayend = NULL;
86 zoomlevel = 0;
87 showfreespace = 1;
88 lastcur = NULL;
89}
90
91CFolderView::~CFolderView()
92{
93 ClearDisplayFolders();
94}
95
96BEGIN_MESSAGE_MAP(CFolderView, CFreeView)
97 //{{AFX_MSG_MAP(CFolderView)
98 ON_WM_SIZE()
99 ON_WM_LBUTTONDOWN()
100 ON_WM_LBUTTONDBLCLK()
101 ON_WM_RBUTTONUP()
102 ON_WM_CREATE()
103 ON_WM_DESTROY()
104 ON_WM_MOUSEMOVE()
105 //}}AFX_MSG_MAP
106 ON_UPDATE_COMMAND_UI_RANGE(100, 41000, OnIgnoreUpdate)
107END_MESSAGE_MAP()
108
109BOOL CFolderView::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT *pResult)
110{
111 if (::IsWindow(m_infotipwnd.m_hWnd)) {
112 MSG msg;
113 msg.message = message;
114 msg.wParam = wParam;
115 msg.lParam = lParam;
116 msg.hwnd = m_hWnd;
117 m_infotipwnd.ReflectMessage(&msg);
118 }
119 if (::IsWindow(m_nametipwnd.m_hWnd)) {
120 MSG msg;
121 msg.message = message;
122 msg.wParam = wParam;
123 msg.lParam = lParam;
124 msg.hwnd = m_hWnd;
125 m_nametipwnd.ReflectMessage(&msg);
126 }
127 return CFreeView::OnWndMsg(message, wParam, lParam, pResult);
128}
129
130int CFolderView::OnCreate(LPCREATESTRUCT lpCreateStruct)
131{
132 if (CFreeView::OnCreate(lpCreateStruct) == -1)
133 return -1;
134 if (!m_infotipwnd.CreateEz(this, 64, 64)) return -1;
135 if (!m_nametipwnd.CreateEz(this, 64, 64)) return -1;
136
137 int i;
138 LOGPALETTE *logpalette = (LOGPALETTE *)malloc(sizeof(LOGPALETTE) + 26 * sizeof(PALETTEENTRY));
139 logpalette->palVersion = 0x300;
140 logpalette->palNumEntries = 26;
141 for (i = 0; i < 26; i++) {
142 logpalette->palPalEntry[i].peFlags = 0;
143 logpalette->palPalEntry[i].peRed = GetRValue(BoxColors[i]);
144 logpalette->palPalEntry[i].peGreen = GetGValue(BoxColors[i]);
145 logpalette->palPalEntry[i].peBlue = GetBValue(BoxColors[i]);
146 }
147 m_palette.CreatePalette(logpalette);
148 delete logpalette;
149
150 black.CreateSolidBrush(RGB(0x00, 0x00, 0x00));
151 white.CreateSolidBrush(RGB(0xFF, 0xFF, 0xFF));
152
153 minifont.CreateFont(-9, 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET,
154 OUT_RASTER_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
155 VARIABLE_PITCH|FF_SWISS, "Small Fonts");
156
157 m_infotipwnd.SetAutoShow(1);
158 m_infotipwnd.SetAutoPos(1);
159 m_infotipwnd.SetShowDelay(theApp.m_settings.infotip_delay);
160 m_infotipwnd.EnableWindow(0);
161
162 HFONT nametipfont = ::CreateFont(-9, 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET,
163 OUT_RASTER_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
164 VARIABLE_PITCH|FF_SWISS, "Small Fonts");
165 ::SendMessage(m_nametipwnd.m_hWnd, WM_SETFONT, (WPARAM)nametipfont, 0);
166 m_nametipwnd.SetAutoShow(1);
167 m_nametipwnd.SetShowDelay(theApp.m_settings.nametip_delay);
168 m_nametipwnd.SetVPadding(0);
169 m_nametipwnd.SetHPadding(1);
170 m_nametipwnd.EnableWindow(0);
171
172 return 0;
173}
174
175void CFolderView::OnDestroy()
176{
177 m_palette.DeleteObject();
178 black.DeleteObject();
179 white.DeleteObject();
180 minifont.DeleteObject();
181
182 m_infotipwnd.DestroyWindow();
183 m_nametipwnd.DestroyWindow();
184
185 CFreeView::OnDestroy();
186}
187
188CDisplayFolder *CFolderView::GetDisplayFolderFromPoint(const CPoint &point)
189{
190 CDisplayFolder *cur = displayfolders;
191
192 while (cur != NULL) {
193 if (point.x > cur->x && point.y > cur->y
194 && point.x < cur->x + cur->w && point.y < cur->y + cur->h) {
195 if (cur->flags & 1) {
196 if (point.x < cur->x+3 || point.y < cur->y+12
197 || point.x > cur->x+cur->w-3 || point.y > cur->y+cur->h-3)
198 break;
199 }
200 else break;
201 }
202 cur = cur->next;
203 }
204
205 if (cur != NULL && cur->name == NULL)
206 cur = NULL;
207 if (cur != NULL && cur->name[0] == '<')
208 cur = NULL;
209
210 return cur;
211}
212
213CDisplayFolder *CFolderView::GetContainerDisplayFolderFromPoint(const CPoint &point)
214{
215 CDisplayFolder *cur = displayfolders, *best = NULL;
216 CRect minrect(-32768,-32768,32767,32767);
217
218 while (cur != NULL) {
219 if (cur->flags & 1
220 && point.x > cur->x && point.y > cur->y
221 && point.x < cur->x + cur->w && point.y < cur->y + cur->h
222 && cur->x >= minrect.left && cur->y >= minrect.top
223 && cur->x+cur->w <= minrect.right && cur->y+cur->h <= minrect.bottom) {
224 // Found a tighter folder, so use it.
225 minrect.left = cur->x;
226 minrect.top = cur->y;
227 minrect.right = cur->x+cur->w;
228 minrect.bottom = cur->y+cur->h;
229 best = cur;
230 }
231 cur = cur->next;
232 }
233
234 return best;
235}
236
237void CFolderView::HighlightPathAtPoint(const CPoint &point)
238{
239 CDisplayFolder *cur = displayfolders;
240
241 CDC *pDC = GetDC();
242 pDC->SelectObject(&minifont);
243 pDC->SetBkMode(TRANSPARENT);
244 pDC->SetTextAlign(TA_LEFT | TA_TOP | TA_NOUPDATECP);
245 pDC->SelectPalette(&m_palette, 0);
246 while (cur != NULL) {
247 if (cur->name != NULL && cur->name[0] != '<') {
248 if (point.x > cur->x && point.y > cur->y
249 && point.x < cur->x + cur->w && point.y < cur->y + cur->h) {
250 if (!(cur->flags & 4)) {
251 cur->flags |= 4;
252 MinimalDrawDisplayFolder(pDC, cur, selected == cur);
253 }
254 }
255 else {
256 if (cur->flags & 4) {
257 cur->flags &= ~4;
258 MinimalDrawDisplayFolder(pDC, cur, selected == cur);
259 }
260 }
261 }
262 cur = cur->next;
263 }
264 ReleaseDC(pDC);
265}
266
267void CFolderView::OnLButtonDown(UINT flags, CPoint point)
268{
269 SelectFolder(GetDisplayFolderFromPoint(point));
270 lastcur = NULL;
271 OnMouseMove(flags, point);
272}
273
274void CFolderView::OnLButtonDblClk(UINT flags, CPoint point)
275{
276 CDisplayFolder *cur = GetDisplayFolderFromPoint(point);
277 SelectFolder(cur);
278
279 if (cur != NULL) {
280 if (cur->flags & 1) ZoomIn(cur);
281 else {
282 CString title, path;
283 title += ((CFolderTree *)GetDocument())->m_path;
284 BuildTitleReverse(selected->source, title);
285 path = title;
286 title += selected->source->names[selected->index];
287 ShellExecute(NULL, NULL, title, NULL, path, SW_SHOWDEFAULT);
288 }
289 }
290 lastcur = NULL;
291 OnMouseMove(flags, point);
292}
293
294void CFolderView::OnMouseMove(UINT nFlags, CPoint point)
295{
296 CDisplayFolder *cur = GetDisplayFolderFromPoint(point);
297
298 if (theApp.m_settings.rollover_box) HighlightPathAtPoint(point);
299 else HighlightPathAtPoint(CPoint(-1,-1));
300
301 if (theApp.m_settings.show_info_tips) {
302 if (cur == NULL)
303 m_infotipwnd.EnableWindow(0);
304 else if (lastcur != cur)
305 SetupInfoTip(cur);
306 }
307 else m_infotipwnd.EnableWindow(0);
308
309 if (theApp.m_settings.show_name_tips) {
310 if (cur == NULL)
311 m_nametipwnd.EnableWindow(0);
312 else if (lastcur != cur)
313 SetupNameTip(cur);
314 }
315 else m_nametipwnd.EnableWindow(0);
316
317 lastcur = cur;
318}
319
320static void PrintFileSize(CString &string, ui64 size)
321{
322 char sizebuf[256];
323 char *dest = sizebuf+255;
324 int ctr = 0;
325 sizebuf[255] = '\0';
326 while (size != 0) {
327 if (++ctr == 4) *--dest = CurLang->digitcomma, ctr = 1;
328 *--dest = (char)(size % 10) + '0';
329 size /= 10;
330 }
331 string += dest;
332 string += " ";
333 string += CurLang->bytes;
334}
335
336static void PrintDate(CString &string, ui64 date)
337{
338 CString tempstring;
339 SYSTEMTIME mtime;
340 FileTimeToSystemTime((FILETIME *)&date, &mtime);
341 if (mtime.wMonth < 1 || mtime.wMonth > 12) mtime.wMonth = 1;
342 if (mtime.wDayOfWeek < 0 || mtime.wDayOfWeek > 6) mtime.wDayOfWeek = 0;
343 tempstring.Format("%02d %s %04d %d:%02d:%02d",
344 mtime.wDay, CurLang->monthnames[mtime.wMonth-1], mtime.wYear,
345 mtime.wHour, mtime.wMinute, mtime.wSecond);
346 string += tempstring;
347}
348
349void CFolderView::SetupInfoTip(CDisplayFolder *cur)
350{
351 if (cur == NULL) {
352 m_infotipwnd.EnableWindow(0);
353 return;
354 }
355
356 CString path;
357 CString string, tempstring;
358
359 // Get the full pathname to the file.
360 CFolderTree *ft = (CFolderTree *)GetDocument();
361 path += ft->m_path;
362 BuildTitleReverse(cur->source, tempstring);
363 path += tempstring;
364
365 // Load in the file's information using FindFirstFile.
366 WIN32_FIND_DATA info;
367 HANDLE handle = FindFirstFile(path+cur->source->names[cur->index], &info);
368 FindClose(handle);
369
370 if (theApp.m_settings.infotip_flags & TIP_PATH)
371 string += path;
372 if (theApp.m_settings.infotip_flags & TIP_NAME)
373 string += cur->source->names[cur->index];
374 if (theApp.m_settings.infotip_flags & (TIP_NAME|TIP_PATH))
375 string += '\n';
376 if (theApp.m_settings.infotip_flags & TIP_SIZE)
377 PrintFileSize(string, cur->source->actualsizes[cur->index]);
378 if (theApp.m_settings.infotip_flags & TIP_ATTRIB) {
379 if ((theApp.m_settings.infotip_flags & TIP_SIZE)
380 && info.dwFileAttributes != 0) string += " / ";
381 if (info.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) string += " ", string += CurLang->attribnames[0];
382 if (info.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) string += " ", string += CurLang->attribnames[1];
383 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) string += " ", string += CurLang->attribnames[2];
384 if (info.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) string += " ", string += CurLang->attribnames[3];
385 if (info.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) string += " ", string += CurLang->attribnames[4];
386 if (info.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) string += " ", string += CurLang->attribnames[5];
387 if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) string += " ", string += CurLang->attribnames[6];
388 if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) string += " ", string += CurLang->attribnames[7];
389 if (info.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) string += " ", string += CurLang->attribnames[8];
390 if (info.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) string += " ", string += CurLang->attribnames[9];
391 if (info.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) string += " ", string += CurLang->attribnames[10];
392 }
393 if (theApp.m_settings.infotip_flags & (TIP_ATTRIB|TIP_SIZE))
394 string += '\n';
395 if (theApp.m_settings.infotip_flags & TIP_DATE) {
396 PrintDate(string, cur->source->times[cur->index]);
397 string += '\n';
398 }
399 if (theApp.m_settings.infotip_flags & TIP_ICON) {
400 SHFILEINFO fileinfo;
401 memset(&fileinfo, sizeof(SHFILEINFO), 0);
402 SHGetFileInfo(path+cur->source->names[cur->index], 0,
403 &fileinfo, sizeof(SHFILEINFO), SHGFI_DISPLAYNAME|SHGFI_ICON);
404 m_infotipwnd.SetIcon(fileinfo.hIcon, 1);
405 m_infotipwnd.SetIconPos(TW_LEFT);
406 }
407
408 m_infotipwnd.SetWindowText(string);
409 m_infotipwnd.AutoSize();
410 m_infotipwnd.EnableWindow(1);
411 m_infotipwnd.RedrawWindow();
412}
413
414void CFolderView::SetupNameTip(CDisplayFolder *cur)
415{
416 m_nametipwnd.EnableWindow(0);
417
418 if (cur == NULL) return;
419
420 CDC *pDC = GetDC();
421 pDC->SelectObject(&minifont);
422 pDC->SetBkMode(TRANSPARENT);
423 pDC->SetTextAlign(TA_LEFT | TA_TOP | TA_NOUPDATECP);
424 pDC->SelectPalette(&m_palette, 0);
425
426 int tx, ty, failed = 0;
427 CSize size = pDC->GetTextExtent(cur->name, strlen(cur->name));
428 int x = cur->x, y = cur->y, w = cur->w + 1, h = cur->h + 1;
429 if (size.cx > w - 2) tx = x + 2;
430 else if (cur->flags & 1) tx = x + 2, failed++;
431 else tx = x + (w - size.cx) / 2, failed++;
432 if (size.cy > h - 2) ty = y + 1;
433 else if (cur->flags & 1) ty = y + 1, failed++;
434 else ty = y + (h - size.cy) / 2, failed++;
435 if (failed == 2) return;
436
437 if (!(cur->flags & 1) && h >= 36 && w >= 48)
438 ty -= 12;
439
440 if (selected == cur) {
441 m_nametipwnd.SetBgColor(RGB(0,0,0));
442 m_nametipwnd.SetTextColor(RGB(255,255,255));
443 }
444 else if (cur->flags & 4) {
445 m_nametipwnd.SetBgColor(BoxColors[(cur->depth & 7) + 8]);
446 m_nametipwnd.SetTextColor(RGB(0,0,0));
447 }
448 else {
449 m_nametipwnd.SetBgColor(BoxColors[cur->depth & 7]);
450 m_nametipwnd.SetTextColor(RGB(0,0,0));
451 }
452 m_nametipwnd.SetWindowText(cur->name);
453 m_nametipwnd.AutoSize();
454 m_nametipwnd.MoveWindow(this, tx-2, ty-1);
455 m_nametipwnd.PushOnScreen();
456
457 ReleaseDC(pDC);
458 m_nametipwnd.EnableWindow(1);
459 m_nametipwnd.RedrawWindow();
460}
461
462static void AddMenuEntry(HMENU menu, UINT cmd = 0, const char *string = NULL,
463 BOOL checked = 0, BOOL disabled = 0, BOOL bold = 0)
464{
465 MENUITEMINFO mii;
466 mii.cbSize = sizeof(MENUITEMINFO);
467 mii.fMask = MIIM_CHECKMARKS|MIIM_ID|MIIM_STATE|MIIM_TYPE;
468 mii.fType = ((string != NULL) ? MFT_STRING : MFT_SEPARATOR);
469 mii.fState = 0;
470 if (bold) mii.fState |= MFS_DEFAULT;
471 if (checked) mii.fState |= MFS_CHECKED;
472 if (disabled) mii.fState |= MFS_GRAYED|MFS_DISABLED;
473 mii.wID = cmd;
474 mii.hSubMenu = NULL;
475 mii.hbmpChecked = NULL;
476 mii.hbmpUnchecked = NULL;
477 mii.dwTypeData = (char *)string;
478 if (string != NULL) mii.cch = strlen(string);
479 else mii.cch = 0;
480
481 ::InsertMenuItem(menu, GetMenuItemCount(menu), TRUE, &mii);
482}
483
484void CFolderView::OnRButtonUp(UINT flags, CPoint point)
485{
486 CDisplayFolder *cur = GetDisplayFolderFromPoint(point);
487 SelectFolder(cur);
488 ClientToScreen(&point);
489
490 bool showinfo = m_infotipwnd.IsWindowEnabled();
491 bool showname = m_nametipwnd.IsWindowEnabled();
492 m_infotipwnd.EnableWindow(0);
493 m_nametipwnd.EnableWindow(0);
494
495 CSpaceMonger *app = (CSpaceMonger *)AfxGetApp();
496 HMENU menu = ::CreatePopupMenu();
497 ::AddMenuEntry(menu, ID_VIEW_ZOOM_IN, CurLang->zoomin, 0, cur == NULL, (cur != NULL) && (cur->flags & 1) != 0);
498 ::AddMenuEntry(menu, ID_VIEW_ZOOM_OUT, CurLang->zoomout, 0, cur == NULL, 0);
499 ::AddMenuEntry(menu, ID_VIEW_ZOOM_FULL, CurLang->zoomfull, 0, cur == NULL, 0);
500 ::AddMenuEntry(menu);
501 ::AddMenuEntry(menu, ID_FILE_RUN, CurLang->run, 0, cur == NULL, (cur != NULL) && (cur->flags & 1) == 0);
502 ::AddMenuEntry(menu, ID_FILE_DELETE, CurLang->del, 0,
503 !app->m_settings.disable_delete && cur == NULL, 0);
504 ::AddMenuEntry(menu);
505 ::AddMenuEntry(menu, ID_FILE_OPEN, CurLang->opendrive, 0, 0, 0);
506 ::AddMenuEntry(menu, ID_FILE_REFRESH, CurLang->rescandrive, 0, 0, 0);
507 ::AddMenuEntry(menu, ID_VIEW_FREE, CurLang->showfreespace, showfreespace, 0, 0);
508 ::AddMenuEntry(menu);
509 ::AddMenuEntry(menu, ID_FILE_PROPERTIES, CurLang->properties, 0, 0, 0);
510 ::TrackPopupMenuEx(menu, TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON,
511 point.x, point.y, theApp.m_mainframe->m_hWnd, NULL);
512 ::DestroyMenu(menu);
513
514 if (showname) m_nametipwnd.EnableWindow(1);
515 if (showinfo) m_infotipwnd.EnableWindow(1);
516}
517
518void CFolderView::SelectFolder(CDisplayFolder *cur)
519{
520 if (cur == selected) return;
521
522 CDC *dc = GetDC();
523
524 if (selected != NULL) {
525 DrawDisplayFolder(dc, selected, 0);
526 selected = NULL;
527 }
528
529 selected = cur;
530 if (selected != NULL)
531 DrawDisplayFolder(dc, selected, 1);
532
533 ReleaseDC(dc);
534 UpdateTitleBar();
535}
536
537static CString GetSizeString(ui64 size, ui64 totalspace, BOOL percent)
538{
539 CString result;
540
541 if (totalspace == 0) totalspace = (ui64)(-1);
542
543 if (percent) {
544 size = (size * (ui64)1000) / totalspace;
545 result.Format(CurLang->percent_format, (ui32)size / 10, (ui32)size % 10);
546 }
547 else {
548 ui32 displayfull, displayfractional;
549 const char *displaytype;
550
551 if (size < (ui64)(1024)) {
552 displayfull = (ui32)size;
553 displayfractional = 0;
554 displaytype = CurLang->bytes;
555 }
556 else if (size < (ui64)(1024*1024)) {
557 displayfull = (ui32)(size / (ui64)(1024));
558 displayfractional = (ui32)(10 * (size % (ui64)(1024)) / (ui64)(1024));
559 displaytype = CurLang->kb;
560 }
561 else if (size < (ui64)(1024*1024*1024)) {
562 displayfull = (ui32)(size / (ui64)(1024*1024));
563 displayfractional = (ui32)(10 * (size % (ui64)(1024*1024)) / (ui64)(1024*1024));
564 displaytype = CurLang->mb;
565 }
566 else {
567 displayfull = (ui32)(size / (ui64)(1024*1024*1024));
568 displayfractional = (ui32)(10 * (size % (ui64)(1024*1024*1024)) / (ui64)(1024*1024*1024));
569 displaytype = CurLang->gb;
570 }
571 result.Format(CurLang->size_format, displayfull, displayfractional, displaytype);
572 }
573
574 return result;
575}
576
577void CFolderView::UpdateTitleBar(void)
578{
579 CMainFrame *mainfrm = (CMainFrame *)GetTopLevelFrame();
580 CFolderTree *ft = (CFolderTree *)GetDocument();
581 CString title = "";
582 ui64 size;
583
584 mainfrm->m_toolbar.UpdateButtonsForView(this);
585
586 if (mainfrm == NULL) return;
587 if (ft == NULL) {
588 mainfrm->SetWindowText(title);
589 return;
590 }
591
592 if (selected != NULL && selected->name != NULL) {
593 if (ft != NULL) title += ft->m_path;
594 BuildTitleReverse(selected->source, title);
595 title += selected->source->names[selected->index];
596 size = selected->source->sizes[selected->index];
597 title += " - " + GetSizeString(size, ft->totalspace, 1)
598 + " - " + GetSizeString(size, ft->totalspace, 0) + " - ";
599 }
600 else if (rootfolder != NULL && ft != NULL) {
601 if (ft != NULL) title += ft->m_path;
602 BuildTitleReverse(rootfolder, title);
603 if (rootfolder->parent == NULL) size = ft->totalspace; // Kludge
604 else size = rootfolder->SizeTotal();
605 title += " - " + GetSizeString(size, ft->totalspace, 0)
606 + " " + CurLang->total + " - " + GetSizeString(ft->freespace, ft->freespace, 0)
607 + " " + CurLang->free + " - ";
608 }
609
610 title += "SpaceMonger";
611
612 mainfrm->SetWindowText(title);
613}
614
615void CFolderView::BuildTitleReverse(CFolder *folder, CString &string)
616{
617 if (folder->parent != NULL)
618 BuildTitleReverse(folder->parent, string);
619 if (folder->parent == NULL) return;
620
621 string += folder->parent->names[folder->parentindex];
622 string += "\\";
623}
624
625void CFolderView::OnDraw(CDC *pDC)
626{
627 pDC->SelectObject(&minifont);
628 pDC->SetBkMode(TRANSPARENT);
629 pDC->SetTextAlign(TA_LEFT | TA_TOP | TA_NOUPDATECP);
630 pDC->SelectPalette(&m_palette, 0);
631 pDC->RealizePalette();
632
633 CDisplayFolder *cur = displayfolders;
634
635 DrawBox(pDC->m_hDC, ColorFlat, 0, 0, m_width, m_height);
636 if (cur == NULL)
637 FillBox(pDC->m_hDC, ColorFlat, 1, 1, m_width-2, m_height-2);
638
639 while (cur != NULL) {
640 MinimalDrawDisplayFolder(pDC, cur, selected == cur);
641 cur = cur->next;
642 }
643}
644
645void CFolderView::DrawDisplayFolder(CDC *pDC, CDisplayFolder *cur, BOOL sel)
646{
647 pDC->SelectObject(&minifont);
648 pDC->SetBkMode(TRANSPARENT);
649 pDC->SetTextAlign(TA_LEFT | TA_TOP | TA_NOUPDATECP);
650 pDC->SelectPalette(&m_palette, 0);
651
652 MinimalDrawDisplayFolder(pDC, cur, sel);
653}
654
655void CFolderView::MinimalDrawDisplayFolder(CDC *pDC, CDisplayFolder *cur, BOOL sel)
656{
657 int x, y, w, h;
658
659 x = cur->x, y = cur->y, w = cur->w + 1, h = cur->h + 1;
660
661 if (cur->depth != -1)
662 DrawBox(pDC->m_hDC, black, x, y, w, h);
663
664 if (w > 2 && h > 2) {
665 COLORREF color, bright, dark;
666 CBrush brush, bbrush, dbrush;
667 int colortype = (cur->flags & 1) ? theApp.m_settings.folder_color
668 : theApp.m_settings.file_color;
669
670 if (sel && !(cur->flags & 2))
671 color = bright = dark = RGB(0,0,0);
672 else if (cur->depth != -1) {
673 if (colortype == 0) {
674 color = BoxColors[cur->depth & 7];
675 bright = BoxColors[(cur->depth & 7) + 8];
676 dark = BoxColors[(cur->depth & 7) + 16];
677 }
678 else if (colortype == 1) {
679 color = GetSysColor(COLOR_3DFACE);
680 bright = GetSysColor(COLOR_3DHILIGHT);
681 dark = GetSysColor(COLOR_3DSHADOW);
682 }
683 else {
684 color = FixedColors[colortype-2];
685 bright = FixedColors[colortype-2 + 10];
686 dark = FixedColors[colortype-2 + 20];
687 }
688 if (theApp.m_settings.rollover_box) {
689 if (cur->flags & 4) dark = color, color = bright, bright = RGB(255,255,255);
690 else bright = color, color = dark;
691 }
692 }
693 else color = bright = dark = GetSysColor(COLOR_3DFACE);
694
695 brush.CreateSolidBrush(color);
696 bbrush.CreateSolidBrush(bright);
697 dbrush.CreateSolidBrush(dark);
698
699 DrawDualBox(pDC->m_hDC, bbrush, dbrush, x + 1, y + 1, w - 2, h - 2);
700 if (cur->flags & 1) {
701 DrawBox(pDC->m_hDC, brush, x + 2, y + 2, w - 4, h - 4);
702 FillBox(pDC->m_hDC, brush, x + 3, y + 3, w - 6, 9);
703 }
704 else FillBox(pDC->m_hDC, brush, x + 2, y + 2, w - 4, h - 4);
705 }
706
707 if (cur->name != NULL) {
708 CRgn rgn;
709 rgn.CreateRectRgn(x, y, x + w, y + h);
710 pDC->SelectClipRgn(&rgn);
711
712 int len = strlen(cur->name);
713 CSize size;
714 int tx, ty;
715
716 size = pDC->GetTextExtent(cur->name, len);
717 if (size.cx > w - 2 || (cur->flags & 1)) tx = x + 2;
718 else tx = x + (w - size.cx) / 2;
719 if (size.cy > h - 2 || (cur->flags & 1)) ty = y + 1;
720 else ty = y + (h - size.cy) / 2;
721
722 if (cur->flags & 2) {
723 // There's only one free-space block, so we can afford to
724 // be a little less efficient with it.
725 CFolderTree *ft = (CFolderTree *)GetDocument();
726 char buffer[256];
727 CString string;
728 ui64 ts = ft->totalspace;
729 if (ts <= 1) ts = 1;
730 si32 freepercent = (si32)(ft->freespace * (ui64)1000 / ts);
731 string.Format(CurLang->freespace_format, freepercent / 10, freepercent % 10);
732 size = pDC->GetTextExtent(string);
733 if (size.cx > w-2) tx = x + 2;
734 else tx = x + (w - size.cx) / 2;
735 pDC->TextOut(tx, ty-18, string);
736 strcpy(buffer, GetSizeString(ft->freespace, ft->totalspace, 0)+" "+CurLang->free);
737 pDC->TextOut(tx, ty-6, buffer, strlen(buffer));
738 sprintf(buffer, CString(CurLang->files_total)+" %u", ft->numfiles);
739 pDC->TextOut(tx, ty+6, buffer, strlen(buffer));
740 sprintf(buffer, CString(CurLang->folders_total)+" %u", ft->numfolders);
741 pDC->TextOut(tx, ty+15, buffer, strlen(buffer));
742 }
743 else {
744 if (sel) pDC->SetTextColor(RGB(0xFF,0xFF,0xFF));
745 if (!(cur->flags & 1) && h >= 36 && w >= 48) {
746 // Enough room (probably) for the date and file size
747 CString string;
748 CSize size;
749 string.Empty();
750 PrintFileSize(string, cur->source->actualsizes[cur->index]);
751 size = pDC->GetTextExtent(string);
752 if (size.cx > w-2)
753 pDC->TextOut(x+2, ty+1, string);
754 else pDC->TextOut(x+(w-size.cx)/2, ty+1, string);
755 string.Empty();
756 PrintDate(string, cur->source->times[cur->index]);
757 size = pDC->GetTextExtent(string);
758 if (size.cx > w-2)
759 pDC->TextOut(x+2, ty+11, string);
760 else pDC->TextOut(x+(w-size.cx)/2, ty+11, string);
761 ty -= 12;
762 }
763 pDC->TextOut(tx, ty, cur->name, len);
764 if (sel) pDC->SetTextColor(RGB(0,0,0));
765 }
766 pDC->SelectClipRgn(NULL);
767 }
768}
769
770void CFolderView::SetDocument(CFreeDoc *doc)
771{
772 CFreeView::SetDocument(doc);
773
774 if (doc != NULL)
775 rootfolder = ((CFolderTree *)doc)->GetRoot();
776 else rootfolder = NULL;
777 zoomlevel = 0;
778
779 UpdateTitleBar();
780 OnSize(0, m_width, m_height);
781 CDC *dc = GetDC();
782 OnDraw(dc);
783 ReleaseDC(dc);
784}
785
786void CFolderView::OnActivate(UINT nState, CWnd *pWndOther, BOOL bMinimized)
787{
788 if (nState == WA_ACTIVE || nState == WA_CLICKACTIVE)
789 SetPalette();
790}
791
792void CFolderView::SetPalette(void)
793{
794 CDC *dc = GetDC();
795 dc->SelectPalette(&m_palette, 0);
796 dc->RealizePalette();
797 ReleaseDC(dc);
798}
799
800void CFolderView::OnUpdate(CFreeDoc *doc)
801{
802 UpdateTitleBar();
803
804 OnSize(0, m_width, m_height);
805
806 CDC *dc = GetDC();
807 OnDraw(dc);
808 ReleaseDC(dc);
809
810 m_infotipwnd.SetShowDelay(theApp.m_settings.infotip_delay);
811 m_nametipwnd.SetShowDelay(theApp.m_settings.nametip_delay);
812}
813
814void CFolderView::OnSize(UINT nType, int cx, int cy)
815{
816 CRect rect;
817 GetClientRect(&rect);
818 m_width = cx = rect.right - rect.left;
819 m_height = cy = rect.bottom - rect.top;
820
821 ClearDisplayFolders();
822
823 if (rootfolder == NULL) {
824 if (GetDocument() == NULL) return;
825 rootfolder = ((CFolderTree *)GetDocument())->GetRoot();
826 zoomlevel = 0;
827 if (rootfolder == NULL) return;
828 }
829
830 BuildFolderLayout(0, 0, cx - 1, cy - 1, rootfolder, zoomlevel);
831}
832
833CDisplayFolder *CFolderView::AddDisplayFolder(CFolder *source, ui32 index,
834 si32 depth, si16 x, si16 y, si16 w, si16 h, ui32 flags)
835{
836 CDisplayFolder *newfolder = new CDisplayFolder;
837 char c;
838
839 if (source != NULL && index != (ui32)-1) {
840 newfolder->name = source->names[index];
841 c = newfolder->name[0];
842 }
843 else newfolder->name = NULL, c = 0;
844
845 if (c == '*' || c == '<' || c == '>' || c == '?' || c == '|')
846 newfolder->depth = -1, flags |= 2;
847 else newfolder->depth = depth;
848
849 newfolder->flags = flags;
850 newfolder->source = source;
851 newfolder->index = index;
852 newfolder->x = x, newfolder->y = y;
853 newfolder->w = w, newfolder->h = h;
854 newfolder->next = NULL;
855
856 if (displayend == NULL)
857 displayfolders = displayend = newfolder;
858 else
859 displayend = (displayend->next = newfolder);
860
861 return(newfolder);
862}
863
864void CFolderView::ClearDisplayFolders(void)
865{
866 CDisplayFolder *cur = displayfolders, *temp;
867 while (cur != NULL) {
868 temp = cur->next;
869 delete cur;
870 cur = temp;
871 }
872 displayfolders = NULL;
873 displayend = NULL;
874 selected = NULL;
875}
876
877void CFolderView::BuildFolderLayout(int x, int y, int w, int h, CFolder *folder, int depth)
878{
879 unsigned int i;
880
881 if (folder == NULL) return;
882
883 int *indices = new int[folder->cur];
884 for (i = 0; i < folder->cur; i++) indices[i] = i;
885
886 static const int minsizes[][2] = {
887 { 96, 64, },
888 { 64, 48, },
889 { 48, 32, },
890 { 32, 24, },
891 { 24, 16, },
892 { 16, 12, },
893 { 8, 6, },
894 };
895 hmin = minsizes[theApp.m_settings.density + 3][0];
896 vmin = minsizes[theApp.m_settings.density + 3][1];
897
898 SizeFolders(x, y, w, h, folder, indices, (int)folder->cur, depth);
899
900 delete indices;
901}
902
903void CFolderView::SizeFolders(int x, int y, int w, int h, CFolder *folder, int *index, int numindices, int depth)
904{
905 if (folder == NULL) return;
906
907 ui64 totalspace = folder->SizeTotal();
908
909 int *list1 = new int[numindices];
910 int *list2 = new int[numindices];
911 int numlist1, numlist2, largest;
912 si64 list1sum, list2sum, bignum;
913 int x1, y1, w1, h1;
914 int x2, y2, w2, h2;
915 int split;
916
917 // Split the lists evenly. We assume the sizes are sorted
918 // in descending order. Overall, this is a greedy algorithm,
919 // so it should produce fairly good results.
920
921 numlist1 = numlist2 = 0;
922 list1sum = list2sum = 0;
923
924 for (largest = 0; largest < numindices; largest++) {
925 bignum = (si64)folder->sizes[index[largest]];
926 if (folder->names[index[largest]][0] == '<' && !showfreespace)
927 bignum = 0;
928 if (bignum != 0) {
929 if (list1sum <= list2sum) {
930 list1[numlist1++] = index[largest];
931 list1sum += bignum;
932 }
933 else {
934 list2[numlist2++] = index[largest];
935 list2sum += bignum;
936 }
937 }
938 }
939
940 // Don't bother if the files have no space
941 if (list1sum + list2sum <= 0) {
942 delete list1;
943 delete list2;
944 return;
945 }
946
947 // Okay, we're now as even as we can safely get. Now we know how to
948 // split up the space.
949 int wbias, hbias;
950 if (theApp.m_settings.bias > 0)
951 wbias = theApp.m_settings.bias + 8, hbias = 8;
952 else if (theApp.m_settings.bias < 0)
953 hbias = -theApp.m_settings.bias + 8, wbias = 8;
954 else wbias = 8, hbias = 8;
955 if (((w * wbias) / 8) > ((h * hbias) / 8)) {
956 split = (int)(((si64)w * list1sum) / (list1sum + list2sum));
957 x1 = x, y1 = y, w1 = split, h1 = h;
958 x2 = x + split, y2 = y, w2 = w - split, h2 = h;
959 }
960 else {
961 split = (int)(((si64)h * list1sum) / (list1sum + list2sum));
962 x1 = x, y1 = y, w1 = w, h1 = split;
963 x2 = x, y2 = y + split, w2 = w, h2 = h - split;
964 }
965 // Now if a given rectangle has more than one file and is
966 // large enough to be subdivided again, subdivide again
967 if (numlist1 > 1 && w1 > hmin && h1 > vmin)
968 SizeFolders(x1, y1, w1, h1, folder, list1, numlist1, depth);
969 else if (numlist1 > 0) {
970 if (w1 > hmin && h1 > vmin) {
971 AddDisplayFolder(folder, list1[0],
972 depth, x1, y1, w1, h1,
973 (folder->children[list1[0]] != NULL));
974 if (folder->children[list1[0]] != NULL) {
975 if (w1 > hmin && h1 > vmin) {
976 BuildFolderLayout(x1 + 3, y1 + 12, w1 - 6, h1 - 15,
977 folder->children[list1[0]], depth+1);
978 }
979 else AddDisplayFolder(folder, (ui32)-1, depth + 1,
980 x2 + 3, y2 + 12, w2 - 6, h2 - 15, 0);
981 }
982 }
983 else AddDisplayFolder(folder, (ui32)-1, depth, x1, y1, w1, h1, 0);
984 }
985 if (numlist2 > 1 && w2 > hmin && h2 > vmin)
986 SizeFolders(x2, y2, w2, h2, folder, list2, numlist2, depth);
987 else if (numlist2 > 0) {
988 if (w2 > hmin && h2 > vmin) {
989 AddDisplayFolder(folder, list2[0],
990 depth, x2, y2, w2, h2,
991 (folder->children[list2[0]] != NULL));
992 if (folder->children[list2[0]] != NULL) {
993 if (w2 > hmin && h2 > vmin) {
994 BuildFolderLayout(x2 + 3, y2 + 12, w2 - 6, h2 - 15,
995 folder->children[list2[0]], depth+1);
996 }
997 else AddDisplayFolder(folder, (ui32)-1, depth + 1,
998 x2 + 3, y2 + 12, w2 - 6, h2 - 15, 0);
999 }
1000 }
1001 else AddDisplayFolder(folder, (ui32)-1, depth, x2, y2, w2, h2, 0);
1002 }
1003
1004 delete list1;
1005 delete list2;
1006}
1007
1008void CFolderView::ZoomIn(CDisplayFolder *folder)
1009{
1010 CFolderTree *doc = (CFolderTree *)GetDocument();
1011 CFolder *oldroot = rootfolder;
1012
1013 if (folder != NULL && folder->source->children[folder->index] != NULL)
1014 rootfolder = folder->source->children[folder->index];
1015
1016 if (rootfolder == oldroot) return;
1017
1018 CRect start(folder->x, folder->y,
1019 folder->x+folder->w, folder->y+folder->h);
1020 CRect end;
1021 GetClientRect(&end);
1022 end.OffsetRect(-end.left, -end.top);
1023 if (theApp.m_settings.animated_zoom) AnimateBox(start, end);
1024
1025 CFolder *parent = rootfolder->parent;
1026 zoomlevel = 0;
1027 while (parent != NULL) zoomlevel++, parent = parent->parent;
1028 OnUpdate(doc);
1029 UpdateTitleBar();
1030}
1031
1032void CFolderView::ZoomOut(void)
1033{
1034 CFolderTree *doc = (CFolderTree *)GetDocument();
1035 CFolder *oldroot = rootfolder;
1036
1037 if (rootfolder != NULL && rootfolder->parent != NULL)
1038 rootfolder = rootfolder->parent;
1039
1040 if (rootfolder == oldroot) return;
1041
1042 CRect start;
1043 GetClientRect(&start);
1044 start.OffsetRect(-start.left, -start.top);
1045 CRect end;
1046 end.left = end.right = start.right / 2;
1047 end.top = end.bottom = start.bottom / 2;
1048 if (theApp.m_settings.animated_zoom) AnimateBox(start, end);
1049
1050 zoomlevel--;
1051 OnUpdate(doc);
1052 UpdateTitleBar();
1053}
1054
1055void CFolderView::ZoomFull(void)
1056{
1057 CFolderTree *doc = (CFolderTree *)GetDocument();
1058 CFolder *oldroot = rootfolder;
1059
1060 if (doc != NULL)
1061 rootfolder = ((CFolderTree *)doc)->GetRoot();
1062 else rootfolder = NULL;
1063
1064 if (rootfolder == oldroot) return;
1065
1066 CRect start;
1067 GetClientRect(&start);
1068 start.OffsetRect(-start.left, -start.top);
1069 CRect end;
1070 end.left = end.right = start.right / 2;
1071 end.top = end.bottom = start.bottom / 2;
1072 if (theApp.m_settings.animated_zoom) AnimateBox(start, end);
1073
1074 zoomlevel = 0;
1075 OnUpdate(doc);
1076 UpdateTitleBar();
1077}
1078
1079void CFolderView::ShowFreeSpace(BOOL shown)
1080{
1081 if (showfreespace == shown) return;
1082 showfreespace = shown;
1083 OnUpdate(GetDocument());
1084}
1085
1086static void ComputeNewRect(CRect &result, const CRect &start, const CRect &end, ui32 max, ui32 step)
1087{
1088 if (max <= 0) max = 1;
1089 result.left = ((start.left * (max - step)) + (end.left * step)) / max;
1090 result.top = ((start.top * (max - step)) + (end.top * step)) / max;
1091 result.right = ((start.right * (max - step)) + (end.right * step)) / max;
1092 result.bottom = ((start.bottom * (max - step)) + (end.bottom * step)) / max;
1093}
1094
1095static void MinimalRect(CDC *dc, const CRect &rect)
1096{
1097 dc->MoveTo(rect.left, rect.top);
1098 dc->LineTo(rect.right, rect.top);
1099 dc->LineTo(rect.right, rect.bottom);
1100 dc->LineTo(rect.left, rect.bottom);
1101 dc->LineTo(rect.left, rect.top);
1102}
1103
1104void CFolderView::AnimateBox(const CRect &start, const CRect &end)
1105{
1106 // Total time of animation: 400 milliseconds + render time, or
1107 // about a half a second.
1108
1109 ui32 step;
1110 CRect rect = start;
1111 CDC *dc = GetDC();
1112 dc->SetROP2(R2_NOT);
1113 for (step = 0; step < 8; step++) {
1114 ComputeNewRect(rect, start, end, 8, step);
1115 MinimalRect(dc, rect);
1116 Sleep(25);
1117 }
1118 for (step = 0; step < 8; step++) {
1119 ComputeNewRect(rect, start, end, 8, step);
1120 MinimalRect(dc, rect);
1121 Sleep(25);
1122 }
1123 dc->SetROP2(R2_COPYPEN);
1124 ReleaseDC(dc);
1125}
1126
1127void CFolderView::OnIgnoreUpdate(CCmdUI *ui)
1128{
1129 GeneralIgnoreUpdate(ui);
1130}
1131
diff --git a/FolderView.h b/FolderView.h
new file mode 100644
index 0000000..5c5e901
--- /dev/null
+++ b/FolderView.h
@@ -0,0 +1,101 @@
1#ifndef FOLDERVIEW_H
2#define FOLDERVIEW_H
3
4#include "FolderTree.h"
5#include "TipWnd.h"
6
7struct CDisplayFolder {
8 char *name;
9 si32 depth;
10 ui32 flags; // 1=folder
11 CFolder *source;
12 ui32 index;
13 si16 x, y, w, h;
14 CDisplayFolder *next;
15};
16
17class CFolderView : public CFreeView {
18public:
19 CFolderView();
20 DECLARE_DYNCREATE(CFolderView)
21 virtual ~CFolderView();
22
23 virtual void SetDocument(CFreeDoc *doc = NULL);
24 virtual void SetPalette(void);
25
26 void BuildTitleReverse(CFolder *folder, CString &string);
27 CDisplayFolder *GetDisplayFolderFromPoint(const CPoint &point);
28 CDisplayFolder *GetContainerDisplayFolderFromPoint(const CPoint &point);
29 void HighlightPathAtPoint(const CPoint &point);
30
31 void ZoomIn(CDisplayFolder *folder);
32 void ZoomOut(void);
33 void ZoomFull(void);
34 void ShowFreeSpace(BOOL show);
35
36 inline bool IsAnythingOpen(void)
37 { return rootfolder != NULL; }
38 inline bool IsAnythingSelected(void)
39 { return selected != NULL; }
40 inline bool IsSelectedAFolder(void)
41 { return selected != NULL && (selected->flags & 1) != 0; }
42 inline bool IsZoomFull(void)
43 { return zoomlevel == 0; }
44
45 void UpdateTitleBar(void);
46
47 void SelectFolder(CDisplayFolder *cur);
48
49 //{{AFX_VIRTUAL(CFolderView)
50protected:
51 virtual void OnDraw(CDC *pDC);
52 //}}AFX_VIRTUAL
53
54protected:
55 //{{AFX_MSG(CFolderView)
56 afx_msg void OnSize(UINT nType, int cx, int cy);
57 afx_msg void OnLButtonDown(UINT flags, CPoint point);
58 afx_msg void OnLButtonDblClk(UINT flags, CPoint point);
59 afx_msg void OnRButtonUp(UINT flags, CPoint point);
60 afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
61 afx_msg void OnDestroy();
62 afx_msg void OnMouseMove(UINT nFlags, CPoint point);
63 //}}AFX_MSG
64 afx_msg void OnIgnoreUpdate(CCmdUI *ui);
65 BOOL OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT *pResult);
66 afx_msg void OnActivate(UINT nState, CWnd *pWndOther, BOOL bMinimized);
67 DECLARE_MESSAGE_MAP()
68
69public:
70 virtual void OnUpdate(CFreeDoc *doc);
71
72protected:
73 void BuildFolderLayout(int x, int y, int w, int h, CFolder *folder, int depth);
74 void SizeFolders(int x, int y, int w, int h, CFolder *folder, int *index, int numindices, int depth);
75 CDisplayFolder *AddDisplayFolder(CFolder *source, ui32 index,
76 si32 depth, si16 x, si16 y, si16 w, si16 h, ui32 flags);
77 void ClearDisplayFolders(void);
78 void DrawDisplayFolder(CDC *pDC, CDisplayFolder *cur, BOOL selected);
79 void MinimalDrawDisplayFolder(CDC *pDC, CDisplayFolder *cur, BOOL selected);
80 void AnimateBox(const CRect &start, const CRect &end);
81 void SetupInfoTip(CDisplayFolder *cur);
82 void SetupNameTip(CDisplayFolder *cur);
83
84protected:
85 CPalette m_palette;
86 CBrush black, white;
87 CFont minifont;
88 CFolder *rootfolder;
89 CDisplayFolder *displayfolders, *displayend;
90 int vmin, hmin;
91 CTipWnd m_infotipwnd;
92 CTipWnd m_nametipwnd;
93 CDisplayFolder *lastcur;
94
95public:
96 int zoomlevel;
97 CDisplayFolder *selected;
98 BOOL showfreespace;
99};
100
101#endif
diff --git a/Freedoc.cpp b/Freedoc.cpp
new file mode 100644
index 0000000..b7c42b9
--- /dev/null
+++ b/Freedoc.cpp
@@ -0,0 +1,122 @@
1
2#include "stdafx.h"
3
4CFreeDoc::CFreeDoc()
5{
6 m_strTitle = "";
7 m_strPathName = "";
8 m_bModified = 0;
9 m_bCreated = 0;
10}
11
12CFreeDoc::~CFreeDoc()
13{
14 if (m_bCreated) OnDestroy();
15
16 m_bCreated = 0;
17 m_bModified = 0;
18 m_strPathName = "";
19 m_strTitle = "";
20}
21
22BOOL CFreeDoc::Create(void)
23{
24 BOOL createresult;
25
26 m_bModified = 0;
27 m_bCreated = 0;
28 m_strTitle = "";
29 m_strPathName = "";
30
31 createresult = OnCreate();
32
33 m_bCreated = 1;
34
35 return(createresult);
36}
37
38BOOL CFreeDoc::IsModified(void) const
39{
40 return(m_bModified);
41}
42
43void CFreeDoc::SetModifiedFlag(const BOOL modified)
44{
45 m_bModified = modified;
46}
47
48void CFreeDoc::SetTitle(const CString &string)
49{
50 m_strTitle = string;
51}
52
53void CFreeDoc::SetPathName(const CString &string)
54{
55 m_strPathName = string;
56}
57
58UINT CFreeDoc::GetViewCount(void) const
59{
60 return(m_viewList.GetCount());
61}
62
63void CFreeDoc::AddView(CFreeView *view)
64{
65 if (view != NULL) {
66 m_viewList.AddTail((void *)view);
67 OnChangedViewList(view, 1);
68 view->m_document = this;
69 }
70}
71
72void CFreeDoc::RemoveView(CFreeView *view)
73{
74 if (view != NULL) {
75 POSITION pos = m_viewList.Find(view);
76 if (pos != NULL) {
77 m_viewList.RemoveAt(pos);
78 OnChangedViewList(view, 0);
79 }
80 view->m_document = NULL;
81 }
82}
83
84POSITION CFreeDoc::GetFirstViewPosition(void) const
85{
86 return(m_viewList.GetHeadPosition());
87}
88
89CFreeView *CFreeDoc::GetNextView(POSITION &position) const
90{
91 CFreeView *view = (CFreeView *)m_viewList.GetNext(position);
92 return(view);
93}
94
95void CFreeDoc::UpdateAllViews(void)
96{
97 POSITION pos = m_viewList.GetHeadPosition();
98 CFreeView *view;
99
100 while (pos != NULL) {
101 view = (CFreeView *)m_viewList.GetNext(pos);
102 UpdateView(view);
103 }
104}
105
106void CFreeDoc::UpdateView(CFreeView *view)
107{
108 view->OnUpdate(this);
109}
110
111void CFreeDoc::OnChangedViewList(CFreeView *view, BOOL added)
112{
113}
114
115BOOL CFreeDoc::OnCreate(void)
116{
117 return(TRUE);
118}
119
120void CFreeDoc::OnDestroy(void)
121{
122}
diff --git a/Freeview.cpp b/Freeview.cpp
new file mode 100644
index 0000000..1a0c3c5
--- /dev/null
+++ b/Freeview.cpp
@@ -0,0 +1,74 @@
1
2#include "stdafx.h"
3
4IMPLEMENT_DYNCREATE(CFreeView, CWnd)
5
6CFreeView::CFreeView()
7{
8 m_document = NULL;
9}
10
11CFreeView::~CFreeView()
12{
13 if (m_document != NULL)
14 m_document->RemoveView(this);
15}
16
17BEGIN_MESSAGE_MAP(CFreeView, CWnd)
18 //{{AFX_MSG_MAP(CFreeView)
19 ON_WM_SIZE()
20 ON_WM_PAINT()
21 //}}AFX_MSG_MAP
22END_MESSAGE_MAP()
23
24BOOL CFreeView::Create(CWnd *parent, BOOL show)
25{
26 CRect rect;
27
28 if (parent != NULL)
29 parent->GetClientRect(&rect);
30 else {
31 rect.left = 0, rect.right = 16;
32 rect.top = 0, rect.bottom = 16;
33 }
34
35 if (!CWnd::Create(NULL, NULL, WS_CHILD,
36 rect, parent, 0)) return(FALSE);
37 if (show) {
38 ShowWindow(SW_SHOWNORMAL);
39 UpdateWindow();
40 }
41
42 return(TRUE);
43}
44
45void CFreeView::SetDocument(CFreeDoc *document)
46{
47 if (m_document != NULL) m_document->RemoveView(this);
48 if (document != NULL) document->AddView(this);
49}
50
51CFreeDoc *CFreeView::GetDocument(void)
52{
53 return(m_document);
54}
55
56void CFreeView::OnSize(UINT nType, int cx, int cy)
57{
58 CWnd::OnSize(nType, cx, cy);
59 m_width = cx, m_height = cy;
60}
61
62void CFreeView::OnDraw(CDC* pDC)
63{
64}
65
66void CFreeView::OnUpdate(CFreeDoc *doc)
67{
68}
69
70void CFreeView::OnPaint()
71{
72 CPaintDC dc(this);
73 OnDraw(&dc);
74}
diff --git a/Mainfrm.cpp b/Mainfrm.cpp
new file mode 100644
index 0000000..fd86441
--- /dev/null
+++ b/Mainfrm.cpp
@@ -0,0 +1,281 @@
1
2#include "StdAfx.h"
3#include "SpaceMonger.h"
4#include "FolderView.h"
5#include "AboutDialog.h"
6#include "Lang.h"
7
8/////////////////////////////////////////////////////////////////////////////
9// CMainFrame
10
11IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
12
13BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
14 //{{AFX_MSG_MAP(CMainFrame)
15 ON_WM_CREATE()
16 ON_WM_DESTROY()
17 ON_WM_SYSCOMMAND()
18 ON_WM_ERASEBKGND()
19 ON_WM_ACTIVATEAPP()
20 ON_WM_CLOSE()
21 ON_WM_WINDOWPOSCHANGED()
22 ON_WM_SHOWWINDOW()
23 //}}AFX_MSG_MAP
24 ON_UPDATE_COMMAND_UI_RANGE(100, 41000, OnIgnoreUpdate)
25END_MESSAGE_MAP()
26
27CMainFrame::CMainFrame()
28{
29}
30
31CMainFrame::~CMainFrame()
32{
33}
34
35BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
36{
37 CFrameWnd::PreCreateWindow(cs);
38
39 cs.dwExStyle &= ~WS_EX_CLIENTEDGE;
40
41 return(1);
42}
43
44int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
45{
46 if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return(-1);
47
48 HINSTANCE hinst = AfxFindResourceHandle(MAKEINTRESOURCE(ID_SPACEMONGER), RT_ICON);
49 HICON hicon = ::LoadIcon(hinst, MAKEINTRESOURCE(ID_SPACEMONGER));
50 SetIcon(hicon, 1);
51 //SetIcon(hicon, 0);
52
53 if (!m_toolbar.Create(this)) return(-1);
54
55 CMenu *menu = GetSystemMenu(FALSE);
56 menu->AppendMenu(MF_SEPARATOR);
57 menu->AppendMenu(MF_STRING, ID_APP_ABOUT, CString("&")
58 + CurLang->about_spacemonger + "...");
59
60 WINDOWPLACEMENT w;
61 w.length = sizeof(WINDOWPLACEMENT);
62 ::GetWindowPlacement(m_hWnd, &w);
63 theApp.m_settings.rect.left = w.rcNormalPosition.left;
64 theApp.m_settings.rect.top = w.rcNormalPosition.top;
65 theApp.m_settings.rect.right = w.rcNormalPosition.right;
66 theApp.m_settings.rect.bottom = w.rcNormalPosition.bottom;
67 theApp.m_settings.showcmd = w.showCmd;
68
69 RecalcLayout(0);
70
71 return(0);
72}
73
74void CMainFrame::OnDestroy(void)
75{
76 WINDOWPLACEMENT w;
77 w.length = sizeof(WINDOWPLACEMENT);
78 ::GetWindowPlacement(m_hWnd, &w);
79 theApp.m_settings.rect.left = w.rcNormalPosition.left;
80 theApp.m_settings.rect.top = w.rcNormalPosition.top;
81 theApp.m_settings.rect.right = w.rcNormalPosition.right;
82 theApp.m_settings.rect.bottom = w.rcNormalPosition.bottom;
83 theApp.m_settings.showcmd = w.showCmd;
84}
85
86void CMainFrame::OnActivateApp(BOOL bActive, HTASK hTask)
87{
88 if (bActive) {
89 CSpaceMonger *monger = (CSpaceMonger *)AfxGetApp();
90 if (monger != NULL && monger->m_view != NULL) {
91 CFolderView *view = (CFolderView *)monger->m_view;
92 view->OnUpdate(monger->m_document);
93 }
94 }
95 else {
96 CSpaceMonger *monger = (CSpaceMonger *)AfxGetApp();
97 if (monger != NULL && monger->m_view != NULL) {
98 CFolderView *view = (CFolderView *)monger->m_view;
99 view->SelectFolder(NULL);
100 }
101 }
102}
103
104void CMainFrame::RecalcLayout(BOOL bNotify)
105{
106 CRect rectBorder;
107 int numwnds, wndnum, width;
108 CWnd *wnd, *first, *last;
109
110 if (m_bInRecalcLayout || !IsWindow(m_hWnd)
111 || (wnd = GetWindow(GW_CHILD)) == NULL) return;
112
113 m_bInRecalcLayout = TRUE;
114
115 first = wnd->GetWindow(GW_HWNDFIRST);
116 last = wnd->GetWindow(GW_HWNDLAST);
117
118 GetClientRect(&rectBorder);
119 rectBorder.OffsetRect(-rectBorder.left, -rectBorder.top);
120 width = rectBorder.right - rectBorder.left;
121
122 // Position our two toolbars
123 m_toolbar.SetWindowPos(NULL, 0, -2, width, 30,
124 SWP_NOZORDER|SWP_NOACTIVATE);
125 rectBorder.top += 28;
126
127 // First count how many windows need to be rearranged
128 numwnds = 0;
129 if (first != NULL) {
130 wnd = first;
131 while (1) {
132 if (wnd->m_hWnd != m_toolbar.m_hWnd)
133 numwnds++;
134 if (wnd == last) break;
135 wnd = wnd->GetWindow(GW_HWNDNEXT);
136 }
137 }
138
139 // Now lay them all out in a horizontal band (cheap & easy)
140 if (first != NULL && numwnds > 0) {
141 wndnum = 0, wnd = first;
142 while (1) {
143 if (wnd->m_hWnd != m_toolbar.m_hWnd) {
144 wnd->SetWindowPos(NULL, rectBorder.left + (width * wndnum) / numwnds, rectBorder.top,
145 (width * (wndnum+1)) / numwnds - (width * wndnum) / numwnds,
146 rectBorder.bottom - rectBorder.top,
147 SWP_NOZORDER);
148 if (++wndnum == numwnds) break;
149 }
150 wnd = wnd->GetWindow(GW_HWNDNEXT);
151 }
152 }
153
154 m_bInRecalcLayout = FALSE;
155}
156
157void CMainFrame::OnSysCommand(UINT nid, LPARAM lparam)
158{
159 if (nid == ID_APP_ABOUT) {
160 CAboutDialog about;
161 about.DoModal();
162 }
163 else CFrameWnd::OnSysCommand(nid, lparam);
164}
165
166BOOL CMainFrame::OnEraseBkgnd(CDC* pDC)
167{
168#if 0
169 CRect rect;
170 GetClientRect(&rect);
171 FillBox(pDC->m_hDC, ColorFlat, 0, 0,
172 rect.right - rect.left, rect.bottom - rect.top);
173#endif
174 return(-1);
175}
176
177void CMainFrame::OnClose()
178{
179 CFrameWnd::OnClose();
180}
181
182void CMainFrame::OnIgnoreUpdate(CCmdUI *ui)
183{
184 GeneralIgnoreUpdate(ui);
185}
186
187void CMainFrame::OnWindowPosChanged(WINDOWPOS *wp)
188{
189 CFrameWnd::OnWindowPosChanged(wp);
190
191 WINDOWPLACEMENT w;
192 w.length = sizeof(WINDOWPLACEMENT);
193 ::GetWindowPlacement(m_hWnd, &w);
194 theApp.m_settings.rect.left = w.rcNormalPosition.left;
195 theApp.m_settings.rect.top = w.rcNormalPosition.top;
196 theApp.m_settings.rect.right = w.rcNormalPosition.right;
197 theApp.m_settings.rect.bottom = w.rcNormalPosition.bottom;
198 theApp.m_settings.showcmd = w.showCmd;
199}
200
201void CMainFrame::OnShowWindow(BOOL bShow, UINT status)
202{
203 CFrameWnd::OnShowWindow(bShow, status);
204
205 WINDOWPLACEMENT w;
206 w.length = sizeof(WINDOWPLACEMENT);
207 ::GetWindowPlacement(m_hWnd, &w);
208 theApp.m_settings.rect.left = w.rcNormalPosition.left;
209 theApp.m_settings.rect.top = w.rcNormalPosition.top;
210 theApp.m_settings.rect.right = w.rcNormalPosition.right;
211 theApp.m_settings.rect.bottom = w.rcNormalPosition.bottom;
212 theApp.m_settings.showcmd = w.showCmd;
213}
214
215/////////////////////////////////////////////////////////////////////////////
216
217IMPLEMENT_DYNCREATE(CMainToolBar, CToolBar)
218
219BEGIN_MESSAGE_MAP(CMainToolBar, CToolBar)
220 //{{AFX_MSG_MAP(CMainToolBar)
221 //}}AFX_MSG_MAP
222 ON_UPDATE_COMMAND_UI_RANGE(100, 41000, OnIgnoreUpdate)
223END_MESSAGE_MAP()
224
225CMainToolBar::CMainToolBar()
226{
227}
228
229CMainToolBar::~CMainToolBar()
230{
231}
232
233int CMainToolBar::Create(CWnd *parent)
234{
235 if (!CToolBar::Create(parent, WS_CHILD|WS_VISIBLE|CBRS_TOP, IDR_TOOLBAR_EN)) return 0;
236 if (!LoadToolBar(CurLang->toolbar_bitmap_id)) return 0;
237
238 EnableState(ViewFree, 1);
239
240 return 1;
241}
242
243void CMainToolBar::EnableState(int state, BOOL enabled)
244{
245 switch (state) {
246 case CMainToolBar::ViewFree:
247 SetButtonStyle(CommandToIndex(ID_VIEW_FREE), enabled ? TBBS_BUTTON|TBBS_PRESSED : TBBS_BUTTON);
248 break;
249 default:
250 break;
251 }
252}
253
254void CMainToolBar::UpdateButtonsForView(CFolderView *view)
255{
256 CSpaceMonger *app = (CSpaceMonger *)AfxGetApp();
257 CToolBarCtrl &ctrl = this->GetToolBarCtrl();
258 ctrl.EnableButton(ID_FILE_RUN, view->IsAnythingOpen() && view->IsAnythingSelected());
259 ctrl.EnableButton(ID_FILE_DELETE, !app->m_settings.disable_delete
260 && view->IsAnythingOpen() && view->IsAnythingSelected());
261 ctrl.EnableButton(ID_FILE_OPEN, 1);
262 ctrl.EnableButton(ID_FILE_REFRESH, view->IsAnythingOpen());
263 ctrl.EnableButton(ID_VIEW_ZOOM_FULL, view->IsAnythingOpen() && !view->IsZoomFull());
264 ctrl.EnableButton(ID_VIEW_ZOOM_OUT, view->IsAnythingOpen() && !view->IsZoomFull());
265 ctrl.EnableButton(ID_VIEW_ZOOM_IN, view->IsAnythingOpen() && view->IsAnythingSelected()
266 && view->IsSelectedAFolder());
267 ctrl.EnableButton(ID_VIEW_FREE, view->IsAnythingOpen());
268 ctrl.EnableButton(ID_SETTINGS, 1);
269 ctrl.EnableButton(ID_APP_ABOUT, 1);
270}
271
272void CMainToolBar::OnIgnoreUpdate(CCmdUI *ui)
273{
274 GeneralIgnoreUpdate(ui);
275}
276
277void CMainToolBar::Reload(void)
278{
279 LoadToolBar(CurLang->toolbar_bitmap_id);
280 RedrawWindow();
281}
diff --git a/Mainfrm.h b/Mainfrm.h
new file mode 100644
index 0000000..899326a
--- /dev/null
+++ b/Mainfrm.h
@@ -0,0 +1,59 @@
1
2#ifndef CMAINFRAME_H
3#define CMAINFRAME_H
4
5class CMainToolBar : public CToolBar {
6public:
7 CMainToolBar();
8 virtual ~CMainToolBar();
9 DECLARE_DYNCREATE(CMainToolBar)
10
11 virtual int Create(CWnd *parent);
12
13 enum {
14 NoState = 0,
15 ViewFree,
16 };
17
18 virtual void EnableState(int state, BOOL enabled);
19 void UpdateButtonsForView(class CFolderView *view);
20
21 void Reload(void);
22
23protected:
24 //{{AFX_MSG(CMainToolBar)
25 afx_msg void OnIgnoreUpdate(CCmdUI *ui);
26 //}}AFX_MSG
27 DECLARE_MESSAGE_MAP()
28
29};
30
31class CMainFrame : public CFrameWnd {
32public:
33 CMainFrame();
34 virtual ~CMainFrame();
35 DECLARE_DYNCREATE(CMainFrame)
36 BOOL PreCreateWindow(CREATESTRUCT& cs);
37
38 virtual void RecalcLayout(BOOL bNotify);
39
40protected:
41 //{{AFX_MSG(CMainFrame)
42 afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
43 afx_msg void OnDestroy(void);
44 afx_msg void OnSysCommand(UINT nid, LPARAM lparam);
45 afx_msg void OnClose();
46 afx_msg void OnActivateApp(BOOL bActive, HTASK hTask);
47 afx_msg BOOL OnEraseBkgnd(CDC* pDC);
48 afx_msg void OnWindowPosChanged(WINDOWPOS *wp);
49 afx_msg void OnShowWindow(BOOL bShow, UINT status);
50 //}}AFX_MSG
51 afx_msg void OnIgnoreUpdate(CCmdUI *ui);
52 DECLARE_MESSAGE_MAP()
53
54public:
55 CMainToolBar m_toolbar;
56};
57
58#endif
59
diff --git a/README.TXT b/README.TXT
new file mode 100644
index 0000000..4001b0a
--- /dev/null
+++ b/README.TXT
@@ -0,0 +1,185 @@
1
2SpaceMonger Version 1.4.0
3-------------------------
4
5
6INTRODUCTION
7------------
8
9SpaceMonger is a free tool for keeping track of the disk space on your
10computer. Instead of viewing your disk as unhelpful little icons or
11pie charts, you see a single picture that shows you at a glance how
12much space every file and folder are using.
13
14The latest version of SpaceMonger is always available at its web page:
15
16 http://www.werkema.com/software/spacemonger.html
17
18
19SYSTEM REQUIREMENTS
20-------------------
21
22SpaceMonger should run on any version of Windows 95, 98, or NT. It has
23been tested on all three. It will probably run fine on Windows 2000, but
24has not been officially tested on Windows 2000. It should be able to run
25on any computer that can run Windows 95, 98, or NT; there are no
26additional space or memory requirements, although we do recommend you have
27at least 4 megabytes of memory installed in your computer if you want it
28to run efficiently.
29
30
31INSTALLATION
32------------
33
34Unpack the .ZIP archive. A single Windows executable will be produced,
35named "SpaceMonger.exe", along with "README.TXT", which is what you're
36reading now. The "SpaceMonger.exe" file is the complete program, and it
37can be moved into any folder you like. (We recommend "C:\Program Files",
38but you don't have to put it there.)
39
40Double-click on it to run it.
41
42
43NOTE TO WINDOWS 2000 USERS:
44---------------------------
45
46SpaceMonger will run on Windows 2000. However, version 1.4.0 will NOT
47correctly report space used by hard links, junction points, or sparse
48files. So if you use Windows 2000, here is what you should expect:
49
50 * Hard linked files will exist in both places: There will appear
51 to be a full copy of the file everywhere a hard link exists,
52 so these files will get over-counted.
53 * Junction points and mount points will be treated as though they
54 are real folders, so their contents will be over-counted as well.
55 * Sparse files will not be treated as sparse: If you have a
56 10-megabyte sparse file that really only uses one megabyte of
57 disk space, it will still be counted as 10 megabytes.
58
59Our crack research team is investigating these problems and should be
60able to resolve some of them soon.
61
62
63FIRST-TIME INSTRUCTIONS
64-----------------------
65
66SpaceMonger is not a hard program to use. In fact, you probably won't
67need any instructions. But for those of you who like to read, here are
68some first-time instructions:
69
70When you first open SpaceMonger, you will initially be presented with a
71blank window. Click "Open". Click on a drive, like drive "C", and hit
72"OK". Wait patiently while the program collects statistics on your
73drive. My, don't you have a lot of files!
74
75SpaceMonger will show you the contents of your drive as little
76rectangles. The larger the rectangle, the more space something is taking
77up. Rectangles that have other rectangles in them are folders.
78Rectangles with no other rectangles in them are files. Colors are used
79to show how deeply the files and folders are nested.
80
81You can get more information on a given folder by clicking on its title
82and then clicking "Zoom In" (or by double-clicking on its title). The
83window will change to show a larger, more detailed view of the folder
84and its files. You can zoom in as many times as you want. "Zoom Out"
85will take you back out (up) by one folder. "Zoom Full" will take you
86all the way back to show the whole drive.
87
88If you see a file or folder you want to delete, click it to select it
89and hit "Delete". It will be moved to the Recycle Bin. If you want to
90see what it is first, click on it and hit "Run or Open", which will try
91to run it if is a program or open it if it is a file.
92
93DISCLAIMER: If you don't know what something is, DON'T DELETE IT.
94 Deleting things at random is a good way to break your programs or
95 Windows itself or worse. 'Nuff said.
96
97If you click the "Setup" button, you can change some aesthetic things
98about the program. You can't damage anything with the Setup dialog box,
99so feel free to try various options until you like how SpaceMonger looks
100and feels.
101
102In addition, you can right-click on a folder or a file to bring up a
103context-sensitive menu of options that are identical to those on the
104toolbar. This may be more efficient for some users.
105
106If you double-click on a folder, SpaceMonger will zoom in on it. If you
107double-click on a file (either a program or a document), SpaceMonger
108will attempt to run it or open it, whichever is suitable.
109
110
111DISTRIBUTION
112------------
113
114SpaceMonger is freeware, not crippled or time-limited in any way. You
115can distribute it any way you like. You can even sell it, but the latest
116copy will always be available for free download at SpaceMonger's web page,
117so you probably won't be able to get much money for it. We encourage
118users of the program to give away copies to their friends.
119
120
121WHAT'S NEW
122----------
123
124Between 1.3.5 and 1.4.0
125 * Internals rewritten to support multiple foreign langauges.
126 Currently foreign language support exists for British English,
127 American English, and French (possibly with grammar errors).
128 * Supports popup info-tips that can display the full filename, the
129 icon, the date, size, and attributes of any file or folder.
130 * Supports popup name-tips that prevent names from being obscured
131 by not having enough space to display them.
132 * Open dialog box now uses large icons.
133 * Includes rollover boxes that highlight the current folder.
134 * Files display their sizes and dates if there is enough room.
135 * Option to save the current window position.
136 * Fixed zero-size bug that caused divide-by-zero errors with some
137 Audio CD disks.
138 * Minor changes to color palette to handle rollover boxes.
139 * Support for Windows Property dialog box.
140 * Numerous other bug fixes.
141 * Support for Windows NT junction points.
142
143Between 1.3.4 and 1.3.5
144 * Toolbar buttons gray out when you can't use them.
145 * Setup option to disable the "Delete" button.
146 * Fixed size-computation routine that was oversizing
147 files on some systems.
148 * Double-clicking on files runs or opens them; double-clicking
149 on folders zooms in on them.
150 * Scanning now includes a percent bar so you can tell how
151 long it's taking.
152
153Between 1.3.0 and 1.3.4
154 * Major speed improvements using new memory manager subsystem.
155 Runs twice as fast and uses half the memory of 1.3.0.
156 * Better display of free space information.
157 * Right-click opens a pop-up menu of options.
158 * Double-click zooms in on a folder.
159 * Few minor bug-fixes.
160 * Replaced old "Scanning..." window with a better one.
161
162Between 1.2.0 and 1.3.0
163 * Added the Setup button with a whole bunch of new options.
164 * Internal bug-fixes to scanning routine.
165
166Between 1.0.2 and 1.2.0
167 * Lots of stuff. 1.1.0 was never released. New buttons,
168 new look, better code. Replaced most of what's under
169 the hood.
170 * 1.2.0 was released for private use only.
171
172Between 1.0.0 and 1.0.2
173 * Miscellaneous bug fixes.
174 * Added "Zoom In" and "Zoom Out" buttons.
175 * Added "Run or Open" and "Delete" buttons.
176
177
178COPYRIGHT AND CONTACT INFORMATION
179---------------------------------
180
181SpaceMonger is Copyright (C) 1998, 1999, and 2000 by Sean Werkema.
182Have questions? Found a bug? Want a feature? Compose your thoughts in
183an e-mail and send them to sean@werkema.com. I should be able to respond
184within a few days of your message.
185
diff --git a/SetupDlg.cpp b/SetupDlg.cpp
new file mode 100644
index 0000000..eb44ab7
--- /dev/null
+++ b/SetupDlg.cpp
@@ -0,0 +1,310 @@
1
2#include "stdafx.h"
3#include "spacemonger.h"
4#include "Lang.h"
5#include "SetupDlg.h"
6
7IMPLEMENT_DYNCREATE(CSettingsDialog, CDialog)
8
9BEGIN_MESSAGE_MAP(CSettingsDialog, CDialog)
10 //{{AFX_MSG_MAP(CSettingsDialog)
11 ON_BN_CLICKED(IDC_SHOW_NAME_TIPS, OnShowNameTips)
12 ON_BN_CLICKED(IDC_SHOW_INFO_TIPS, OnShowInfoTips)
13 ON_CBN_SELENDOK(IDC_LANG, OnLang)
14 //}}AFX_MSG_MAP
15END_MESSAGE_MAP()
16
17CSettingsDialog::CSettingsDialog(CWnd *parent)
18 : CDialog(IDD_SETTINGS, parent)
19{
20}
21
22CSettingsDialog::~CSettingsDialog()
23{
24}
25
26void CSettingsDialog::OnCancel(void)
27{
28 theApp.m_settings.lang[0] = oldlang[0];
29 theApp.m_settings.lang[1] = oldlang[1];
30 theApp.m_settings.lang[2] = oldlang[2];
31 theApp.m_settings.lang[3] = oldlang[3];
32 CurLang = oldlangptr;
33
34 CDialog::OnCancel();
35}
36
37void CSettingsDialog::OnOK(void)
38{
39 CComboBox *density = (CComboBox *)GetDlgItem(IDC_DENSITY);
40 if (density != NULL)
41 theApp.m_settings.density = density->GetCurSel()-3;
42 CComboBox *file_color = (CComboBox *)GetDlgItem(IDC_FILE_COLOR);
43 if (file_color != NULL)
44 theApp.m_settings.file_color = file_color->GetCurSel();
45 CComboBox *folder_color = (CComboBox *)GetDlgItem(IDC_FOLDER_COLOR);
46 if (folder_color != NULL)
47 theApp.m_settings.folder_color = folder_color->GetCurSel();
48 CButton *auto_rescan = (CButton *)GetDlgItem(IDC_AUTO_RESCAN);
49 if (auto_rescan != NULL)
50 theApp.m_settings.auto_rescan = auto_rescan->GetCheck();
51 CButton *animated = (CButton *)GetDlgItem(IDC_ANIMATED);
52 if (animated != NULL)
53 theApp.m_settings.animated_zoom = animated->GetCheck();
54 CButton *disable_delete = (CButton *)GetDlgItem(IDC_DISABLE_DELETE);
55 if (disable_delete != NULL)
56 theApp.m_settings.disable_delete = disable_delete->GetCheck();
57 CSliderCtrl *bias = (CSliderCtrl *)GetDlgItem(IDC_BIAS);
58 if (bias != NULL)
59 theApp.m_settings.bias = bias->GetPos()-20;
60 CButton *save_pos = (CButton *)GetDlgItem(IDC_SAVE_POS);
61 if (save_pos != NULL)
62 theApp.m_settings.save_pos = save_pos->GetCheck();
63
64 CButton *show_tips = (CButton *)GetDlgItem(IDC_SHOW_NAME_TIPS);
65 if (show_tips != NULL)
66 theApp.m_settings.show_name_tips = show_tips->GetCheck();
67 show_tips = (CButton *)GetDlgItem(IDC_SHOW_ROLLOVER_BOX);
68 if (show_tips != NULL)
69 theApp.m_settings.rollover_box = show_tips->GetCheck();
70 show_tips = (CButton *)GetDlgItem(IDC_SHOW_INFO_TIPS);
71 if (show_tips != NULL)
72 theApp.m_settings.show_info_tips = show_tips->GetCheck();
73
74 CButton *tip;
75 theApp.m_settings.infotip_flags = 0;
76 CEdit *nametipdelay = (CEdit *)GetDlgItem(IDC_NAMETIP_DELAY);
77 if (nametipdelay != NULL) {
78 CString string;
79 nametipdelay->GetWindowText(string);
80 theApp.m_settings.nametip_delay = atoi(string);
81 }
82
83 if ((tip = (CButton *)GetDlgItem(IDC_INFOTIP_PATH)) != NULL && tip->GetCheck())
84 theApp.m_settings.infotip_flags |= TIP_PATH;
85 if ((tip = (CButton *)GetDlgItem(IDC_INFOTIP_NAME)) != NULL && tip->GetCheck())
86 theApp.m_settings.infotip_flags |= TIP_NAME;
87 if ((tip = (CButton *)GetDlgItem(IDC_INFOTIP_SIZE)) != NULL && tip->GetCheck())
88 theApp.m_settings.infotip_flags |= TIP_SIZE;
89 if ((tip = (CButton *)GetDlgItem(IDC_INFOTIP_DATE)) != NULL && tip->GetCheck())
90 theApp.m_settings.infotip_flags |= TIP_DATE;
91 if ((tip = (CButton *)GetDlgItem(IDC_INFOTIP_ATTRIB)) != NULL && tip->GetCheck())
92 theApp.m_settings.infotip_flags |= TIP_ATTRIB;
93 if ((tip = (CButton *)GetDlgItem(IDC_INFOTIP_ICON)) != NULL && tip->GetCheck())
94 theApp.m_settings.infotip_flags |= TIP_ICON;
95 CEdit *infotipdelay = (CEdit *)GetDlgItem(IDC_INFOTIP_DELAY);
96 if (infotipdelay != NULL) {
97 CString string;
98 infotipdelay->GetWindowText(string);
99 theApp.m_settings.infotip_delay = atoi(string);
100 }
101
102 CDialog::OnOK();
103}
104
105void CSettingsDialog::OnShowNameTips(void)
106{
107 CButton *show_tips = (CButton *)GetDlgItem(IDC_SHOW_NAME_TIPS);
108 if (show_tips != NULL)
109 EnableNameTipButtons(show_tips->GetCheck());
110}
111
112void CSettingsDialog::OnShowInfoTips(void)
113{
114 CButton *show_tips = (CButton *)GetDlgItem(IDC_SHOW_INFO_TIPS);
115 if (show_tips != NULL)
116 EnableInfoTipButtons(show_tips->GetCheck());
117}
118
119void CSettingsDialog::EnableNameTipButtons(BOOL bEnable)
120{
121 CWnd *wnd;
122 if ((wnd = GetDlgItem(IDC_STATIC_NAMETIP1)) != NULL)
123 wnd->EnableWindow(bEnable);
124 if ((wnd = GetDlgItem(IDC_NAMETIP_DELAY)) != NULL)
125 wnd->EnableWindow(bEnable);
126 if ((wnd = GetDlgItem(IDC_STATIC_NAMETIP2)) != NULL)
127 wnd->EnableWindow(bEnable);
128}
129
130void CSettingsDialog::EnableInfoTipButtons(BOOL bEnable)
131{
132 CWnd *wnd;
133 if ((wnd = GetDlgItem(IDC_INFOTIP_PATH)) != NULL)
134 wnd->EnableWindow(bEnable);
135 if ((wnd = GetDlgItem(IDC_INFOTIP_NAME)) != NULL)
136 wnd->EnableWindow(bEnable);
137 if ((wnd = GetDlgItem(IDC_INFOTIP_DATE)) != NULL)
138 wnd->EnableWindow(bEnable);
139 if ((wnd = GetDlgItem(IDC_INFOTIP_SIZE)) != NULL)
140 wnd->EnableWindow(bEnable);
141 if ((wnd = GetDlgItem(IDC_INFOTIP_ATTRIB)) != NULL)
142 wnd->EnableWindow(bEnable);
143 if ((wnd = GetDlgItem(IDC_INFOTIP_ICON)) != NULL)
144 wnd->EnableWindow(bEnable);
145 if ((wnd = GetDlgItem(IDC_STATIC_INFOTIP1)) != NULL)
146 wnd->EnableWindow(bEnable);
147 if ((wnd = GetDlgItem(IDC_INFOTIP_DELAY)) != NULL)
148 wnd->EnableWindow(bEnable);
149 if ((wnd = GetDlgItem(IDC_STATIC_INFOTIP2)) != NULL)
150 wnd->EnableWindow(bEnable);
151}
152
153void CSettingsDialog::OnLang(void)
154{
155 CComboBox *lang = (CComboBox *)GetDlgItem(IDC_LANG);
156 if (lang == NULL) return;
157 int index = lang->GetCurSel();
158 theApp.m_settings.lang[0] = Langs[index].abbrev[0];
159 theApp.m_settings.lang[1] = Langs[index].abbrev[1];
160 theApp.m_settings.lang[2] = '\0';
161 theApp.m_settings.lang[3] = '\0';
162 CurLang = Langs[index].text;
163 UpdateDialogForNewLanguage();
164}
165
166void CSettingsDialog::UpdateDialogForNewLanguage(void)
167{
168 CComboBox *lang = (CComboBox *)GetDlgItem(IDC_LANG);
169 if (lang != NULL) lang->ResetContent();
170 CComboBox *density = (CComboBox *)GetDlgItem(IDC_DENSITY);
171 if (density != NULL) density->ResetContent();
172 CComboBox *file_color = (CComboBox *)GetDlgItem(IDC_FILE_COLOR);
173 if (file_color != NULL) file_color->ResetContent();
174 CComboBox *folder_color = (CComboBox *)GetDlgItem(IDC_FOLDER_COLOR);
175 if (folder_color != NULL) folder_color->ResetContent();
176
177 int i;
178
179 SetWindowText(CurLang->settings);
180 SetDlgItemText(IDOK, CurLang->ok);
181 SetDlgItemText(IDCANCEL, CurLang->cancel);
182
183 SetDlgItemText(IDC_STATIC_LAYOUT, CurLang->layout);
184 SetDlgItemText(IDC_STATIC_DENSITY, CurLang->density);
185 SetDlgItemText(IDC_STATIC_BIAS, CurLang->bias);
186 SetDlgItemText(IDC_STATIC_HORZ, CurLang->horz);
187 SetDlgItemText(IDC_STATIC_EQUAL, CurLang->equal);
188 SetDlgItemText(IDC_STATIC_VERT, CurLang->vert);
189 SetDlgItemText(IDC_STATIC_DISPLAYCOLORS, CurLang->displaycolors);
190 SetDlgItemText(IDC_STATIC_FILES, CurLang->files);
191 SetDlgItemText(IDC_STATIC_FOLDERS, CurLang->folders);
192 SetDlgItemText(IDC_STATIC_TOOLTIPS, CurLang->tooltips);
193 SetDlgItemText(IDC_STATIC_MISCOPTIONS, CurLang->miscoptions);
194 SetDlgItemText(IDC_SHOW_NAME_TIPS, CurLang->shownametips);
195 SetDlgItemText(IDC_SHOW_ROLLOVER_BOX, CurLang->showrolloverbox);
196 SetDlgItemText(IDC_SHOW_INFO_TIPS, CurLang->showinfotips);
197 SetDlgItemText(IDC_INFOTIP_PATH, CurLang->fullpath);
198 SetDlgItemText(IDC_INFOTIP_NAME, CurLang->filename);
199 SetDlgItemText(IDC_INFOTIP_ICON, CurLang->icon);
200 SetDlgItemText(IDC_INFOTIP_DATE, CurLang->datetime);
201 SetDlgItemText(IDC_INFOTIP_SIZE, CurLang->filesize);
202 SetDlgItemText(IDC_INFOTIP_ATTRIB, CurLang->attrib);
203 SetDlgItemText(IDC_STATIC_NAMETIP1, CurLang->delay);
204 SetDlgItemText(IDC_STATIC_NAMETIP2, CurLang->msec);
205 SetDlgItemText(IDC_STATIC_INFOTIP1, CurLang->delay);
206 SetDlgItemText(IDC_STATIC_INFOTIP2, CurLang->msec);
207 SetDlgItemText(IDC_AUTO_RESCAN, CurLang->autorescan);
208 SetDlgItemText(IDC_DISABLE_DELETE, CurLang->disabledelete);
209 SetDlgItemText(IDC_ANIMATED, CurLang->animatedzoom);
210 SetDlgItemText(IDC_SAVE_POS, CurLang->savepos);
211
212 if (lang != NULL) {
213 for (i = 0; Langs[i].name != NULL; i++) {
214 lang->AddString(Langs[i].name);
215 if (Langs[i].abbrev[0] == theApp.m_settings.lang[0]
216 && Langs[i].abbrev[1] == theApp.m_settings.lang[1])
217 lang->SetCurSel(i);
218 }
219 }
220
221 if (density != NULL) {
222 for (i = 0; i < 6; i++)
223 density->AddString(CurLang->densitynames[i]);
224 density->SetCurSel(theApp.m_settings.density+3);
225 }
226 if (file_color != NULL) {
227 for (i = 0; i < 12; i++)
228 file_color->AddString(CurLang->colornames[i]);
229 file_color->SetCurSel(theApp.m_settings.file_color);
230 }
231 if (folder_color != NULL) {
232 for (i = 0; i < 12; i++)
233 folder_color->AddString(CurLang->colornames[i]);
234 folder_color->SetCurSel(theApp.m_settings.folder_color);
235 }
236 CButton *auto_rescan = (CButton *)GetDlgItem(IDC_AUTO_RESCAN);
237 if (auto_rescan != NULL)
238 auto_rescan->SetCheck(theApp.m_settings.auto_rescan);
239 CButton *animated = (CButton *)GetDlgItem(IDC_ANIMATED);
240 if (animated != NULL)
241 animated->SetCheck(theApp.m_settings.animated_zoom);
242 CButton *disable_delete = (CButton *)GetDlgItem(IDC_DISABLE_DELETE);
243 if (disable_delete != NULL)
244 disable_delete->SetCheck(theApp.m_settings.disable_delete);
245 CButton *save_pos = (CButton *)GetDlgItem(IDC_SAVE_POS);
246 if (save_pos != NULL)
247 save_pos->SetCheck(theApp.m_settings.save_pos);
248
249 CButton *show_name_tips = (CButton *)GetDlgItem(IDC_SHOW_NAME_TIPS);
250 if (show_name_tips != NULL)
251 show_name_tips->SetCheck(theApp.m_settings.show_name_tips);
252 show_name_tips = (CButton *)GetDlgItem(IDC_SHOW_ROLLOVER_BOX);
253 if (show_name_tips != NULL)
254 show_name_tips->SetCheck(theApp.m_settings.rollover_box);
255
256 CButton *tip;
257 CButton *show_info_tips = (CButton *)GetDlgItem(IDC_SHOW_INFO_TIPS);
258 if (show_info_tips != NULL)
259 show_info_tips->SetCheck(theApp.m_settings.show_info_tips);
260 if ((tip = (CButton *)GetDlgItem(IDC_INFOTIP_PATH)) != NULL)
261 tip->SetCheck((theApp.m_settings.infotip_flags & TIP_PATH) != 0);
262 if ((tip = (CButton *)GetDlgItem(IDC_INFOTIP_NAME)) != NULL)
263 tip->SetCheck((theApp.m_settings.infotip_flags & TIP_NAME) != 0);
264 if ((tip = (CButton *)GetDlgItem(IDC_INFOTIP_DATE)) != NULL)
265 tip->SetCheck((theApp.m_settings.infotip_flags & TIP_DATE) != 0);
266 if ((tip = (CButton *)GetDlgItem(IDC_INFOTIP_SIZE)) != NULL)
267 tip->SetCheck((theApp.m_settings.infotip_flags & TIP_SIZE) != 0);
268 if ((tip = (CButton *)GetDlgItem(IDC_INFOTIP_ATTRIB)) != NULL)
269 tip->SetCheck((theApp.m_settings.infotip_flags & TIP_ATTRIB) != 0);
270 if ((tip = (CButton *)GetDlgItem(IDC_INFOTIP_ICON)) != NULL)
271 tip->SetCheck((theApp.m_settings.infotip_flags & TIP_ICON) != 0);
272
273 CEdit *tipdelay = (CEdit *)GetDlgItem(IDC_NAMETIP_DELAY);
274 if (tipdelay != NULL) {
275 CString string;
276 string.Format("%u", theApp.m_settings.nametip_delay);
277 tipdelay->SetWindowText(string);
278 }
279 tipdelay = (CEdit *)GetDlgItem(IDC_INFOTIP_DELAY);
280 if (tipdelay != NULL) {
281 CString string;
282 string.Format("%u", theApp.m_settings.infotip_delay);
283 tipdelay->SetWindowText(string);
284 }
285 EnableNameTipButtons(theApp.m_settings.show_name_tips);
286 EnableInfoTipButtons(theApp.m_settings.show_info_tips);
287
288 CSliderCtrl *bias = (CSliderCtrl *)GetDlgItem(IDC_BIAS);
289 if (bias != NULL) {
290 bias->SetRange(0, 40, 0);
291 bias->SetPos(theApp.m_settings.bias+20);
292 bias->SetTicFreq(5);
293 }
294}
295
296BOOL CSettingsDialog::OnInitDialog()
297{
298 oldlang[0] = theApp.m_settings.lang[0];
299 oldlang[1] = theApp.m_settings.lang[1];
300 oldlang[2] = theApp.m_settings.lang[2];
301 oldlang[3] = theApp.m_settings.lang[3];
302 oldlangptr = CurLang;
303
304 UpdateDialogForNewLanguage();
305
306 CDialog::OnInitDialog();
307
308 return TRUE;
309}
310
diff --git a/SetupDlg.h b/SetupDlg.h
new file mode 100644
index 0000000..f181d21
--- /dev/null
+++ b/SetupDlg.h
@@ -0,0 +1,32 @@
1
2#ifndef SETTINGSDIALOG_H
3#define SETTINGSDIALOG_H
4
5class CSettingsDialog : public CDialog {
6public:
7 CSettingsDialog(CWnd *parent = NULL);
8 DECLARE_DYNCREATE(CSettingsDialog)
9 virtual ~CSettingsDialog();
10
11protected:
12 //{{AFX_MSG(CSettingsDialog)
13 virtual void OnOK();
14 virtual void OnCancel();
15 virtual void OnShowNameTips();
16 virtual void OnShowInfoTips();
17 virtual void OnLang();
18 //}}AFX_MSG
19 DECLARE_MESSAGE_MAP()
20
21 void UpdateDialogForNewLanguage(void);
22
23 virtual BOOL OnInitDialog();
24 void EnableNameTipButtons(BOOL bEnable);
25 void EnableInfoTipButtons(BOOL bEnable);
26
27protected:
28 char oldlang[4];
29 Lang *oldlangptr;
30};
31
32#endif
diff --git a/SpaceMonger.cpp b/SpaceMonger.cpp
new file mode 100644
index 0000000..e3df885
--- /dev/null
+++ b/SpaceMonger.cpp
@@ -0,0 +1,527 @@
1
2#include "StdAfx.h"
3#include "SpaceMonger.h"
4#include "Lang.h"
5#include "MainFrm.h"
6#include "FolderTree.h"
7#include "FolderView.h"
8#include "DriveDialog.h"
9#include "SetupDlg.h"
10#include "TipWnd.h"
11#include "AboutDialog.h"
12
13/////////////////////////////////////////////////////////////////////////////
14// The primary CSpaceMonger object
15
16CSpaceMonger theApp;
17
18/////////////////////////////////////////////////////////////////////////////
19// CApp
20
21BEGIN_MESSAGE_MAP(CSpaceMonger, CWinApp)
22 //{{AFX_MSG_MAP(CSpaceMonger)
23 ON_COMMAND(ID_APP_ABOUT, OnAbout)
24 ON_COMMAND(ID_APP_EXIT, OnAppExit)
25 ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
26 ON_COMMAND(ID_FILE_REFRESH, OnFileRefresh)
27 ON_COMMAND(ID_FILE_RUN, OnFileRun)
28 ON_COMMAND(ID_FILE_DELETE, OnFileDelete)
29 ON_COMMAND(ID_FILE_PROPERTIES, OnFileProperties)
30 ON_COMMAND(ID_VIEW_ZOOM_FULL, OnZoomFull)
31 ON_COMMAND(ID_VIEW_ZOOM_IN, OnZoomIn)
32 ON_COMMAND(ID_VIEW_ZOOM_OUT, OnZoomOut)
33 ON_COMMAND(ID_VIEW_FREE, OnShowFree)
34 ON_COMMAND(ID_SETTINGS, OnSettings)
35 //}}AFX_MSG_MAP
36 ON_UPDATE_COMMAND_UI_RANGE(100, 41000, OnIgnoreUpdate)
37END_MESSAGE_MAP()
38
39CSpaceMonger::CSpaceMonger()
40{
41 m_document = NULL;
42}
43
44CSpaceMonger::~CSpaceMonger()
45{
46}
47
48BOOL CSpaceMonger::InitInstance()
49{
50 int i;
51
52 InitTipWnd(AfxGetInstanceHandle());
53
54 // Load in the settings from the Registry. If there were no settings,
55 // we load defaults. Once we've got them, save them back, which sounds
56 // odd, but it will end up creating the necessary entries if they don't
57 // exist.
58 m_settings.Load();
59 m_settings.Save();
60
61 int showcmd = m_settings.showcmd;
62 RECT rect = m_settings.rect;
63 if (!m_settings.save_pos) {
64 showcmd = SW_SHOWNORMAL;
65 rect.top = rect.left = CW_USEDEFAULT;
66 rect.right = rect.bottom = 0; // This is actually CW_USEDEFAULT because of a bug
67 // in CFrameWnd::Create()
68 }
69
70 // Create the main window
71 m_mainframe = new CMainFrame;
72 m_mainframe->CFrameWnd::Create(NULL, "SpaceMonger", WS_OVERLAPPEDWINDOW, rect);
73 m_pMainWnd = m_mainframe;
74
75 // Create the one and only document
76 m_document = new CFolderTree;
77 m_document->Create();
78
79 // Create the main document view
80 m_view = new CFolderView;
81 m_view->Create(m_mainframe, 1);
82 m_view->SetDocument(m_document);
83 m_view->SetFocus();
84
85 // Load in the animations
86 static int anim_name[4] = {
87 IDB_SCAN1, IDB_SCAN2, IDB_SCAN3, IDB_SCAN4,
88 };
89 for (i = 0; i < 4; i++)
90 m_scan_animation[i] = (HBITMAP)LoadImage(m_hInstance,
91 MAKEINTRESOURCE(anim_name[i]), IMAGE_BITMAP, 128, 48,
92 LR_LOADTRANSPARENT|LR_LOADMAP3DCOLORS);
93
94 m_mainframe->ShowWindow(showcmd);
95 m_mainframe->UpdateWindow();
96 m_mainframe->RecalcLayout();
97
98 return(TRUE);
99}
100
101int CSpaceMonger::ExitInstance()
102{
103 m_settings.Save();
104
105 // m_pMainWnd is auto-deleted by the framework
106 delete m_view;
107 delete m_document;
108
109 return(0);
110}
111
112void CSpaceMonger::OnAppExit(void)
113{
114 CWinApp::OnAppExit();
115}
116
117void CSpaceMonger::OnFileOpen(void)
118{
119 CDriveDialog drvdialog;
120 int drive = drvdialog.DoModal();
121 if (drive == -1) return;
122
123 CFolderTree *ft = (CFolderTree *)m_document;
124 ft->m_path.Format("%c:\\", (char)(drive + 'A'));
125 OnFileRefresh();
126}
127
128void CSpaceMonger::OnFileRefresh(void)
129{
130 CFolderTree *ft = (CFolderTree *)m_document;
131
132 m_mainframe->EnableWindow(0);
133 m_view->SetDocument(NULL);
134 m_view->UpdateWindow();
135
136 ((CFolderView *)m_view)->zoomlevel = 0;
137 ft->LoadTree(ft->m_path, 1, m_mainframe);
138 m_view->SetDocument(m_document);
139 ft->UpdateAllViews();
140 m_mainframe->EnableWindow(1);
141}
142
143void CSpaceMonger::OnFileRun(void)
144{
145 CFolderView *fv = (CFolderView *)m_view;
146 CFolderTree *ft = (CFolderTree *)m_document;
147
148 if (fv == NULL || ft == NULL || fv->selected == NULL) return;
149
150 CString title, path;
151 if (ft != NULL) title += ft->m_path;
152 fv->BuildTitleReverse(fv->selected->source, title);
153 path = title;
154 title += fv->selected->source->names[fv->selected->index];
155
156 ShellExecute(NULL, NULL, title, NULL, path, SW_SHOWDEFAULT);
157}
158
159void CSpaceMonger::OnFileDelete(void)
160{
161 CFolderView *fv = (CFolderView *)m_view;
162 CFolderTree *ft = (CFolderTree *)m_document;
163
164 if (fv == NULL || ft == NULL || fv->selected == NULL) return;
165
166 CString title;
167 if (ft != NULL) title += ft->m_path;
168 fv->BuildTitleReverse(fv->selected->source, title);
169 title += fv->selected->source->names[fv->selected->index];
170 BOOL isfolder;
171 if (fv->selected->source->children[fv->selected->index] != NULL)
172 isfolder = 1;
173 else isfolder = 0;
174
175 char source[MAX_PATH+8];
176 int len;
177
178 strcpy(source, title);
179 len = strlen(source);
180 source[len] = '\0';
181 source[len+1] = '\0';
182
183 SHFILEOPSTRUCT fop;
184 fop.hwnd = m_mainframe->m_hWnd;
185 fop.wFunc = FO_DELETE;
186 fop.pFrom = source;
187 fop.pTo = NULL;
188 fop.fFlags = FOF_SIMPLEPROGRESS|FOF_ALLOWUNDO|FOF_NOCONFIRMATION;
189 fop.fAnyOperationsAborted = 0;
190 fop.hNameMappings = NULL;
191 fop.lpszProgressTitle = CurLang->deleting;
192
193 if (SHFileOperation(&fop) != 0 || fop.fAnyOperationsAborted) {
194 AfxMessageBox("Windows failed to delete file.");
195 return;
196 }
197
198 if (isfolder) {
199 delete fv->selected->source->children[fv->selected->index];
200 fv->selected->source->children[fv->selected->index] = NULL;
201 }
202 ui64 subsize = fv->selected->source->sizes[fv->selected->index];
203 CFolder *folder = fv->selected->source;
204 if (isfolder) folder->size_children -= subsize;
205 else folder->size_self -= subsize;
206 folder = folder->parent;
207 while (folder != NULL) {
208 folder->size_children -= subsize;
209 folder = folder->parent;
210 }
211 fv->selected->source->sizes[fv->selected->index] = 0;
212
213 if (m_settings.auto_rescan)
214 OnFileRefresh();
215 else
216 fv->OnUpdate(m_document);
217}
218
219void CSpaceMonger::OnZoomIn(void)
220{
221 ((CFolderView *)m_view)->ZoomIn(((CFolderView *)m_view)->selected);
222}
223
224void CSpaceMonger::OnZoomOut(void)
225{
226 ((CFolderView *)m_view)->ZoomOut();
227}
228
229void CSpaceMonger::OnZoomFull(void)
230{
231 ((CFolderView *)m_view)->ZoomFull();
232}
233
234void CSpaceMonger::OnShowFree(void)
235{
236 CFolderView *fv = (CFolderView *)m_view;
237 CMainFrame *mf = (CMainFrame *)m_mainframe;
238 if (fv == NULL || mf == NULL) return;
239
240 BOOL showfreespace = !fv->showfreespace;
241 mf->m_toolbar.EnableState(CMainToolBar::ViewFree, showfreespace);
242 fv->ShowFreeSpace(showfreespace);
243}
244
245void CSpaceMonger::OnSettings(void)
246{
247 CSettingsDialog settingsdialog;
248 if (settingsdialog.DoModal() == IDOK) {
249 m_settings.Save();
250 if (m_view != NULL && m_document != NULL) {
251 m_view->OnUpdate(m_document);
252 ((CFolderView *)m_view)->UpdateTitleBar();
253 }
254 ((CMainFrame *)m_mainframe)->m_toolbar.Reload();
255 }
256}
257
258void CSpaceMonger::OnFileProperties(void)
259{
260 CFolderView *fv = (CFolderView *)m_view;
261 CFolderTree *ft = (CFolderTree *)m_document;
262
263 if (fv == NULL || ft == NULL || fv->selected == NULL) return;
264
265 CString path = ft->m_path;
266 fv->BuildTitleReverse(fv->selected->source, path);
267 path += fv->selected->source->names[fv->selected->index];
268
269 SHELLEXECUTEINFO si;
270 ZeroMemory(&si, sizeof(si));
271 si.cbSize = sizeof(si);
272 si.hwnd = fv->GetSafeHwnd();
273 si.nShow = SW_SHOW;
274 si.fMask = SEE_MASK_INVOKEIDLIST;
275 si.lpVerb = _T("properties");
276 si.lpFile = (LPCTSTR)path;
277 ShellExecuteEx(&si);
278}
279
280void CSpaceMonger::OnAbout()
281{
282 CAboutDialog about;
283 about.DoModal();
284}
285
286void CSpaceMonger::OnIgnoreUpdate(CCmdUI *ui)
287{
288 GeneralIgnoreUpdate(ui);
289}
290
291void GeneralIgnoreUpdate(CCmdUI *ui)
292{
293 CFolderView *fv = (CFolderView *)theApp.m_view;
294 CDisplayFolder *cur = fv->selected;
295 int zoom = fv->zoomlevel;
296
297 if (ui->m_nID == ID_FILE_DELETE) {
298 if (theApp.m_settings.disable_delete || cur == NULL)
299 ui->Enable(0);
300 }
301 else if (ui->m_nID == ID_FILE_RUN) {
302 if (cur == NULL) ui->Enable(0);
303 }
304 else if (ui->m_nID == ID_FILE_PROPERTIES) {
305 if (cur == NULL) ui->Enable(0);
306 }
307 else if (ui->m_nID == ID_FILE_REFRESH) {
308 CFolderTree *ft = (CFolderTree *)theApp.m_document;
309 if (ft == NULL || ft->GetRoot() == NULL) ui->Enable(0);
310 }
311 else if (ui->m_nID == ID_VIEW_FREE) {
312 CFolderTree *ft = (CFolderTree *)theApp.m_document;
313 ui->SetCheck(fv->showfreespace);
314 if (ft == NULL || ft->GetRoot() == NULL) ui->Enable(0);
315 }
316 else if (ui->m_nID == ID_VIEW_ZOOM_IN) {
317 if (cur == NULL || (cur->flags & 1) == 0)
318 ui->Enable(0);
319 }
320 else if (ui->m_nID == ID_VIEW_ZOOM_OUT || ui->m_nID == ID_VIEW_ZOOM_FULL) {
321 if (zoom == 0) ui->Enable(0);
322 }
323}
324
325/////////////////////////////////////////////////////////////////////////////
326// Application Settings
327//
328
329void CCurrentSettings::Reset(void)
330{
331 density = 0;
332 file_color = 0;
333 folder_color = 0;
334 auto_rescan = 0;
335 animated_zoom = 1;
336 disable_delete = 0;
337 bias = 0;
338 show_name_tips = 1;
339 nametip_delay = 125;
340 show_info_tips = 1;
341 rollover_box = 0;
342 infotip_flags = TIP_DATE|TIP_SIZE|TIP_ICON;
343 infotip_delay = 250;
344 rect.left = rect.right = rect.top = rect.bottom = CW_USEDEFAULT;
345 showcmd = SW_SHOWNORMAL;
346 save_pos = 0;
347 lang[0] = 'u';
348 lang[1] = 's';
349 lang[2] = '\0';
350 lang[3] = '\0';
351}
352
353void CCurrentSettings::Load(void)
354{
355 HKEY key;
356 Reset();
357 if (RegOpenKey(HKEY_CURRENT_USER, "Software\\65\\SpaceMonger\\1.3", &key) != ERROR_SUCCESS)
358 return;
359
360 DWORD size = sizeof(density);
361 DWORD type;
362 RegQueryValueEx(key, "density", NULL, &type, (unsigned char *)&density, &size);
363 size = sizeof(file_color);
364 RegQueryValueEx(key, "file_color", NULL, &type, (unsigned char *)&file_color, &size);
365 size = sizeof(folder_color);
366 RegQueryValueEx(key, "folder_color", NULL, &type, (unsigned char *)&folder_color, &size);
367 size = sizeof(auto_rescan);
368 RegQueryValueEx(key, "auto_rescan", NULL, &type, (unsigned char *)&auto_rescan, &size);
369 size = sizeof(animated_zoom);
370 RegQueryValueEx(key, "animated_zoom", NULL, &type, (unsigned char *)&animated_zoom, &size);
371 size = sizeof(disable_delete);
372 RegQueryValueEx(key, "disable_delete", NULL, &type, (unsigned char *)&disable_delete, &size);
373 size = sizeof(save_pos);
374 RegQueryValueEx(key, "save_pos", NULL, &type, (unsigned char *)&save_pos, &size);
375 size = sizeof(bias);
376 RegQueryValueEx(key, "bias", NULL, &type, (unsigned char *)&bias, &size);
377 size = sizeof(show_name_tips);
378 RegQueryValueEx(key, "show_name_tips", NULL, &type, (unsigned char *)&show_name_tips, &size);
379 size = sizeof(rollover_box);
380 RegQueryValueEx(key, "show_rollover_box", NULL, &type, (unsigned char *)&rollover_box, &size);
381 size = sizeof(show_info_tips);
382 RegQueryValueEx(key, "show_info_tips", NULL, &type, (unsigned char *)&show_info_tips, &size);
383 size = sizeof(nametip_delay);
384 RegQueryValueEx(key, "nametip_delay", NULL, &type, (unsigned char *)&nametip_delay, &size);
385 size = sizeof(infotip_flags);
386 RegQueryValueEx(key, "infotip_flags", NULL, &type, (unsigned char *)&infotip_flags, &size);
387 size = sizeof(infotip_delay);
388 RegQueryValueEx(key, "infotip_delay", NULL, &type, (unsigned char *)&infotip_delay, &size);
389 size = sizeof(rect.left);
390 RegQueryValueEx(key, "window_rect.left", NULL, &type, (unsigned char *)&rect.left, &size);
391 size = sizeof(rect.top);
392 RegQueryValueEx(key, "window_rect.top", NULL, &type, (unsigned char *)&rect.top, &size);
393 size = sizeof(rect.right);
394 RegQueryValueEx(key, "window_rect.right", NULL, &type, (unsigned char *)&rect.right, &size);
395 size = sizeof(rect.bottom);
396 RegQueryValueEx(key, "window_rect.bottom", NULL, &type, (unsigned char *)&rect.bottom, &size);
397 size = sizeof(showcmd);
398 RegQueryValueEx(key, "window_showcmd", NULL, &type, (unsigned char *)&showcmd, &size);
399 size = sizeof(lang);
400 RegQueryValueEx(key, "lang", NULL, &type, (unsigned char *)&lang, &size);
401 RegCloseKey(key);
402
403 if (density < -3) density = -3;
404 if (density > 3) density = 3;
405
406 if (file_color < 0 || file_color > 12) file_color = 0;
407 if (folder_color < 0 || folder_color > 12) folder_color = 0;
408
409 auto_rescan = !!auto_rescan;
410 animated_zoom = !!animated_zoom;
411 disable_delete = !!disable_delete;
412 save_pos = !!save_pos;
413
414 rollover_box = !!rollover_box;
415
416 show_name_tips = !!show_name_tips;
417 if (nametip_delay < 0) nametip_delay = 0;
418 if (nametip_delay > 99999) nametip_delay = 99999;
419
420 show_info_tips = !!show_info_tips;
421 infotip_flags &= TIP_PATH|TIP_NAME|TIP_ICON|TIP_DATE|TIP_SIZE|TIP_ATTRIB;
422 if (infotip_delay < 0) infotip_delay = 0;
423 if (infotip_delay > 99999) infotip_delay = 99999;
424
425 if (bias < -20) bias = -20;
426 if (bias > 20) bias = 20;
427
428 // Ensure that the window's provided rectangle has at least a little of
429 // its area visible to the end-user.
430 int scrnwidth = GetSystemMetrics(SM_CXSCREEN), scrnheight = GetSystemMetrics(SM_CYSCREEN);
431 if (rect.top > rect.bottom) {
432 int temp = rect.top;
433 rect.top = rect.bottom;
434 rect.bottom = temp;
435 }
436 if (rect.left > rect.right) {
437 int temp = rect.left;
438 rect.left = rect.right;
439 rect.right = temp;
440 }
441 if (rect.right - rect.left > scrnwidth) rect.right = rect.left + scrnwidth;
442 if (rect.bottom - rect.top > scrnheight) rect.bottom = rect.top + scrnheight;
443 if (rect.top > scrnheight-8)
444 rect.bottom -= (rect.top - (scrnheight-8)), rect.top = scrnheight-8;
445 if (rect.left > scrnwidth-8)
446 rect.right -= (rect.left - (scrnwidth-8)), rect.left = scrnwidth-8;
447 if (rect.right < 8)
448 rect.left += (8-rect.right), rect.right = 8;
449 if (rect.bottom < 8)
450 rect.top += (8-rect.bottom), rect.bottom = 8;
451
452 // Ensure that the window's placement is comprehensible.
453 if (showcmd != SW_SHOWMINIMIZED && showcmd != SW_SHOWMAXIMIZED
454 && showcmd != SW_SHOWNORMAL)
455 showcmd = SW_SHOWNORMAL;
456
457 // Find the language in the list of languages. If it's not found,
458 // try US English.
459 lang[0] = tolower(lang[0]);
460 lang[1] = tolower(lang[1]);
461 lang[2] = '\0';
462 lang[3] = '\0';
463 int i;
464 CurLang = NULL;
465 for (i = 0; Langs[i].name != NULL; i++) {
466 if (lang[0] == Langs[i].abbrev[0] && lang[1] == Langs[i].abbrev[1]) {
467 CurLang = Langs[i].text;
468 break;
469 }
470 }
471 if (CurLang == NULL) {
472 CurLang = Langs[0].text;
473 lang[0] = Langs[0].abbrev[0];
474 lang[1] = Langs[0].abbrev[1];
475 lang[2] = '\0';
476 lang[3] = '\0';
477 }
478}
479
480void CCurrentSettings::Save(void)
481{
482 HKEY key;
483 if (RegCreateKey(HKEY_CURRENT_USER, "Software\\65\\SpaceMonger\\1.3", &key) != ERROR_SUCCESS)
484 return;
485 DWORD size;
486 size = sizeof(density);
487 RegSetValueEx(key, "density", NULL, REG_DWORD, (unsigned char *)&density, size);
488 size = sizeof(file_color);
489 RegSetValueEx(key, "file_color", NULL, REG_DWORD, (unsigned char *)&file_color, size);
490 size = sizeof(folder_color);
491 RegSetValueEx(key, "folder_color", NULL, REG_DWORD, (unsigned char *)&folder_color, size);
492 size = sizeof(auto_rescan);
493 RegSetValueEx(key, "auto_rescan", NULL, REG_DWORD, (unsigned char *)&auto_rescan, size);
494 size = sizeof(animated_zoom);
495 RegSetValueEx(key, "animated_zoom", NULL, REG_DWORD, (unsigned char *)&animated_zoom, size);
496 size = sizeof(disable_delete);
497 RegSetValueEx(key, "disable_delete", NULL, REG_DWORD, (unsigned char *)&disable_delete, size);
498 size = sizeof(save_pos);
499 RegSetValueEx(key, "save_pos", NULL, REG_DWORD, (unsigned char *)&save_pos, size);
500 size = sizeof(bias);
501 RegSetValueEx(key, "bias", NULL, REG_DWORD, (unsigned char *)&bias, size);
502 size = sizeof(show_name_tips);
503 RegSetValueEx(key, "show_name_tips", NULL, REG_DWORD, (unsigned char *)&show_name_tips, size);
504 size = sizeof(rollover_box);
505 RegSetValueEx(key, "show_rollover_box", NULL, REG_DWORD, (unsigned char *)&rollover_box, size);
506 size = sizeof(show_info_tips);
507 RegSetValueEx(key, "show_info_tips", NULL, REG_DWORD, (unsigned char *)&show_info_tips, size);
508 size = sizeof(nametip_delay);
509 RegSetValueEx(key, "nametip_delay", NULL, REG_DWORD, (unsigned char *)&nametip_delay, size);
510 size = sizeof(infotip_flags);
511 RegSetValueEx(key, "infotip_flags", NULL, REG_DWORD, (unsigned char *)&infotip_flags, size);
512 size = sizeof(infotip_delay);
513 RegSetValueEx(key, "infotip_delay", NULL, REG_DWORD, (unsigned char *)&infotip_delay, size);
514 size = sizeof(rect.left);
515 RegSetValueEx(key, "window_rect.left", NULL, REG_DWORD, (unsigned char *)&rect.left, size);
516 size = sizeof(rect.top);
517 RegSetValueEx(key, "window_rect.top", NULL, REG_DWORD, (unsigned char *)&rect.top, size);
518 size = sizeof(rect.right);
519 RegSetValueEx(key, "window_rect.right", NULL, REG_DWORD, (unsigned char *)&rect.right, size);
520 size = sizeof(rect.bottom);
521 RegSetValueEx(key, "window_rect.bottom",NULL, REG_DWORD, (unsigned char *)&rect.bottom, size);
522 size = sizeof(showcmd);
523 RegSetValueEx(key, "window_showcmd", NULL, REG_DWORD, (unsigned char *)&showcmd, size);
524 size = sizeof(lang);
525 RegSetValueEx(key, "lang", NULL, REG_SZ, (unsigned char *)&lang, 3);
526 RegCloseKey(key);
527}
diff --git a/SpaceMonger.dsp b/SpaceMonger.dsp
new file mode 100644
index 0000000..a6bf31c
--- /dev/null
+++ b/SpaceMonger.dsp
@@ -0,0 +1,249 @@
1# Microsoft Developer Studio Project File - Name="SpaceMonger" - Package Owner=<4>
2# Microsoft Developer Studio Generated Build File, Format Version 6.00
3# ** DO NOT EDIT **
4
5# TARGTYPE "Win32 (x86) Application" 0x0101
6
7CFG=SpaceMonger - Win32 Release
8!MESSAGE This is not a valid makefile. To build this project using NMAKE,
9!MESSAGE use the Export Makefile command and run
10!MESSAGE
11!MESSAGE NMAKE /f "SpaceMonger.mak".
12!MESSAGE
13!MESSAGE You can specify a configuration when running NMAKE
14!MESSAGE by defining the macro CFG on the command line. For example:
15!MESSAGE
16!MESSAGE NMAKE /f "SpaceMonger.mak" CFG="SpaceMonger - Win32 Release"
17!MESSAGE
18!MESSAGE Possible choices for configuration are:
19!MESSAGE
20!MESSAGE "SpaceMonger - Win32 Release" (based on "Win32 (x86) Application")
21!MESSAGE "SpaceMonger - Win32 Debug" (based on "Win32 (x86) Application")
22!MESSAGE
23
24# Begin Project
25# PROP AllowPerConfigDependencies 0
26# PROP Scc_ProjName ""
27# PROP Scc_LocalPath ""
28CPP=cl.exe
29MTL=midl.exe
30RSC=rc.exe
31
32!IF "$(CFG)" == "SpaceMonger - Win32 Release"
33
34# PROP BASE Use_MFC 2
35# PROP BASE Use_Debug_Libraries 0
36# PROP BASE Output_Dir ".\Release"
37# PROP BASE Intermediate_Dir ".\Release"
38# PROP BASE Target_Dir ""
39# PROP Use_MFC 1
40# PROP Use_Debug_Libraries 0
41# PROP Output_Dir ".\Release"
42# PROP Intermediate_Dir ".\Release"
43# PROP Ignore_Export_Lib 0
44# PROP Target_Dir ""
45# ADD BASE CPP /nologo /MD /W3 /GX /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Yu"stdafx.h" /c
46# ADD CPP /nologo /MT /W3 /Ox /Ot /Og /Oi /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GF /c
47# ADD BASE MTL /nologo /D "NDEBUG" /win32
48# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
49# ADD BASE RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
50# ADD RSC /l 0x409 /d "NDEBUG"
51BSC32=bscmake.exe
52# ADD BASE BSC32 /nologo
53# ADD BSC32 /nologo
54LINK32=link.exe
55# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386
56# ADD LINK32 /nologo /subsystem:windows /machine:I386
57# SUBTRACT LINK32 /profile /debug /nodefaultlib
58
59!ELSEIF "$(CFG)" == "SpaceMonger - Win32 Debug"
60
61# PROP BASE Use_MFC 2
62# PROP BASE Use_Debug_Libraries 1
63# PROP BASE Output_Dir ".\Debug"
64# PROP BASE Intermediate_Dir ".\Debug"
65# PROP BASE Target_Dir ""
66# PROP Use_MFC 1
67# PROP Use_Debug_Libraries 1
68# PROP Output_Dir ".\Debug"
69# PROP Intermediate_Dir ".\Debug"
70# PROP Ignore_Export_Lib 0
71# PROP Target_Dir ""
72# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Yu"stdafx.h" /c
73# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c
74# ADD BASE MTL /nologo /D "_DEBUG" /win32
75# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
76# ADD BASE RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
77# ADD RSC /l 0x409 /d "_DEBUG"
78BSC32=bscmake.exe
79# ADD BASE BSC32 /nologo
80# ADD BSC32 /nologo
81LINK32=link.exe
82# ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386
83# ADD LINK32 /nologo /subsystem:windows /profile /debug /machine:I386
84
85!ENDIF
86
87# Begin Target
88
89# Name "SpaceMonger - Win32 Release"
90# Name "SpaceMonger - Win32 Debug"
91# Begin Group "Source Files"
92
93# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
94# Begin Source File
95
96SOURCE=.\AboutDialog.cpp
97# End Source File
98# Begin Source File
99
100SOURCE=.\DriveDialog.cpp
101# End Source File
102# Begin Source File
103
104SOURCE=.\FolderTree.cpp
105# End Source File
106# Begin Source File
107
108SOURCE=.\FolderView.cpp
109# End Source File
110# Begin Source File
111
112SOURCE=.\Freedoc.cpp
113# End Source File
114# Begin Source File
115
116SOURCE=.\Freeview.cpp
117# End Source File
118# Begin Source File
119
120SOURCE=.\lang_en.cpp
121# End Source File
122# Begin Source File
123
124SOURCE=.\lang_fr.cpp
125# End Source File
126# Begin Source File
127
128SOURCE=.\Mainfrm.cpp
129# End Source File
130# Begin Source File
131
132SOURCE=.\SetupDlg.cpp
133# End Source File
134# Begin Source File
135
136SOURCE=.\SpaceMonger.cpp
137# End Source File
138# Begin Source File
139
140SOURCE=.\SpaceMonger.rc
141# End Source File
142# Begin Source File
143
144SOURCE=.\StdAfx.cpp
145# ADD CPP /Yc"stdafx.h"
146# End Source File
147# Begin Source File
148
149SOURCE=.\TipWnd.cpp
150# End Source File
151# End Group
152# Begin Group "Header Files"
153
154# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
155# Begin Source File
156
157SOURCE=.\AboutDialog.h
158# End Source File
159# Begin Source File
160
161SOURCE=.\DriveDialog.h
162# End Source File
163# Begin Source File
164
165SOURCE=.\FolderTree.h
166# End Source File
167# Begin Source File
168
169SOURCE=.\FolderView.h
170# End Source File
171# Begin Source File
172
173SOURCE=.\lang.h
174# End Source File
175# Begin Source File
176
177SOURCE=.\Mainfrm.h
178# End Source File
179# Begin Source File
180
181SOURCE=.\resource.h
182# End Source File
183# Begin Source File
184
185SOURCE=.\SetupDlg.h
186# End Source File
187# Begin Source File
188
189SOURCE=.\SpaceMonger.h
190# End Source File
191# Begin Source File
192
193SOURCE=.\Stdafx.h
194# End Source File
195# Begin Source File
196
197SOURCE=.\TipWnd.h
198# End Source File
199# Begin Source File
200
201SOURCE=.\xapp.h
202# End Source File
203# End Group
204# Begin Group "Resource Files"
205
206# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
207# Begin Source File
208
209SOURCE=.\res\bitmap1.bmp
210# End Source File
211# Begin Source File
212
213SOURCE=.\res\bmp00001.bmp
214# End Source File
215# Begin Source File
216
217SOURCE=.\res\bmp00002.bmp
218# End Source File
219# Begin Source File
220
221SOURCE=.\res\bmp00003.bmp
222# End Source File
223# Begin Source File
224
225SOURCE=.\res\scan1.bmp
226# End Source File
227# Begin Source File
228
229SOURCE=.\Res\SpaceMonger.ico
230# End Source File
231# Begin Source File
232
233SOURCE=.\res\toolbar1.bmp
234# End Source File
235# Begin Source File
236
237SOURCE=.\res\toolbar_en.bmp
238# End Source File
239# Begin Source File
240
241SOURCE=.\res\toolbar_fr.bmp
242# End Source File
243# Begin Source File
244
245SOURCE=.\res\toolbar_francais.bmp
246# End Source File
247# End Group
248# End Target
249# End Project
diff --git a/SpaceMonger.dsw b/SpaceMonger.dsw
new file mode 100644
index 0000000..8a53582
--- /dev/null
+++ b/SpaceMonger.dsw
@@ -0,0 +1,29 @@
1Microsoft Developer Studio Workspace File, Format Version 6.00
2# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
3
4###############################################################################
5
6Project: "SpaceMonger"=.\SpaceMonger.dsp - Package Owner=<4>
7
8Package=<5>
9{{{
10}}}
11
12Package=<4>
13{{{
14}}}
15
16###############################################################################
17
18Global:
19
20Package=<5>
21{{{
22}}}
23
24Package=<3>
25{{{
26}}}
27
28###############################################################################
29
diff --git a/SpaceMonger.h b/SpaceMonger.h
new file mode 100644
index 0000000..4128282
--- /dev/null
+++ b/SpaceMonger.h
@@ -0,0 +1,90 @@
1
2#ifndef CSPACEMONGER_H
3#define CSPACEMONGER_H
4
5#ifndef __AFXWIN_H__
6 #error include 'stdafx.h' before including this file for PCH
7#endif
8
9#include "resource.h" // main symbols
10#include "MainFrm.h" // Main window
11
12enum {
13 TIP_PATH = 1, // Display full path in tooltip
14 TIP_NAME = 2, // Display filename in tooltip
15 TIP_ICON = 4, // Display suitable icon in tooltip
16 TIP_DATE = 8, // Display file date in tooltip
17 TIP_SIZE = 16, // Display file size in tooltip
18 TIP_ATTRIB = 32, // Display file attributes in tooltip
19};
20
21struct CCurrentSettings {
22 int density; // Density of filenames
23 int file_color; // Displayed color of files
24 int folder_color; // Displayed color of folders
25 BOOL auto_rescan; // Auto-rescan when a file is deleted
26 BOOL animated_zoom; // Use animated zoom in/out
27 BOOL disable_delete; // Disallow the deletion of files
28 BOOL rollover_box; // Show rollover box
29 int bias; // Display bias, from -20 (vert) to +20 (horz)
30
31 BOOL save_pos; // Save this window's position?
32 RECT rect; // Pluralized window rectangle
33 int showcmd; // Current show-command
34
35 BOOL show_name_tips; // Show tooltips?
36 int nametip_delay; // Tip delay, in milliseconds
37
38 BOOL show_info_tips; // Show tooltips?
39 int infotip_flags; // Tooltip flags
40 int infotip_delay; // Tip delay, in milliseconds
41
42 char lang[4]; // Language, by two-letter code
43
44 void Reset(void); // Reset to default values
45 void Load(void); // Retrieve current settings from Registry
46 void Save(void); // Save current settings to Registry
47};
48
49class CSpaceMonger : public CWinApp {
50public:
51 CSpaceMonger();
52 ~CSpaceMonger();
53
54 //{{AFX_VIRTUAL(CSpaceMonger)
55 virtual BOOL InitInstance();
56 virtual int ExitInstance();
57 //}}AFX_VIRTUAL
58
59 //{{AFX_MSG(CSpaceMonger)
60 afx_msg void OnAbout();
61 afx_msg void OnAppExit(void);
62 afx_msg void OnFileOpen(void);
63 afx_msg void OnFileRefresh(void);
64 afx_msg void OnFileRun(void);
65 afx_msg void OnFileDelete(void);
66 afx_msg void OnZoomFull(void);
67 afx_msg void OnZoomIn(void);
68 afx_msg void OnZoomOut(void);
69 afx_msg void OnShowFree(void);
70 afx_msg void OnSettings(void);
71 afx_msg void OnFileProperties(void);
72 afx_msg void OnIgnoreUpdate(CCmdUI *ui);
73 //}}AFX_MSG
74 DECLARE_MESSAGE_MAP()
75
76public:
77 CFrameWnd *m_mainframe;
78 CFreeDoc *m_document;
79 CFreeView *m_view;
80
81 HBITMAP m_scan_animation[4];
82
83 CCurrentSettings m_settings;
84};
85
86void GeneralIgnoreUpdate(CCmdUI *ui);
87
88extern CSpaceMonger theApp;
89
90#endif
diff --git a/SpaceMonger.ncb b/SpaceMonger.ncb
new file mode 100644
index 0000000..4cbddaf
--- /dev/null
+++ b/SpaceMonger.ncb
Binary files differ
diff --git a/SpaceMonger.opt b/SpaceMonger.opt
new file mode 100644
index 0000000..48885a1
--- /dev/null
+++ b/SpaceMonger.opt
Binary files differ
diff --git a/SpaceMonger.rc b/SpaceMonger.rc
new file mode 100644
index 0000000..7171a28
--- /dev/null
+++ b/SpaceMonger.rc
@@ -0,0 +1,330 @@
1//Microsoft Developer Studio generated resource script.
2//
3#include "resource.h"
4
5#define APSTUDIO_READONLY_SYMBOLS
6/////////////////////////////////////////////////////////////////////////////
7//
8// Generated from the TEXTINCLUDE 2 resource.
9//
10#include "afxres.h"
11
12/////////////////////////////////////////////////////////////////////////////
13#undef APSTUDIO_READONLY_SYMBOLS
14
15/////////////////////////////////////////////////////////////////////////////
16// English (U.S.) resources
17
18#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
19#ifdef _WIN32
20LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
21#pragma code_page(1252)
22#endif //_WIN32
23
24/////////////////////////////////////////////////////////////////////////////
25//
26// Dialog
27//
28
29IDD_ABOUT DIALOG DISCARDABLE 0, 0, 239, 145
30STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | WS_POPUP | WS_VISIBLE |
31 WS_CAPTION | WS_SYSMENU
32FONT 8, "MS Sans Serif"
33BEGIN
34 DEFPUSHBUTTON "",IDOK,94,124,50,14
35 ICON ID_SPACEMONGER,IDC_STATIC,7,9,20,20
36 LTEXT "SpaceMonger Version 1.4.0",IDC_STATIC,37,9,95,10
37 LTEXT "Copyright © 1998, 1999, 2000 by Sean Werkema",
38 IDC_STATIC,37,18,168,8
39 LTEXT "",IDC_STATIC_FREEWARE,37,41,195,10
40 LTEXT "",IDC_STATIC_WARRANTY,37,55,195,34
41 CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,37,34,195,1
42 LTEXT "",IDC_STATIC_EMAIL,37,93,195,18
43 CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,37,115,195,1
44END
45
46IDD_OPEN_DIALOG DIALOG DISCARDABLE 0, 0, 221, 170
47STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | WS_POPUP | WS_VISIBLE |
48 WS_CAPTION | WS_SYSMENU
49FONT 8, "MS Sans Serif"
50BEGIN
51 DEFPUSHBUTTON "",IDOK,113,151,50,14
52 PUSHBUTTON "",IDCANCEL,58,151,50,14
53 CONTROL "",IDC_DRIVE_LIST,"SysListView32",LVS_SINGLESEL |
54 LVS_SORTASCENDING | LVS_AUTOARRANGE | WS_BORDER |
55 WS_TABSTOP,7,5,207,139
56END
57
58IDD_SCAN_DIALOG DIALOGEX 0, 0, 250, 54
59STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | WS_POPUP | WS_VISIBLE |
60 WS_CAPTION
61EXSTYLE WS_EX_TOOLWINDOW
62FONT 8, "MS Sans Serif"
63BEGIN
64 PUSHBUTTON "",IDCANCEL,203,24,40,14
65 LTEXT "",IDC_STATIC_FILESFOUND,103,21,66,8
66 LTEXT "",IDC_STATIC_FOLDERSFOUND,103,30,66,8
67 LTEXT "",IDC_PATH,7,4,236,9
68 LTEXT "0",IDC_FILES,171,21,30,8
69 LTEXT "0",IDC_FOLDERS,171,30,30,8
70 CONTROL "",IDC_LOAD_PROGRESS,"msctls_progress32",WS_BORDER,7,44,
71 236,6
72END
73
74IDD_SETTINGS DIALOG DISCARDABLE 0, 0, 280, 213
75STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | WS_POPUP | WS_VISIBLE |
76 WS_CAPTION | WS_SYSMENU
77FONT 8, "MS Sans Serif"
78BEGIN
79 COMBOBOX IDC_LANG,191,8,82,101,CBS_DROPDOWNLIST | WS_VSCROLL |
80 WS_TABSTOP
81 COMBOBOX IDC_DENSITY,42,18,90,85,CBS_DROPDOWNLIST | WS_GROUP |
82 WS_TABSTOP
83 CONTROL "",IDC_BIAS,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP |
84 WS_TABSTOP,39,49,95,17
85 COMBOBOX IDC_FILE_COLOR,191,40,72,143,CBS_DROPDOWNLIST | WS_GROUP |
86 WS_TABSTOP
87 COMBOBOX IDC_FOLDER_COLOR,191,55,72,142,CBS_DROPDOWNLIST |
88 WS_TABSTOP
89 CONTROL "",IDC_SHOW_NAME_TIPS,"Button",BS_AUTOCHECKBOX |
90 WS_GROUP | WS_TABSTOP,24,85,104,10
91 EDITTEXT IDC_NAMETIP_DELAY,59,96,27,12,ES_NUMBER | WS_GROUP
92 CONTROL "",IDC_SHOW_ROLLOVER_BOX,"Button",BS_AUTOCHECKBOX |
93 WS_TABSTOP,24,126,119,8
94 CONTROL "",IDC_SHOW_INFO_TIPS,"Button",BS_AUTOCHECKBOX |
95 WS_GROUP | WS_TABSTOP,144,85,104,10
96 CONTROL "",IDC_INFOTIP_PATH,"Button",BS_AUTOCHECKBOX | WS_GROUP |
97 WS_TABSTOP,153,96,50,10
98 CONTROL "",IDC_INFOTIP_DATE,"Button",BS_AUTOCHECKBOX |
99 WS_TABSTOP,205,96,50,10
100 CONTROL "",IDC_INFOTIP_NAME,"Button",BS_AUTOCHECKBOX |
101 WS_TABSTOP,153,106,50,10
102 CONTROL "",IDC_INFOTIP_SIZE,"Button",BS_AUTOCHECKBOX |
103 WS_TABSTOP,205,106,50,10
104 CONTROL "",IDC_INFOTIP_ICON,"Button",BS_AUTOCHECKBOX |
105 WS_TABSTOP,153,116,50,10
106 CONTROL "",IDC_INFOTIP_ATTRIB,"Button",BS_AUTOCHECKBOX |
107 WS_TABSTOP,205,116,50,10
108 EDITTEXT IDC_INFOTIP_DELAY,182,129,27,12,ES_NUMBER | WS_GROUP
109 CONTROL "",IDC_AUTO_RESCAN,"Button",BS_AUTOCHECKBOX | WS_GROUP |
110 WS_TABSTOP,24,160,120,10
111 CONTROL "",IDC_DISABLE_DELETE,"Button",BS_AUTOCHECKBOX |
112 WS_TABSTOP,24,171,120,10
113 CONTROL "",IDC_ANIMATED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
114 144,160,120,10
115 CONTROL "",IDC_SAVE_POS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
116 144,171,120,10
117 PUSHBUTTON "",IDCANCEL,86,194,50,14,WS_GROUP
118 DEFPUSHBUTTON "",IDOK,142,194,50,14
119 LTEXT "",IDC_STATIC_DENSITY,14,20,27,8
120 LTEXT "",IDC_STATIC_FILES,160,43,30,8
121 LTEXT "",IDC_STATIC_BIAS,14,55,24,8
122 CTEXT "",IDC_STATIC_HORZ,35,40,21,8
123 CTEXT "",IDC_STATIC_VERT,118,40,21,8
124 CTEXT "",IDC_STATIC_EQUAL,76,40,21,8
125 LTEXT "",IDC_STATIC_FOLDERS,160,58,30,8
126 LTEXT "",IDC_STATIC_INFOTIP1,153,131,28,8
127 LTEXT "",IDC_STATIC_INFOTIP2,212,131,25,8
128 GROUPBOX "",IDC_STATIC_LAYOUT,7,4,139,68
129 GROUPBOX "",IDC_STATIC_DISPLAYCOLORS,153,29,120,43
130 GROUPBOX "",IDC_STATIC_TOOLTIPS,7,74,266,73
131 GROUPBOX "",IDC_STATIC_MISCOPTIONS,6,149,267,38
132 LTEXT "",IDC_STATIC_NAMETIP1,30,98,28,8
133 LTEXT "",IDC_STATIC_NAMETIP2,89,98,25,8
134END
135
136
137/////////////////////////////////////////////////////////////////////////////
138//
139// DESIGNINFO
140//
141
142#ifdef APSTUDIO_INVOKED
143GUIDELINES DESIGNINFO DISCARDABLE
144BEGIN
145 IDD_ABOUT, DIALOG
146 BEGIN
147 LEFTMARGIN, 7
148 RIGHTMARGIN, 232
149 TOPMARGIN, 7
150 BOTTOMMARGIN, 138
151 END
152
153 IDD_OPEN_DIALOG, DIALOG
154 BEGIN
155 LEFTMARGIN, 7
156 RIGHTMARGIN, 214
157 TOPMARGIN, 7
158 BOTTOMMARGIN, 163
159 END
160
161 IDD_SCAN_DIALOG, DIALOG
162 BEGIN
163 LEFTMARGIN, 7
164 RIGHTMARGIN, 243
165 TOPMARGIN, 7
166 BOTTOMMARGIN, 50
167 END
168
169 IDD_SETTINGS, DIALOG
170 BEGIN
171 LEFTMARGIN, 6
172 RIGHTMARGIN, 273
173 TOPMARGIN, 4
174 BOTTOMMARGIN, 208
175 END
176END
177#endif // APSTUDIO_INVOKED
178
179
180#ifdef APSTUDIO_INVOKED
181/////////////////////////////////////////////////////////////////////////////
182//
183// TEXTINCLUDE
184//
185
1861 TEXTINCLUDE DISCARDABLE
187BEGIN
188 "resource.h\0"
189END
190
1912 TEXTINCLUDE DISCARDABLE
192BEGIN
193 "#include ""afxres.h""\r\n"
194 "\0"
195END
196
1973 TEXTINCLUDE DISCARDABLE
198BEGIN
199 "\r\n"
200 "\0"
201END
202
203#endif // APSTUDIO_INVOKED
204
205
206/////////////////////////////////////////////////////////////////////////////
207//
208// Icon
209//
210
211// Icon with lowest ID value placed first to ensure application icon
212// remains consistent on all systems.
213ID_SPACEMONGER ICON DISCARDABLE "res\\SpaceMonger.ico"
214
215/////////////////////////////////////////////////////////////////////////////
216//
217// Toolbar
218//
219
220IDR_TOOLBAR_EN TOOLBAR DISCARDABLE 44, 15
221BEGIN
222 BUTTON ID_FILE_OPEN
223 BUTTON ID_FILE_REFRESH
224 SEPARATOR
225 BUTTON ID_VIEW_ZOOM_FULL
226 BUTTON ID_VIEW_ZOOM_IN
227 BUTTON ID_VIEW_ZOOM_OUT
228 SEPARATOR
229 BUTTON ID_VIEW_FREE
230 SEPARATOR
231 BUTTON ID_FILE_RUN
232 BUTTON ID_FILE_DELETE
233 SEPARATOR
234 BUTTON ID_SETTINGS
235 SEPARATOR
236 BUTTON ID_APP_ABOUT
237END
238
239IDR_TOOLBAR_FR TOOLBAR DISCARDABLE 44, 15
240BEGIN
241 BUTTON ID_FILE_OPEN
242 BUTTON ID_FILE_REFRESH
243 SEPARATOR
244 BUTTON ID_VIEW_ZOOM_FULL
245 BUTTON ID_VIEW_ZOOM_IN
246 BUTTON ID_VIEW_ZOOM_OUT
247 SEPARATOR
248 BUTTON ID_VIEW_FREE
249 SEPARATOR
250 BUTTON ID_FILE_RUN
251 BUTTON ID_FILE_DELETE
252 SEPARATOR
253 BUTTON ID_SETTINGS
254 SEPARATOR
255 BUTTON ID_APP_ABOUT
256END
257
258
259/////////////////////////////////////////////////////////////////////////////
260//
261// Bitmap
262//
263
264IDB_SCAN1 BITMAP DISCARDABLE "res\\scan1.bmp"
265IDB_SCAN2 BITMAP DISCARDABLE "res\\scan2.bmp"
266IDB_SCAN3 BITMAP DISCARDABLE "res\\scan3.bmp"
267IDB_SCAN4 BITMAP DISCARDABLE "res\\scan4.bmp"
268IDR_TOOLBAR_EN BITMAP DISCARDABLE "res\\toolbar_en.bmp"
269IDR_TOOLBAR_FR BITMAP DISCARDABLE "res\\toolbar_fr.bmp"
270
271#ifndef _MAC
272/////////////////////////////////////////////////////////////////////////////
273//
274// Version
275//
276
277VS_VERSION_INFO VERSIONINFO
278 FILEVERSION 1,4,0,1
279 PRODUCTVERSION 1,4,0,1
280 FILEFLAGSMASK 0x3fL
281#ifdef _DEBUG
282 FILEFLAGS 0x1L
283#else
284 FILEFLAGS 0x0L
285#endif
286 FILEOS 0x40004L
287 FILETYPE 0x1L
288 FILESUBTYPE 0x0L
289BEGIN
290 BLOCK "StringFileInfo"
291 BEGIN
292 BLOCK "040904b0"
293 BEGIN
294 VALUE "Comments", "Visit http://www.werkema.com/software/spacemonger.html for the latest version\0"
295 VALUE "CompanyName", "65 Systems\0"
296 VALUE "FileDescription", "SpaceMonger Program File\0"
297 VALUE "FileVersion", "1, 4, 0, 1\0"
298 VALUE "InternalName", "SpaceMonger\0"
299 VALUE "LegalCopyright", "Copyright © 1997-2000 Sean Werkema\0"
300 VALUE "LegalTrademarks", "\0"
301 VALUE "OriginalFilename", "SpaceMonger.exe\0"
302 VALUE "PrivateBuild", "\0"
303 VALUE "ProductName", "SpaceMonger\0"
304 VALUE "ProductVersion", "1, 4, 0, 1\0"
305 VALUE "SpecialBuild", "\0"
306 END
307 END
308 BLOCK "VarFileInfo"
309 BEGIN
310 VALUE "Translation", 0x409, 1200
311 END
312END
313
314#endif // !_MAC
315
316#endif // English (U.S.) resources
317/////////////////////////////////////////////////////////////////////////////
318
319
320
321#ifndef APSTUDIO_INVOKED
322/////////////////////////////////////////////////////////////////////////////
323//
324// Generated from the TEXTINCLUDE 3 resource.
325//
326
327
328/////////////////////////////////////////////////////////////////////////////
329#endif // not APSTUDIO_INVOKED
330
diff --git a/StdAfx.cpp b/StdAfx.cpp
new file mode 100644
index 0000000..f36634a
--- /dev/null
+++ b/StdAfx.cpp
@@ -0,0 +1,5 @@
1// stdafx.cpp : source file that includes just the standard includes
2// SpaceMonger.pch will be the pre-compiled header
3// stdafx.obj will contain the pre-compiled type information
4
5#include "StdAfx.h"
diff --git a/Stdafx.h b/Stdafx.h
new file mode 100644
index 0000000..220fd6a
--- /dev/null
+++ b/Stdafx.h
@@ -0,0 +1,25 @@
1// stdafx.h : include file for standard system include files,
2// or project specific include files that are used frequently, but
3// are changed infrequently
4//
5
6#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
7
8#include <afxwin.h> // MFC core and standard components
9#include <afxext.h> // MFC extensions
10#include <afxmt.h> // MFC multithreading extensions
11#ifndef _AFX_NO_AFXCMN_SUPPORT
12#include <afxcmn.h> // MFC support for Windows 95 Common Controls
13#endif // _AFX_NO_AFXCMN_SUPPORT
14
15#include <winnetwk.h> // Windows networking subsystem
16#include <winsock.h> // Windows sockets
17#include <nspapi.h> // Namespace API
18#include <shellapi.h> // Shell (Explorer) API
19#include <shlobj.h> // Shell object definitions
20
21#include "xapp.h" // Extended MFC utils
22#include "e.h" // Enhanced portable types
23
24#define bool char
25
diff --git a/TipWnd.cpp b/TipWnd.cpp
new file mode 100644
index 0000000..623cbd1
--- /dev/null
+++ b/TipWnd.cpp
@@ -0,0 +1,789 @@
1
2#include "stdafx.h"
3#include "SpaceMonger.h"
4#include "TipWnd.h"
5
6#ifdef _DEBUG
7#define new DEBUG_NEW
8#undef THIS_FILE
9static char THIS_FILE[] = __FILE__;
10#endif
11
12/***************************************************************************/
13
14#define CLASSNAME "TipWnd"
15
16struct TipWndInfo {
17 HICON icon;
18 int flags;
19 char *text;
20 int textlen;
21 HFONT font;
22 COLORREF bgcolor;
23 COLORREF textcolor;
24 COLORREF bordercolor;
25 short int vpadding, hpadding;
26 unsigned char autoshow;
27 unsigned char autopos;
28 short int showdelay;
29 UINT timer, hidetimer;
30 HWND owner;
31 int mousex, mousey;
32 BOOL hidden;
33 BOOL enabled;
34 int ourmousex, ourmousey;
35};
36
37enum {
38 TIPWND_LARGE_ICON = 1,
39
40 TIPWND_ICON_LEFT = 0,
41 TIPWND_ICON_TOP = 2,
42 TIPWND_ICON_RIGHT = 4,
43 TIPWND_ICON_BOTTOM = 6,
44
45 TIPWND_ANCHOR_LEFT = 8,
46 TIPWND_ANCHOR_TOP = 16,
47 TIPWND_ANCHOR_RIGHT = 32,
48 TIPWND_ANCHOR_BOTTOM = 64,
49
50 TIPWND_ANCHOR_TOPLEFT = 8|16,
51 TIPWND_ANCHOR_TOPRIGHT = 32|16,
52 TIPWND_ANCHOR_BOTTOMLEFT = 8|64,
53 TIPWND_ANCHOR_BOTTOMRIGHT = 32|64,
54
55 TIPWND_ALIGN_LEFT = 128,
56 TIPWND_ALIGN_TOP = 256,
57 TIPWND_ALIGN_RIGHT = 512,
58 TIPWND_ALIGN_BOTTOM = 1024,
59
60 TIPWND_ALIGN_TOPLEFT = 128|256,
61 TIPWND_ALIGN_TOPRIGHT = 512|256,
62 TIPWND_ALIGN_BOTTOMLEFT = 128|1024,
63 TIPWND_ALIGN_BOTTOMRIGHT = 512|1024,
64};
65
66/***************************************************************************/
67
68static HFONT SetBestFont(HDC dc, TipWndInfo *info)
69{
70 if (info->font != NULL)
71 return (HFONT)::SelectObject(dc, info->font);
72 else return (HFONT)::SelectObject(dc, ::GetStockObject(DEFAULT_GUI_FONT));
73}
74
75static void ComputeTextExtents(HDC dc, TipWndInfo *info, SIZE *size)
76{
77 // Scan the text to determine the longest line (in pixels) and the
78 // total height in pixels.
79 const char *start, *end;
80 int maxlen = 0, height = 0;
81 SIZE linesize;
82 TEXTMETRIC tm;
83 ::GetTextMetrics(dc, &tm);
84
85 start = info->text;
86 if (start != NULL) {
87 while (*start != '\0') {
88 end = start;
89 while (*end != '\0' && *end != '\n') end++;
90 linesize.cx = linesize.cy = 0;
91 ::GetTextExtentPoint32(dc, start, end-start, &linesize);
92 height += tm.tmAscent + tm.tmDescent;
93 if (linesize.cx > maxlen) maxlen = linesize.cx;
94 if (*end == '\n') end++;
95 start = end;
96 }
97 }
98 size->cx = maxlen;
99 size->cy = height;
100}
101
102static void DrawMultilineText(HDC dc, TipWndInfo *info, POINT *point)
103{
104 ::SetTextColor(dc, info->textcolor);
105
106 // Scan the text to determine the longest line (in pixels) and the
107 // total height in pixels.
108 const char *start, *end;
109 SIZE linesize;
110 TEXTMETRIC tm;
111 ::GetTextMetrics(dc, &tm);
112
113 start = info->text;
114 if (start != NULL) {
115 while (*start != '\0') {
116 end = start;
117 while (*end != '\0' && *end != '\n') end++;
118 linesize.cx = linesize.cy = 0;
119 ::TextOut(dc, point->x, point->y, start, end-start);
120 point->y += tm.tmAscent + tm.tmDescent;
121 if (*end == '\n') end++;
122 start = end;
123 }
124 }
125}
126
127static LRESULT CALLBACK TipWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
128{
129 TipWndInfo *info = (TipWndInfo *)::GetWindowLong(hwnd, GWL_USERDATA);
130 if (info == NULL && uMsg != WM_CREATE)
131 return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
132
133 switch (uMsg) {
134
135 case WM_CREATE:
136 info = (TipWndInfo *)malloc(sizeof(TipWndInfo));
137 info->icon = NULL;
138 info->text = NULL;
139 info->textlen = 0;
140 info->flags = TIPWND_ANCHOR_TOPLEFT|TIPWND_ALIGN_LEFT;
141 info->font = NULL;
142 info->bgcolor = GetSysColor(COLOR_INFOBK);
143 info->bordercolor = RGB(0,0,0);
144 info->textcolor = GetSysColor(COLOR_INFOTEXT);
145 info->hpadding = 2;
146 info->vpadding = 2;
147 info->autoshow = 0;
148 info->autopos = 0;
149 info->showdelay = 1000;
150 info->owner = NULL;
151 info->mousex = info->mousey = -32768;
152 info->hidden = 0;
153 info->enabled = 1;
154 info->ourmousex = info->ourmousey = -32768;
155 ::SetWindowLong(hwnd, GWL_USERDATA, (LONG)info);
156 return 0;
157
158 case WM_DESTROY:
159 if (info != NULL) {
160 if (info->font != NULL) ::DeleteObject(info->font);
161 if (info->text != NULL) free(info->text);
162 free(info);
163 }
164 return 0;
165
166 case WM_PAINT:
167 {
168 PAINTSTRUCT ps;
169 HDC dc = ::BeginPaint(hwnd, &ps);
170
171 RECT rect;
172 ::GetClientRect(hwnd, &rect);
173 rect.right -= rect.left;
174 rect.bottom -= rect.top;
175 rect.top = 0;
176 rect.left = 0;
177
178 ::SetBkMode(dc, TRANSPARENT);
179 ::SetTextAlign(dc, TA_TOP|TA_LEFT);
180
181 HFONT font = SetBestFont(dc, info);
182
183 SIZE textsize;
184 ComputeTextExtents(dc, info, &textsize);
185 POINT textpoint;
186
187 SIZE pad;
188 pad.cx = pad.cy = 0;
189 SIZE iconoffset;
190 iconoffset.cx = iconoffset.cy = 0;
191 if (info->icon != NULL) {
192 int delta = (info->flags & 1) ? 32 : 16;
193 switch (info->flags & 6) {
194 case TIPWND_ICON_LEFT:
195 pad.cx = delta + 4;
196 iconoffset.cx = 0;
197 textsize.cx += delta + 4;
198 if (textsize.cy < delta)
199 pad.cy = (delta-textsize.cy)/2, textsize.cy = delta;
200 break;
201 case TIPWND_ICON_RIGHT:
202 pad.cx = 0;
203 iconoffset.cx = textsize.cx + 4;
204 textsize.cx += delta + 4;
205 if (textsize.cy < delta)
206 pad.cy = (delta-textsize.cy)/2, textsize.cy = delta;
207 break;
208 case TIPWND_ICON_TOP:
209 pad.cy = delta + 2;
210 iconoffset.cx = 0;
211 textsize.cy += delta + 2;
212 if (textsize.cx < delta)
213 pad.cx = (delta-textsize.cx)/2, textsize.cx = delta;
214 break;
215 case TIPWND_ICON_BOTTOM:
216 pad.cy = 0;
217 iconoffset.cy = textsize.cy + 2;
218 textsize.cy += delta + 2;
219 if (textsize.cx < delta)
220 pad.cx = (delta-textsize.cx)/2, textsize.cx = delta;
221 break;
222 }
223 }
224
225 if ((info->flags & (TIPWND_ALIGN_LEFT|TIPWND_ALIGN_RIGHT)) == TIPWND_ALIGN_LEFT)
226 textpoint.x = 1+info->hpadding;
227 else if ((info->flags & (TIPWND_ALIGN_LEFT|TIPWND_ALIGN_RIGHT)) == TIPWND_ALIGN_RIGHT)
228 textpoint.x = rect.right - 1 - info->hpadding - textsize.cx;
229 else textpoint.x = rect.right / 2 - textsize.cx / 2;
230
231 if ((info->flags & (TIPWND_ALIGN_TOP|TIPWND_ALIGN_BOTTOM)) == TIPWND_ALIGN_TOP)
232 textpoint.y = 1+info->vpadding;
233 else if ((info->flags & (TIPWND_ALIGN_TOP|TIPWND_ALIGN_BOTTOM)) == TIPWND_ALIGN_BOTTOM)
234 textpoint.y = rect.bottom - 1 - info->vpadding - textsize.cy;
235 else textpoint.y = rect.bottom / 2 - textsize.cy / 2;
236
237 if (info->icon != NULL)
238 ::DrawIcon(dc, textpoint.x+iconoffset.cx,
239 textpoint.y+iconoffset.cy, info->icon);
240 textpoint.x += pad.cx;
241 textpoint.y += pad.cy;
242 DrawMultilineText(dc, info, &textpoint);
243
244 ::SelectObject(dc, font);
245 ::EndPaint(hwnd, &ps);
246 return 0;
247 }
248
249 case WM_ERASEBKGND:
250 {
251 HDC dc = (HDC)wParam;
252
253 RECT rect;
254 ::GetClientRect(hwnd, &rect);
255 rect.right -= rect.left;
256 rect.bottom -= rect.top;
257 rect.top = 0;
258 rect.left = 0;
259
260 HBRUSH bgcolor = ::CreateSolidBrush(info->bgcolor);
261 HBRUSH border = ::CreateSolidBrush(info->bordercolor);
262 ::FrameRect(dc, &rect, border);
263 rect.top++, rect.left++;
264 rect.right--, rect.bottom--;
265 ::FillRect(dc, &rect, bgcolor);
266 ::DeleteObject(bgcolor);
267 ::DeleteObject(border);
268 }
269 return 1;
270
271 case WM_SETICON:
272 if (info->icon == (HICON)lParam) return 0;
273 info->icon = (HICON)lParam;
274 info->flags &= ~TIPWND_LARGE_ICON;
275 if (wParam == ICON_BIG) info->flags |= TIPWND_LARGE_ICON;
276 ::RedrawWindow(hwnd, NULL, NULL, RDW_ERASE|RDW_INTERNALPAINT);
277 return 0;
278
279 case WM_GETICON:
280 return (LRESULT)info->icon;
281
282 case WM_CLEAR:
283 if (info->text == NULL) return 0;
284 free(info->text);
285 info->textlen = 0;
286 info->text = NULL;
287 ::RedrawWindow(hwnd, NULL, NULL, RDW_ERASE|RDW_INTERNALPAINT);
288 return 0;
289
290 case WM_SETTEXT:
291 if ((const char *)lParam == NULL) lParam = (LPARAM)"<null>";
292 if (info->text != NULL) {
293 if (!strcmp(info->text, (const char *)lParam)) return 0;
294 free(info->text);
295 }
296 info->textlen = strlen((const char *)lParam);
297 info->text = (char *)malloc(info->textlen+1);
298 strcpy(info->text, (const char *)lParam);
299 ::RedrawWindow(hwnd, NULL, NULL, RDW_ERASE|RDW_INTERNALPAINT);
300 return 0;
301
302 case WM_GETTEXT:
303 if (lParam != NULL) {
304 strncpy((char *)lParam, info->text, (int)wParam);
305 ((char *)lParam)[wParam-1] = '\0';
306 if ((int)wParam > (int)info->textlen) return (LRESULT)info->textlen;
307 else return (LRESULT)wParam;
308 }
309 return 0;
310
311 case WM_GETTEXTLENGTH:
312 return (LRESULT)info->textlen;
313
314 case WM_SETFONT:
315 if (info->font != NULL) ::DeleteObject(info->font);
316 info->font = (HFONT)wParam;
317 if (lParam != 0) ::RedrawWindow(hwnd, NULL, NULL, RDW_ERASE|RDW_INTERNALPAINT);
318 return 0;
319
320 case WM_GETFONT:
321 return (LRESULT)info->font;
322
323 case WM_ENABLE:
324 if (wParam) {
325 if (!info->enabled) {
326 info->enabled = 1;
327 if (info->autoshow) {
328 if (info->timer == 0)
329 info->timer = ::SetTimer(hwnd, 1, info->showdelay, NULL);
330 if (info->hidetimer == 0)
331 info->hidetimer = ::SetTimer(hwnd, 2, 250, NULL);
332 }
333 }
334 }
335 else {
336 if (info->enabled) {
337 info->enabled = 0;
338 if (info->timer != 0) ::KillTimer(hwnd, 1);
339 if (info->hidetimer != 0) ::KillTimer(hwnd, 2);
340 info->timer = 0;
341 info->hidetimer = 0;
342 if (info->autoshow) {
343 info->mousex = info->mousey = -32768;
344 info->ourmousex = info->ourmousey = -32768;
345 if (!info->hidden) info->hidden = 1, ::ShowWindow(hwnd, SW_HIDE);
346 }
347 }
348 }
349 return 0;
350
351 case WM_COMMAND:
352 switch (wParam) {
353
354 case TW_AUTO_SIZE:
355 {
356 SIZE size;
357 HDC dc = ::GetDC(hwnd);
358 HFONT oldfont = SetBestFont(dc, info);
359 ComputeTextExtents(dc, info, &size);
360 ::SelectObject(dc, oldfont);
361 ::ReleaseDC(hwnd, dc);
362 if (info->icon != NULL) {
363 int delta = (info->flags & 1) ? 32 : 16;
364 switch (info->flags & 6) {
365 case TIPWND_ICON_LEFT:
366 case TIPWND_ICON_RIGHT:
367 size.cx += delta + info->hpadding*2;
368 if (size.cy < delta) size.cy = delta;
369 break;
370 case TIPWND_ICON_TOP:
371 case TIPWND_ICON_BOTTOM:
372 size.cy += delta + info->vpadding*2;
373 if (size.cx < delta) size.cx = delta;
374 break;
375 }
376 }
377
378 RECT rect;
379 ::GetWindowRect(hwnd, &rect);
380 if (rect.right-rect.left != size.cx+2+info->hpadding*2
381 || rect.bottom-rect.top != size.cy+2+info->vpadding*2)
382 ::SetWindowPos(hwnd, NULL, rect.left, rect.top,
383 size.cx+2+info->hpadding*2, size.cy+2+info->vpadding*2,
384 SWP_NOACTIVATE|SWP_NOZORDER);
385 else ::RedrawWindow(hwnd, NULL, NULL, RDW_ERASE|RDW_INTERNALPAINT);
386 }
387 return 0;
388
389 case TW_SET_ANCHOR:
390 info->flags &= ~(8|16|32|64);
391 info->flags |= ((lParam & 15) << 3);
392 return 0;
393
394 case TW_GET_ANCHOR:
395 return (LRESULT)((info->flags >> 3) & (8|16|32|64));
396
397 case TW_SET_ICONPOS:
398 if ((info->flags & 6) != ((lParam & 3) << 1)) {
399 info->flags &= ~(2|4);
400 info->flags |= ((lParam & 3) << 1);
401 ::RedrawWindow(hwnd, NULL, NULL, RDW_ERASE|RDW_INTERNALPAINT);
402 }
403 return 0;
404
405 case TW_GET_ICONPOS:
406 return (LRESULT)((info->flags >> 1) & 3);
407
408 case TW_SET_BGCOLOR:
409 if (lParam != (LPARAM)info->bgcolor) {
410 info->bgcolor = lParam;
411 ::RedrawWindow(hwnd, NULL, NULL, RDW_ERASE|RDW_INTERNALPAINT);
412 }
413 return 0;
414
415 case TW_GET_BGCOLOR:
416 return (LRESULT)info->bgcolor;
417
418 case TW_SET_TEXTCOLOR:
419 if (lParam != (LPARAM)info->textcolor) {
420 info->textcolor = lParam;
421 ::RedrawWindow(hwnd, NULL, NULL, RDW_ERASE|RDW_INTERNALPAINT);
422 }
423 return 0;
424
425 case TW_GET_TEXTCOLOR:
426 return (LRESULT)info->textcolor;
427
428 case TW_SET_BORDERCOLOR:
429 if (lParam != (LPARAM)info->bordercolor) {
430 info->bordercolor = lParam;
431 ::RedrawWindow(hwnd, NULL, NULL, RDW_ERASE|RDW_INTERNALPAINT);
432 }
433 return 0;
434
435 case TW_GET_BORDERCOLOR:
436 return (LRESULT)info->bordercolor;
437
438 case TW_SET_AUTOSHOW:
439 if (info->autoshow != lParam) {
440 info->autoshow = (lParam != 0);
441 if (info->timer != 0) {
442 ::KillTimer(hwnd, info->timer);
443 info->timer = 0;
444 }
445 if (info->hidetimer != 0) {
446 ::KillTimer(hwnd, info->hidetimer);
447 info->hidetimer = 0;
448 }
449 if (info->autoshow) {
450 info->timer = ::SetTimer(hwnd, 1, info->showdelay, NULL);
451 info->hidetimer = ::SetTimer(hwnd, 2, 250, NULL);
452 }
453 }
454 return 0;
455
456 case TW_GET_AUTOSHOW:
457 return info->autoshow;
458
459 case TW_SET_SHOWDELAY:
460 if (info->showdelay != lParam) {
461 info->showdelay = (short int)lParam;
462 if (info->showdelay < 1) info->showdelay = 1;
463 if (info->timer != 0) {
464 ::KillTimer(hwnd, info->timer);
465 info->timer = 0;
466 info->hidetimer = 0;
467 }
468 if (info->autoshow) {
469 info->timer = ::SetTimer(hwnd, 1, info->showdelay, NULL);
470 }
471 }
472 return 0;
473
474 case TW_GET_SHOWDELAY:
475 return info->showdelay;
476
477 case TW_SET_AUTOPOS:
478 info->autopos = (lParam != 0);
479 return 0;
480
481 case TW_GET_AUTOPOS:
482 return info->autopos;
483
484 case TW_SET_HPADDING:
485 if (info->hpadding != (int)lParam) {
486 info->hpadding = (int)lParam;
487 ::RedrawWindow(hwnd, NULL, NULL, RDW_ERASE|RDW_INTERNALPAINT);
488 }
489 return 0;
490
491 case TW_GET_HPADDING:
492 return info->hpadding;
493
494 case TW_SET_VPADDING:
495 if (info->vpadding != (int)lParam) {
496 info->vpadding = (int)lParam;
497 ::RedrawWindow(hwnd, NULL, NULL, RDW_ERASE|RDW_INTERNALPAINT);
498 }
499 return 0;
500
501 case TW_GET_VPADDING:
502 return info->vpadding;
503
504 case TW_GET_OWNER:
505 return (LRESULT)info->owner;
506
507 case TW_REFLECT_MESSAGE:
508 {
509 MSG *msg = (MSG *)lParam;
510 if (msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONUP
511 || msg->message == WM_RBUTTONDOWN || msg->message == WM_RBUTTONUP
512 || msg->message == WM_MBUTTONDOWN || msg->message == WM_MBUTTONUP
513 || msg->message == WM_MOUSEMOVE || msg->message == WM_KILLFOCUS
514 || msg->message == WM_SETFOCUS || msg->message == WM_KEYDOWN
515 || msg->message == WM_KEYUP) {
516 if (msg->message == WM_MOUSEMOVE) {
517 if (info->mousex == LOWORD(msg->lParam)
518 && info->mousey == HIWORD(msg->lParam)) return 0;
519 info->mousex = LOWORD(msg->lParam);
520 info->mousey = HIWORD(msg->lParam);
521 }
522 if (info->timer != 0 && info->showdelay > 1) {
523 ::KillTimer(hwnd, info->timer);
524 info->timer = 0;
525 info->hidetimer = 0;
526 info->mousex = info->mousey = -32768;
527 info->ourmousex = info->ourmousey = -32768;
528 if (!info->hidden) info->hidden = 1, ::ShowWindow(hwnd, SW_HIDE);
529 }
530 if (info->autoshow && msg->message != WM_KILLFOCUS) {
531 info->timer = ::SetTimer(hwnd, 1, info->showdelay, NULL);
532 }
533 }
534 }
535 return 0;
536
537 default:
538 return 0;
539 }
540
541 case WM_LBUTTONDOWN:
542 case WM_LBUTTONUP:
543 case WM_RBUTTONDOWN:
544 case WM_RBUTTONUP:
545 case WM_MBUTTONDOWN:
546 case WM_MBUTTONUP:
547 {
548 POINT point;
549 point.x = LOWORD(lParam);
550 point.y = HIWORD(lParam);
551 ::ClientToScreen(hwnd, &point);
552 ::ScreenToClient(info->owner, &point);
553 ::SendMessage(info->owner, uMsg, wParam, MAKELPARAM(point.x, point.y));
554 }
555 return 0;
556
557 case WM_MOUSEMOVE:
558 {
559 POINT point;
560 point.x = LOWORD(lParam);
561 point.y = HIWORD(lParam);
562 if (point.x != info->ourmousex || point.y != info->ourmousey) {
563 info->ourmousex = point.x, info->ourmousey = point.y;
564 ::ClientToScreen(hwnd, &point);
565 ::ScreenToClient(info->owner, &point);
566 ::SendMessage(info->owner, uMsg, wParam, MAKELPARAM(point.x, point.y));
567 }
568 }
569 return 0;
570
571 case WM_TIMER:
572 if (wParam == 1) {
573 if (info->timer != 0) {
574 ::KillTimer(hwnd, info->timer);
575 info->timer = 0;
576 info->hidetimer = 0;
577 }
578 if (info->autoshow) {
579 if (info->autopos) {
580 RECT rect;
581 POINT point;
582 ::GetWindowRect(hwnd, &rect);
583 ::GetCursorPos(&point);
584 if (point.x + (rect.right-rect.left) > GetSystemMetrics(SM_CXSCREEN) - 16)
585 point.x = GetSystemMetrics(SM_CXSCREEN) - (rect.right-rect.left) - 16;
586 if (point.y + (rect.bottom-rect.top) > GetSystemMetrics(SM_CYSCREEN) - 16)
587 point.y = GetSystemMetrics(SM_CYSCREEN) - (rect.bottom-rect.top) - 16;
588 if (rect.left != point.x+16 || rect.top != point.y+16) {
589 ::SetWindowPos(hwnd, NULL, point.x+16, point.y+16,
590 rect.right-rect.left, rect.bottom-rect.top, SWP_NOACTIVATE|SWP_NOZORDER);
591 info->ourmousex = info->ourmousey = -32768;
592 }
593 else ::RedrawWindow(hwnd, NULL, NULL, RDW_ERASE|RDW_INTERNALPAINT);
594 }
595 if (::IsWindowEnabled(hwnd)) {
596 ::BringWindowToTop(hwnd);
597 if (info->hidden) info->hidden = 0, ::ShowWindow(hwnd, SW_SHOWNOACTIVATE);
598 ::UpdateWindow(hwnd);
599 }
600 if (info->hidetimer == 0)
601 info->hidetimer = ::SetTimer(hwnd, 2, 250, NULL);
602 }
603 }
604 else if (wParam == 2) {
605 // If the mouse is no longer in the window and we're using autoshow,
606 // hide the tip with a quickness.
607 POINT point;
608 ::GetCursorPos(&point);
609 HWND wnd = ::WindowFromPoint(point);
610 // If the window the mouse is over is a TipWnd, then the mouse is
611 // really just over that TipWnd's owner.
612 char cname[32];
613 ::GetClassName(wnd, cname, 31);
614 if (!strcmp(cname, CLASSNAME))
615 wnd = (HWND)::SendMessage(wnd, WM_COMMAND, TW_GET_OWNER, 0);
616 // If the mouse has moved out of this TipWnd's owner, hide the TipWnd.
617 if (wnd != info->owner) {
618 ::KillTimer(hwnd, info->timer);
619 ::KillTimer(hwnd, info->hidetimer);
620 info->timer = 0;
621 info->hidetimer = 0;
622 info->mousex = info->mousey = -32768;
623 info->ourmousex = info->ourmousey = -32768;
624 if (!info->hidden) info->hidden = 1, ::ShowWindow(hwnd, SW_HIDE);
625 }
626 }
627 return 0;
628
629 default:
630 return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
631 }
632}
633
634/***************************************************************************/
635
636static HINSTANCE theInst;
637
638void WINAPI ::InitTipWnd(HINSTANCE inst)
639{
640 static bool initted = 0;
641
642 if (initted) return;
643
644 WNDCLASSEX wc;
645
646 wc.cbSize = sizeof(WNDCLASSEX);
647 wc.cbClsExtra = 0;
648 wc.cbWndExtra = sizeof(void *);
649 wc.hbrBackground = NULL;
650 wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
651 wc.hIcon = NULL;
652 wc.hIconSm = NULL;
653 wc.hInstance = theInst;
654 wc.lpszClassName = CLASSNAME;
655 wc.lpszMenuName = NULL;
656 wc.style = CS_VREDRAW|CS_HREDRAW|CS_SAVEBITS;
657 wc.lpfnWndProc = TipWndProc;
658
659 ::RegisterClassEx(&wc);
660
661 initted = 1;
662}
663
664HWND WINAPI ::CreateTipWnd(HWND owner, const RECT *rect, BOOL showwnd)
665{
666 HWND hwnd = ::CreateWindowEx(WS_EX_TOPMOST, CLASSNAME, "", WS_POPUP,
667 rect->left, rect->top, rect->right-rect->left, rect->bottom-rect->top,
668 owner, NULL, theInst, NULL);
669 TipWndInfo *info = (TipWndInfo *)::GetWindowLong(hwnd, GWL_USERDATA);
670 if (info != NULL) info->owner = owner;
671 return hwnd;
672}
673
674HWND WINAPI ::CreateTipWndEz(HWND owner, int x, int y,
675 const char *text, HICON icon, BOOL showwnd)
676{
677 POINT point;
678 point.x = x, point.y = y;
679 ::ClientToScreen(owner, &point);
680 RECT rect;
681 rect.left = point.x, rect.top = point.y;
682 rect.right = point.x + 64, rect.bottom = point.y + 16;
683
684 HWND wnd = CreateTipWnd(owner, &rect, 0);
685 if (wnd == NULL) return NULL;
686
687 TipWnd_SetText(wnd, text);
688 TipWnd_SetIcon(wnd, icon, ICON_BIG);
689
690 if (showwnd) {
691 ::BringWindowToTop(wnd);
692 ::ShowWindow(wnd, SW_SHOWNOACTIVATE);
693 ::UpdateWindow(wnd);
694 }
695
696 return wnd;
697}
698
699/***************************************************************************/
700
701/* The MFC class wrapper. Very simple, since the Windows HWND does
702 all the real work. */
703
704IMPLEMENT_DYNAMIC(CTipWnd, CWnd)
705
706CTipWnd::CTipWnd()
707{
708}
709
710CTipWnd::~CTipWnd()
711{
712 DestroyWindow();
713}
714
715BOOL CTipWnd::Create(CWnd *owner, const RECT &rect, BOOL showwnd)
716{
717 CWnd *pWnd = this;
718 if (!pWnd->CreateEx(WS_EX_TOPMOST, _T(CLASSNAME), _T(""), WS_POPUP, rect, owner, 0, NULL))
719 return 0;
720 TipWndInfo *info = (TipWndInfo *)::GetWindowLong(m_hWnd, GWL_USERDATA);
721 if (info != NULL) info->owner = owner->m_hWnd;
722
723 if (showwnd) {
724 pWnd->BringWindowToTop();
725 pWnd->ShowWindow(SW_SHOWNOACTIVATE);
726 pWnd->UpdateWindow();
727 }
728
729 return 1;
730}
731
732BOOL CTipWnd::CreateEz(CWnd *owner, int x, int y, const CString &text,
733 HICON icon, BOOL showwnd)
734{
735 CPoint point(x, y);
736 owner->ClientToScreen(&point);
737 CRect rect(point.x, point.y, point.x+64, point.y+16);
738
739 if (!Create(owner, rect, 0)) return 0;
740
741 SetWindowText(text);
742 SetIcon(icon, 1);
743
744 if (showwnd) {
745 BringWindowToTop();
746 ShowWindow(SW_SHOWNOACTIVATE);
747 UpdateWindow();
748 }
749
750 return 1;
751}
752
753void CTipWnd::MoveWindow(CWnd *owner, int x, int y)
754{
755 CPoint point(x, y);
756 owner->ClientToScreen(&point);
757 SetWindowPos(NULL, point.x, point.y, 0, 0, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE);
758}
759
760void CTipWnd::PushOnScreen(void)
761{
762 CRect rect;
763 GetWindowRect(&rect);
764 short int scrnwidth = GetSystemMetrics(SM_CXSCREEN);
765 short int scrnheight = GetSystemMetrics(SM_CYSCREEN);
766 if (rect.right > scrnwidth)
767 rect.left -= rect.right-scrnwidth, rect.right = scrnwidth;
768 if (rect.bottom > scrnheight)
769 rect.top -= rect.bottom-scrnheight, rect.top = scrnheight;
770 if (rect.left < 0)
771 rect.right -= 0-rect.left, rect.left = 0;
772 if (rect.top < 0)
773 rect.bottom -= 0-rect.top, rect.top = 0;
774 SetWindowPos(NULL, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top,
775 SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE);
776}
777
778// MFC's default handling of OnCommand screws up our message-passing, so
779// we override to fix it.
780BOOL CTipWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT *pResult)
781{
782 if (message == WM_COMMAND) {
783 *pResult = TipWndProc(m_hWnd, message, wParam, lParam);
784 return 1;
785 }
786 else return CWnd::OnWndMsg(message, wParam, lParam, pResult);
787}
788
789/***************************************************************************/
diff --git a/TipWnd.h b/TipWnd.h
new file mode 100644
index 0000000..b40ead0
--- /dev/null
+++ b/TipWnd.h
@@ -0,0 +1,203 @@
1#ifndef TIPWND_H
2#define TIPWND_H
3
4/* TipWnd messages */
5enum {
6 TW_AUTO_SIZE = 101,
7 TW_SET_ANCHOR = 102,
8 TW_GET_ANCHOR = 103,
9 TW_SET_ICONPOS = 104,
10 TW_GET_ICONPOS = 105,
11 TW_SET_BGCOLOR = 106,
12 TW_GET_BGCOLOR = 107,
13 TW_SET_TEXTCOLOR = 108,
14 TW_GET_TEXTCOLOR = 109,
15 TW_SET_BORDERCOLOR = 110,
16 TW_GET_BORDERCOLOR = 111,
17 TW_SET_AUTOSHOW = 112,
18 TW_GET_AUTOSHOW = 113,
19 TW_SET_AUTOPOS = 114,
20 TW_GET_AUTOPOS = 115,
21 TW_SET_SHOWDELAY = 116,
22 TW_GET_SHOWDELAY = 117,
23 TW_SET_HPADDING = 118,
24 TW_GET_HPADDING = 119,
25 TW_SET_VPADDING = 120,
26 TW_GET_VPADDING = 121,
27 TW_GET_OWNER = 122,
28 TW_REFLECT_MESSAGE = 199,
29};
30
31/* TipWnd message parameters */
32enum {
33 TW_LEFT = 0,
34 TW_TOP = 1,
35 TW_RIGHT = 2,
36 TW_BOTTOM = 3,
37
38 TW_ALIGN_LEFT = 1,
39 TW_ALIGN_TOP = 2,
40 TW_ALIGN_RIGHT = 4,
41 TW_ALIGN_BOTTOM = 8,
42
43 TW_ALIGN_TOPLEFT = 1|2,
44 TW_ALIGN_TOPRIGHT = 2|4,
45 TW_ALIGN_BOTTOMLEFT = 1|8,
46 TW_ALIGN_BOTTOMRIGHT = 2|8,
47};
48
49/***************************************************************************/
50
51/* TipWnd helper macros */
52#define TipWnd_AutoSize(hwnd) \
53 SendMessage(hwnd, WM_COMMAND, TW_AUTO_SIZE, 0)
54#define TipWnd_SetAnchor(hwnd, anchor) \
55 SendMessage(hwnd, WM_COMMAND, TW_SET_ANCHOR, (LPARAM)(anchor))
56#define TipWnd_GetAnchor(hwnd) \
57 SendMessage(hwnd, WM_COMMAND, TW_GET_ANCHOR, 0)
58#define TipWnd_SetIconPos(hwnd, pos) \
59 SendMessage(hwnd, WM_COMMAND, TW_SET_ICONPOS, (LPARAM)(pos))
60#define TipWnd_GetIconPos(hwnd) \
61 SendMessage(hwnd, WM_COMMAND, TW_GET_ICONPOS, 0)
62#define TipWnd_SetBgColor(hwnd, color) \
63 SendMessage(hwnd, WM_COMMAND, TW_SET_BGCOLOR, (LPARAM)(color))
64#define TipWnd_GetBgColor(hwnd) \
65 SendMessage(hwnd, WM_COMMAND, TW_GET_BGCOLOR, 0)
66#define TipWnd_SetTextColor(hwnd, color) \
67 SendMessage(hwnd, WM_COMMAND, TW_SET_TEXTCOLOR, (LPARAM)(color))
68#define TipWnd_GetTextColor(hwnd) \
69 SendMessage(hwnd, WM_COMMAND, TW_GET_TEXTCOLOR, 0)
70#define TipWnd_SetBorderColor(hwnd, color) \
71 SendMessage(hwnd, WM_COMMAND, TW_SET_BORDERCOLOR, (LPARAM)(color))
72#define TipWnd_GetBorderColor(hwnd) \
73 SendMessage(hwnd, WM_COMMAND, TW_GET_BORDERCOLOR, 0)
74#define TipWnd_SetFont(hwnd, font, redraw) \
75 SendMessage(hwnd, WM_SETFONT, (WPARAM)(font), (LPARAM)(redraw))
76#define TipWnd_GetFont(hwnd) \
77 SendMessage(hwnd, WM_GETFONT, 0, 0)
78#define TipWnd_SetText(hwnd, text) \
79 SendMessage(hwnd, WM_SETTEXT, 0, (WPARAM)(text))
80#define TipWnd_GetText(hwnd, buffer, buflen) \
81 SendMessage(hwnd, WM_GETTEXT, (WPARAM)(buffer), (LPARAM)(buflen))
82#define TipWnd_GetTextLength(wnd) \
83 SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0)
84#define TipWnd_SetIcon(hwnd, type, icon) \
85 SendMessage(hwnd, WM_SETICON, (WPARAM)(type), (LPARAM)(icon))
86#define TipWnd_GetIcon(hwnd) \
87 SendMessage(hwnd, WM_GETICON, 0, 0)
88#define TipWnd_SetAutoShow(hwnd, enable) \
89 SendMessage(hwnd, WM_COMMAND, TW_SET_AUTOSHOW, (LPARAM)(enable))
90#define TipWnd_GetAutoShow(hwnd) \
91 SendMessage(hwnd, WM_COMMAND, TW_GET_AUTOSHOW, 0)
92#define TipWnd_SetShowDelay(hwnd, delay) \
93 SendMessage(hwnd, WM_COMMAND, TW_SET_SHOWDELAY, (LPARAM)(delay))
94#define TipWnd_GetShowDelay(hwnd) \
95 SendMessage(hwnd, WM_COMMAND, TW_GET_SHOWDELAY, 0)
96#define TipWnd_ReflectMessage(hwnd, pmsg) \
97 SendMessage(hwnd, WM_COMMAND, TW_REFLECT_MESSAGE, (LPARAM)(pmsg))
98#define TipWnd_SetAutoPos(hwnd, pos) \
99 SendMessage(hwnd, WM_COMMAND, TW_SET_AUTOPOS, (LPARAM)(pos))
100#define TipWnd_GetAutoPos(hwnd) \
101 SendMessage(hwnd, WM_COMMAND, TW_GET_AUTOPOS, 0)
102#define TipWnd_SetHPadding(hwnd, padding) \
103 SendMessage(hwnd, WM_COMMAND, TW_SET_HPADDING, (WPARAM)(padding))
104#define TipWnd_GetHPadding(hwnd) \
105 SendMessage(hwnd, WM_COMMAND, TW_GET_HPADDING, 0)
106#define TipWnd_SetVPadding(hwnd, padding) \
107 SendMessage(hwnd, WM_COMMAND, TW_SET_VPADDING, (WPARAM)(padding))
108#define TipWnd_GetVPadding(hwnd) \
109 SendMessage(hwnd, WM_COMMAND, TW_GET_VPADDING, 0)
110#define TipWnd_GetOwner(hwnd) \
111 SendMessage(hwnd, WM_COMMAND, TW_GET_OWNER, 0)
112
113/***************************************************************************/
114
115#ifdef __cplusplus
116extern "C" {
117#endif
118
119// TipWnd functions
120void WINAPI InitTipWnd(HINSTANCE inst);
121HWND WINAPI CreateTipWnd(HWND owner, const RECT *rect, BOOL showwnd);
122HWND WINAPI CreateTipWndEz(HWND owner, int x, int y,
123 const char *text, HICON icon, BOOL showwnd);
124
125#ifdef __cplusplus
126};
127#endif
128
129/***************************************************************************/
130
131#ifdef __AFXWIN_H__
132
133/* MFC support class, if they're using MFC. Like most of the MFC classes,
134 it's just a wrapper around the Windows HWND. You still have to call
135 InitTipWnd() somewhere at the beginning of your program, though. */
136
137class CTipWnd : public CWnd {
138 DECLARE_DYNAMIC(CTipWnd)
139
140public:
141 CTipWnd();
142 virtual ~CTipWnd();
143 virtual BOOL Create(CWnd *owner, const RECT &rect, BOOL showwnd = 0);
144 virtual BOOL CreateEz(CWnd *owner, int x, int y, const CString &text = "",
145 HICON icon = NULL, BOOL showwnd = 0);
146 void MoveWindow(CWnd *owner, int x, int y);
147 void PushOnScreen(void);
148
149protected:
150 virtual BOOL OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT *pResult);
151
152public:
153 inline void AutoSize(void)
154 { SendMessage(WM_COMMAND, TW_AUTO_SIZE); }
155 inline void SetAnchor(int anchor)
156 { SendMessage(WM_COMMAND, TW_SET_ANCHOR, (LPARAM)anchor); }
157 inline int GetAnchor(void)
158 { return SendMessage(WM_COMMAND, TW_GET_ANCHOR); }
159 inline void SetIconPos(int iconpos)
160 { SendMessage(WM_COMMAND, TW_SET_ICONPOS, (LPARAM)iconpos); }
161 inline int GetIconPos(void)
162 { return SendMessage(WM_COMMAND, TW_GET_ICONPOS); }
163 inline void SetBgColor(COLORREF color)
164 { SendMessage(WM_COMMAND, TW_SET_BGCOLOR, (LPARAM)color); }
165 inline int GetBgColor(void)
166 { return SendMessage(WM_COMMAND, TW_GET_BGCOLOR); }
167 inline void SetTextColor(COLORREF color)
168 { SendMessage(WM_COMMAND, TW_SET_TEXTCOLOR, (LPARAM)color); }
169 inline int GetTextColor(void)
170 { return SendMessage(WM_COMMAND, TW_GET_TEXTCOLOR); }
171 inline void SetBorderColor(COLORREF color)
172 { SendMessage(WM_COMMAND, TW_SET_BORDERCOLOR, (LPARAM)color); }
173 inline int GetBorderColor(void)
174 { return SendMessage(WM_COMMAND, TW_GET_BORDERCOLOR); }
175 inline void SetAutoShow(BOOL bEnable)
176 { SendMessage(WM_COMMAND, TW_SET_AUTOSHOW, (LPARAM)bEnable); }
177 inline BOOL GetAutoShow(void)
178 { return (BOOL)SendMessage(WM_COMMAND, TW_GET_AUTOSHOW); }
179 inline void SetShowDelay(int delay)
180 { SendMessage(WM_COMMAND, TW_SET_SHOWDELAY, (LPARAM)delay); }
181 inline int GetShowDelay(void)
182 { return SendMessage(WM_COMMAND, TW_GET_SHOWDELAY); }
183 inline void SetAutoPos(BOOL bAutoPos)
184 { SendMessage(WM_COMMAND, TW_SET_AUTOPOS, (LPARAM)bAutoPos); }
185 inline int GetAutoPos(void)
186 { return SendMessage(WM_COMMAND, TW_GET_AUTOPOS); }
187 inline void ReflectMessage(const MSG *msg)
188 { SendMessage(WM_COMMAND, TW_REFLECT_MESSAGE, (LPARAM)msg); }
189 inline void SetHPadding(int padding)
190 { SendMessage(WM_COMMAND, TW_SET_HPADDING, (LPARAM)padding); }
191 inline int GetHPadding(void)
192 { return SendMessage(WM_COMMAND, TW_GET_HPADDING); }
193 inline void SetVPadding(int padding)
194 { SendMessage(WM_COMMAND, TW_SET_VPADDING, (LPARAM)padding); }
195 inline int GetVPadding(void)
196 { return SendMessage(WM_COMMAND, TW_GET_VPADDING); }
197 inline CWnd *GetTipWndOwner(void)
198 { return CWnd::FromHandle((HWND)SendMessage(WM_COMMAND, TW_GET_OWNER)); }
199};
200
201#endif
202
203#endif
diff --git a/lang.h b/lang.h
new file mode 100644
index 0000000..2dd0e0a
--- /dev/null
+++ b/lang.h
@@ -0,0 +1,51 @@
1
2#ifndef LANG_H
3#define LANG_H
4
5struct Lang {
6 int toolbar_bitmap_id;
7 const char *about_spacemonger;
8 const char *freeware;
9 const char *warranty;
10 const char *email;
11 const char *ok, *cancel;
12 const char *bytes, *kb, *mb, *gb;
13 const char *freespace_format;
14 const char *zoomin, *zoomout, *zoomfull, *run, *del;
15 const char *opendrive, *rescandrive, *showfreespace;
16 const char *percent_format, *size_format;
17 const char *total, *free, *files_total, *folders_total, *files_found, *folders_found;
18 char digitpt, digitcomma;
19 const char **densitynames;
20 const char **colornames;
21 const char **monthnames;
22 const char **attribnames;
23 const char *deleting;
24 const char *selectdrive;
25 const char *scanning;
26 const char *settings;
27 const char *layout, *density, *bias, *horz, *equal, *vert;
28 const char *displaycolors, *files, *folders;
29 const char *tooltips, *shownametips, *showinfotips, *delay, *msec;
30 const char *fullpath, *filename, *smallicon, *icon, *datetime, *filesize, *attrib;
31 const char *miscoptions;
32 const char *autorescan, *disabledelete, *animatedzoom, *savepos;
33 const char *showrolloverbox;
34 const char *properties;
35};
36
37struct LangEntry {
38 const char *abbrev;
39 const char *name;
40 Lang *text;
41};
42
43extern Lang *CurLang; // Current language
44
45extern Lang LangUs; // English (US)
46extern Lang LangUk; // English (UK/Aust.)
47extern Lang LangFr; // Français (Nationale)
48
49extern LangEntry Langs[]; // List of languages
50
51#endif
diff --git a/lang_en.cpp b/lang_en.cpp
new file mode 100644
index 0000000..cc1f9d3
--- /dev/null
+++ b/lang_en.cpp
@@ -0,0 +1,109 @@
1
2#include "stdafx.h"
3#include "SpaceMonger.h"
4#include "lang.h"
5
6LangEntry Langs[] = {
7 { "us", "English (US)", &LangUs },
8 { "uk", "English (UK/Aust.)", &LangUk },
9 { "fr", "Français (Nationale)", &LangFr },
10 { NULL, NULL, NULL },
11};
12
13Lang *CurLang = &LangUs;
14
15/////////////////////////////////////////////////////////////////////////////
16
17static const char *densitynames[] = {
18 "Too Few Files", "Very Few Files", "Normal", "Lots of Files",
19 "Very Many Files", "Too Many Files",
20};
21
22static const char *uscolornames[] = {
23 "Rainbow", "Windows Colors", "White", "Light Gray", "Dark Gray",
24 "Red", "Orange", "Yellow", "Green", "Aqua", "Blue", "Violet",
25};
26
27static const char *monthnames[] = {
28 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
29 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
30};
31
32static const char *attribnames[] = {
33 "Arch", "Compress", "Folder", "Encrypt", "Hidden", "Offline",
34 "Read-Only", "Reparse-Pt", "Sparse", "System", "Temp",
35};
36
37Lang LangUs = {
38 IDR_TOOLBAR_EN,
39 "About SpaceMonger",
40 "THIS PROGRAM IS FREEWARE.",
41 "You may distribute this program freely. Because this program is"
42 " free, the author cannot and will not assume responsibility"
43 " for this program's behavior. There are no warranties of any"
44 " kind, expressed or implied, on this product.",
45 "Have questions? Found a bug? Want a feature?\n"
46 "E-mail to <sean@werkema.com>.",
47 "OK", "Cancel",
48 "bytes", "Kb", "Mb", "Gb",
49 "<Free Space: %d.%d%%>",
50 "Zoom &In", "Zoom &Out", "Zoom &Full", "&Run / Open", "&Delete",
51 "&Open Drive...", "&Rescan Drive", "&Show Free Space",
52 "%lu.%01lu%%", "%lu.%01lu %s",
53 "Total", "Free", "Files Total:", "Folders Total:", "Files Found:", "Folders Found:",
54 '.', ',',
55 densitynames, uscolornames, monthnames, attribnames,
56 "Deleting...",
57 "Select Drive to View",
58 "Scanning Disk...",
59 "SpaceMonger Settings",
60 "File Layout", "Density:", "Bias:", "Horz", "Equal", "Vert",
61 "Display Colors", "Files", "Folders",
62 "ToolTips", "Show file-name-tips", "Show file-info-tips", "Delay:", "msec",
63 "Full Path", "Filename", "Small Icon", "Icon", "Date / Time", "File Size", "Attributes",
64 "Miscellaneous Options",
65 "Auto Rescan on Delete", "Disable \"Delete\" Command",
66 "Animated Zoom In / Zoom Out", "Remember Window Position",
67 "Show Rollover Boxes",
68 "Properties...",
69};
70
71static const char *ukcolornames[] = {
72 "Rainbow", "Windows Colours", "White", "Light Gray", "Dark Gray",
73 "Red", "Orange", "Yellow", "Green", "Aqua", "Blue", "Violet",
74};
75
76Lang LangUk = {
77 IDR_TOOLBAR_EN,
78 "About SpaceMonger",
79 "THIS PROGRAM IS FREEWARE.",
80 "You may distribute this program freely. Because this program is"
81 " free, the author cannot and will not assume responsibility"
82 " for this program's behavior. There are no warranties of any"
83 " kind, expressed or implied, on this product.",
84 "Have questions? Found a bug? Want a feature?\n"
85 "E-mail to <sean@werkema.com>.",
86 "OK", "Cancel",
87 "bytes", "Kb", "Mb", "Gb",
88 "<Free Space: %d.%d%%>",
89 "Zoom &In", "Zoom &Out", "Zoom &Full", "&Run / Open", "&Delete",
90 "&Open Drive...", "&Rescan Drive", "&Show Free Space",
91 "%lu.%01lu%%", "%lu.%01lu %s",
92 "Total", "Free", "Files Total:", "Folders Total:", "Files Found:", "Folders Found:",
93 '.', ',',
94 densitynames, ukcolornames, monthnames, attribnames,
95 "Deleting...",
96 "Select Drive to View",
97 "Scanning Disk...",
98 "SpaceMonger Settings",
99 "File Layout", "Density:", "Bias:", "Horz", "Equal", "Vert",
100 "Display Colours", "Files", "Folders",
101 "ToolTips", "Show file-name-tips", "Show file-info-tips", "Delay:", "msec",
102 "Full Path", "Filename", "Small Icon", "Icon", "Date / Time", "File Size", "Attributes",
103 "Miscellaneous Options",
104 "Auto Rescan on Delete", "Disable \"Delete\" Command",
105 "Animated Zoom In / Zoom Out", "Remember Window Position",
106 "Show Rollover Boxes",
107 "Properties...",
108};
109
diff --git a/lang_fr.cpp b/lang_fr.cpp
new file mode 100644
index 0000000..78ceea8
--- /dev/null
+++ b/lang_fr.cpp
@@ -0,0 +1,58 @@
1
2#include "stdafx.h"
3#include "SpaceMonger.h"
4#include "lang.h"
5
6static const char *densitynames[] = {
7 "Petit Peu de Fichiers", "Peu de Fichiers", "Normal", "Beaucoup de Fichiers",
8 "Très Beaucoup de Fichiers", "Trop de Fichiers",
9};
10
11static const char *uscolornames[] = {
12 "Arc-en-Ceil", "Colours de Windows", "Blanc", "Gris Clair", "Gris Foncé",
13 "Rouge", "Orange", "Jaune", "Vert", "Aqua", "Bleu", "Violette",
14};
15
16static const char *monthnames[] = {
17 "Jan", "Fev", "Mars", "Avril", "Mai", "Juin",
18 "Juil", "Août", "Sep", "Oct", "Nov", "Dec",
19};
20
21static const char *attribnames[] = {
22 "Arch", "Compress", "Dossier", "Encrypt", "Caché", "Pas-au-ligne",
23 "Lire-Seulement", "Reparse-Pt", "Clairsemé", "Système", "Temp",
24};
25
26Lang LangFr = {
27 IDR_TOOLBAR_FR,
28 "De SpaceMonger",
29 "CE PROGRAMME EST FREEWARE.",
30 "«You may distribute this program freely. Because this program is"
31 " free, the author cannot and will not assume responsibility"
32 " for this program's behavior. There are no warranties of any"
33 " kind, expressed or implied, on this product.»",
34 "Vous avez des questions? Trouvez un «bug»? Voudriez quelque-chose? "
35 "Envoyez e-mail à «sean@werkema.com».",
36 "D'accord", "Annul",
37 "octets", "Ko", "Mo", "Go",
38 "<l'Espace Libre: %d,%d%%>",
39 "&Vrombir", "&Démarrer", "Voir &Tout", "&Exécuter", "&Effacer",
40 "&Ouvrir un Disque...", "&Rouvrir", "&Montrer l'Espace Libre",
41 "%lu,%01lu%%", "%lu,%01lu %s",
42 "Total", "Libre", "Fichiers Totals:", "Dossiers Totals:", "Fichiers Trouvés:", "Dossiers Trouvés:",
43 ',', '.',
44 densitynames, uscolornames, monthnames, attribnames,
45 "Effacer...",
46 "Choisir un Disque",
47 "Scruter le Disque...",
48 "Configuration de SpaceMonger",
49 "Orientation des Fichiers", "Densité:", "Orient:", "Horz", "Égale", "Vert",
50 "Colours", "Fichiers", "Dossiers",
51 "«ToolTips»", "Montrer Nom «ToolTips»", "Montrer Info «ToolTips»", "Délai:", "msec",
52 "Sentier", "Nom-fichier", "Petit Icon", "Icon", "Date/Heure", "Octets", "Attributs",
53 "Autres Options",
54 "Auto-Rouvrir à Effacer", "Pas de Command «Effacer»",
55 "Vrombir Animé", "Souvenir Position du Window",
56 "Montrer les Boites «Rollovers»",
57 "Properties...",
58};
diff --git a/res/SpaceMonger.ico b/res/SpaceMonger.ico
new file mode 100644
index 0000000..123634e
--- /dev/null
+++ b/res/SpaceMonger.ico
Binary files differ
diff --git a/res/scan1.bmp b/res/scan1.bmp
new file mode 100644
index 0000000..588f602
--- /dev/null
+++ b/res/scan1.bmp
Binary files differ
diff --git a/res/scan2.bmp b/res/scan2.bmp
new file mode 100644
index 0000000..395f963
--- /dev/null
+++ b/res/scan2.bmp
Binary files differ
diff --git a/res/scan3.bmp b/res/scan3.bmp
new file mode 100644
index 0000000..986c690
--- /dev/null
+++ b/res/scan3.bmp
Binary files differ
diff --git a/res/scan4.bmp b/res/scan4.bmp
new file mode 100644
index 0000000..9c64ee2
--- /dev/null
+++ b/res/scan4.bmp
Binary files differ
diff --git a/res/toolbar_en.bmp b/res/toolbar_en.bmp
new file mode 100644
index 0000000..d90739e
--- /dev/null
+++ b/res/toolbar_en.bmp
Binary files differ
diff --git a/res/toolbar_fr.bmp b/res/toolbar_fr.bmp
new file mode 100644
index 0000000..e9a4706
--- /dev/null
+++ b/res/toolbar_fr.bmp
Binary files differ
diff --git a/resource.h b/resource.h
new file mode 100644
index 0000000..a540764
--- /dev/null
+++ b/resource.h
@@ -0,0 +1,99 @@
1//{{NO_DEPENDENCIES}}
2// Microsoft Developer Studio generated include file.
3// Used by SpaceMonger.rc
4//
5#define ID_SPACEMONGER 100
6#define IDD_DIALOG1 101
7#define IDD_ABOUT 102
8#define IDD_OPEN_DIALOG 104
9#define IDD_SCAN_DIALOG 105
10#define IDB_SCAN1 114
11#define IDB_SCAN2 115
12#define IDB_SCAN3 116
13#define IDB_SCAN4 117
14#define IDD_INFO_BAR 118
15#define IDD_SETTINGS 119
16#define IDB_BITMAP1 123
17#define IDR_TOOLBAR_EN 200
18#define IDR_TOOLBAR_FR 201
19#define IDC_DRIVE_LIST 1000
20#define IDC_PATH 1001
21#define IDC_FILES 1002
22#define IDC_FOLDERS 1003
23#define IDC_TOTAL 1005
24#define IDC_FREE 1006
25#define IDC_DENSITY 1006
26#define IDC_USED 1007
27#define IDC_ANIMATED 1007
28#define IDC_AUTO_RESCAN 1008
29#define IDC_FILE_COLOR 1009
30#define IDC_BIAS 1010
31#define IDC_FOLDER_COLOR 1011
32#define IDC_LOAD_PROGRESS 1011
33#define IDC_DISABLE_DELETE 1012
34#define IDC_SHOW_TIPS 1013
35#define IDC_SHOW_NAME_TIPS 1013
36#define IDC_TIP_PATH 1014
37#define IDC_NAMETIP_PATH 1014
38#define IDC_TIP_NAME 1015
39#define IDC_NAMETIP_NAME 1015
40#define IDC_TIP_DATE 1016
41#define IDC_INFOTIP_DATE 1016
42#define IDC_TIP_SIZE 1017
43#define IDC_INFOTIP_SIZE 1017
44#define IDC_TIP_ATTRIB 1018
45#define IDC_INFOTIP_ATTRIB 1018
46#define IDC_TIP_ICON 1019
47#define IDC_NAMETIP_ICON 1019
48#define IDC_SAVE_POS 1020
49#define IDC_TIP_DELAY 1021
50#define IDC_INFOTIP_DELAY 1021
51#define IDC_STATIC_TIP1 1022
52#define IDC_STATIC_INFOTIP1 1022
53#define IDC_STATIC_TIP2 1023
54#define IDC_STATIC_INFOTIP2 1023
55#define IDC_SHOW_INFO_TIPS 1024
56#define IDC_STATIC_FREEWARE 1024
57#define IDC_NAMETIP_DELAY 1025
58#define IDC_STATIC_WARRANTY 1025
59#define IDC_STATIC_NAMETIP1 1026
60#define IDC_STATIC_EMAIL 1026
61#define IDC_STATIC_NAMETIP2 1027
62#define IDC_STATIC_FILESFOUND 1027
63#define IDC_INFOTIP_PATH 1028
64#define IDC_STATIC_FOLDERSFOUND 1028
65#define IDC_INFOTIP_NAME 1029
66#define IDC_INFOTIP_ICON 1030
67#define IDC_STATIC_LAYOUT 1031
68#define IDC_STATIC_DISPLAYCOLORS 1032
69#define IDC_STATIC_FILES 1033
70#define IDC_STATIC_FOLDERS 1034
71#define IDC_STATIC_DENSITY 1035
72#define IDC_STATIC_BIAS 1036
73#define IDC_STATIC_HORZ 1037
74#define IDC_STATIC_EQUAL 1038
75#define IDC_STATIC_VERT 1039
76#define IDC_STATIC_TOOLTIPS 1040
77#define IDC_STATIC_MISCOPTIONS 1041
78#define IDC_LANG 1042
79#define IDC_SHOW_ROLLOVER_BOX 1043
80#define ID_FILE_REFRESH 40002
81#define ID_VIEW_FREE 40003
82#define ID_VIEW_ZOOM_IN 40004
83#define ID_VIEW_ZOOM_OUT 40005
84#define ID_VIEW_ZOOM_FULL 40006
85#define ID_FILE_RUN 40013
86#define ID_FILE_DELETE 40014
87#define ID_SETTINGS 40017
88#define ID_FILE_PROPERTIES 40018
89
90// Next default values for new objects
91//
92#ifdef APSTUDIO_INVOKED
93#ifndef APSTUDIO_READONLY_SYMBOLS
94#define _APS_NEXT_RESOURCE_VALUE 124
95#define _APS_NEXT_COMMAND_VALUE 40019
96#define _APS_NEXT_CONTROL_VALUE 1044
97#define _APS_NEXT_SYMED_VALUE 101
98#endif
99#endif
diff --git a/xapp.h b/xapp.h
new file mode 100644
index 0000000..7ba0e1a
--- /dev/null
+++ b/xapp.h
@@ -0,0 +1,248 @@
1
2#ifndef XAPP_H
3#define XAPP_H
4
5class CFreeDoc;
6class CFreeView;
7
8/******************************************************************************
9** Painting utility functions
10*/
11
12#define ColorWindowBack (GetSysColorBrush(COLOR_APPWORKSPACE))
13#define ColorText (GetSysColorBrush(COLOR_WINDOWTEXT))
14#define ColorTextBack (GetSysColorBrush(COLOR_WINDOW))
15#define ColorBright (GetSysColorBrush(COLOR_3DHIGHLIGHT))
16#define ColorFlat (GetSysColorBrush(COLOR_3DFACE))
17#define ColorDark (GetSysColorBrush(COLOR_3DSHADOW))
18#define ColorBorder (GetSysColorBrush(COLOR_3DDKSHADOW))
19#define ColorActive (GetSysColorBrush(COLOR_ACTIVECAPTION))
20#define ColorInactive (GetSysColorBrush(COLOR_INACTIVECAPTION))
21
22/*
23** DrawHLine
24** Draw a horizontal line in a given brush.
25*/
26
27inline static void DrawHLine(HDC dc, HBRUSH brush, int x, int y, int length)
28{
29 RECT rect;
30 rect.top = y, rect.bottom = y + 1;
31 rect.left = x, rect.right = x + length;
32 FillRect(dc, &rect, brush);
33}
34
35/*
36** DrawVLine
37** Draw a vertical line in a given brush.
38*/
39
40inline static void DrawVLine(HDC dc, HBRUSH brush, int x, int y, int length)
41{
42 RECT rect;
43 rect.top = y, rect.bottom = y + length;
44 rect.left = x, rect.right = x + 1;
45 FillRect(dc, &rect, brush);
46}
47
48/*
49** FillBox
50** Fill a rectangle in a given brush.
51*/
52
53inline static void FillBox(HDC dc, HBRUSH brush, int x, int y, int width, int height)
54{
55 RECT rect;
56 rect.top = y, rect.bottom = y + height;
57 rect.left = x, rect.right = x + width;
58 FillRect(dc, &rect, brush);
59}
60
61/*
62** DrawBox
63** Draw a rectangle in a given brush.
64*/
65
66inline static void DrawBox(HDC dc, HBRUSH brush, int x, int y, int width, int height)
67{
68 RECT rect;
69 rect.top = y, rect.bottom = y + height;
70 rect.left = x, rect.right = x + width;
71 FrameRect(dc, &rect, brush);
72}
73
74/*
75** DrawDualBox
76** Draw a two-color rectangle in a given pair of brushes.
77*/
78
79inline static void DrawDualBox(HDC dc, HBRUSH topleft, HBRUSH bottomright,
80 int x, int y, int width, int height)
81{
82 RECT rect;
83
84 rect.top = y, rect.bottom = y + 1;
85 rect.left = x, rect.right = x + width;
86 FillRect(dc, &rect, topleft);
87 rect.top = y + height - 1, rect.bottom = y + height;
88 FillRect(dc, &rect, bottomright);
89 rect.top = y, rect.bottom = y + height;
90 rect.left = x, rect.right = x + 1;
91 FillRect(dc, &rect, topleft);
92 rect.left = x + width - 1, rect.right = x + width;
93 FillRect(dc, &rect, bottomright);
94}
95
96/*
97** FillDualBox
98** Draw a two-color rectangle in a given pair of brushes, and fill
99** in the area it encloses with a third color.
100*/
101
102inline static void FillDualBox(HDC dc, HBRUSH topleft, HBRUSH bottomright,
103 HBRUSH fill, int x, int y, int width, int height)
104{
105 RECT rect;
106
107 rect.top = y, rect.bottom = y + 1;
108 rect.left = x, rect.right = x + width;
109 FillRect(dc, &rect, topleft);
110 rect.top = y + height - 1, rect.bottom = y + height;
111 FillRect(dc, &rect, bottomright);
112 rect.top = y, rect.bottom = y + height;
113 rect.left = x, rect.right = x + 1;
114 FillRect(dc, &rect, topleft);
115 rect.left = x + width - 1, rect.right = x + width;
116 FillRect(dc, &rect, bottomright);
117 rect.top = y + 1, rect.bottom = y + width - 2;
118 rect.left = x + 1, rect.right = x + width - 2;
119 FillRect(dc, &rect, fill);
120}
121
122/*
123** Macros to build some common UI objects
124*/
125
126#define DrawRaisedBox(dc, x, y, width, height) \
127 (DrawDualBox(dc, ColorBright, ColorDark, x, y, width, height))
128
129#define DrawLoweredBox(dc, x, y, width, height) \
130 (DrawDualBox(dc, ColorDark, ColorBright, x, y, width, height))
131
132#define DrawEditBox(dc, x, y, width, height) \
133 (DrawDualBox(dc, ColorDark, ColorBright, x, y, width, height), \
134 DrawDualBox(dc, ColorBorder, ColorFlat, (x)+1, (y)+1, (width)-2, (height)-2))
135
136#define DrawWindowBorder(dc, x, y, width, height) \
137 (DrawDualBox(dc, ColorFlat, ColorBorder, x, y, width, height), \
138 DrawDualBox(dc, ColorBright, ColorDark, (x)+1, (y)+1, (width)-2, (height)-2))
139
140#define FillWindowBorder(dc, x, y, width, height) \
141 (DrawDualBox(dc, ColorFlat, ColorBorder, x, y, width, height), \
142 FillDualBox(dc, ColorBright, ColorDark, ColorFlat, (x)+1, (y)+1, (width)-2, (height)-2))
143
144#define DrawButtonUp(dc, x, y, width, height) \
145 (DrawDualBox(dc, ColorBright, ColorBorder, x, y, width, height), \
146 DrawDualBox(dc, ColorFlat, ColorDark, (x)+1, (y)+1, (width)-2, (height)-2))
147
148#define DrawButtonDown(dc, x, y, width, height) \
149 (DrawDualBox(dc, ColorDark, ColorBorder, x, y, width, height), \
150 DrawBox(dc, ColorFlat, (x)+1, (y)+1, (width)-2, (height)-2))
151
152#define FillRaisedBox(dc, x, y, width, height) \
153 (FillDualBox(dc, ColorBright, ColorDark, ColorFlat, x, y, width, height))
154
155#define FillLoweredBox(dc, x, y, width, height) \
156 (FillDualBox(dc, ColorDark, ColorBright, ColorFlat, x, y, width, height))
157
158#define FillButtonUp(dc, x, y, width, height) \
159 (DrawDualBox(dc, ColorBright, ColorBorder, x, y, width, height), \
160 FillDualBox(dc, ColorFlat, ColorDark, ColorFlat, (x)+1, (y)+1, (width)-2, (height)-2))
161
162#define FillButtonDown(dc, x, y, width, height) \
163 (DrawDualBox(dc, ColorDark, ColorBorder, x, y, width, height), \
164 FillBox(dc, ColorFlat, (x)+1, (y)+1, (width)-2, (height)-2))
165
166
167/******************************************************************************
168** The "liberated document" class
169*/
170
171class CFreeDoc {
172public:
173 CFreeDoc();
174 virtual ~CFreeDoc();
175
176 virtual BOOL Create(void);
177
178 virtual const CString &GetTitle(void) const
179 { return(m_strTitle); }
180 virtual void SetTitle(const CString &string);
181 virtual const CString &GetPathName(void) const
182 { return(m_strPathName); }
183 virtual void SetPathName(const CString &string);
184
185 virtual BOOL IsModified(void) const;
186 virtual void SetModifiedFlag(const BOOL modified = TRUE);
187
188 virtual UINT GetViewCount(void) const;
189 virtual void AddView(CFreeView *view);
190 virtual void RemoveView(CFreeView *view);
191 virtual POSITION GetFirstViewPosition(void) const;
192 virtual CFreeView *GetNextView(POSITION &position) const;
193 virtual void UpdateAllViews(void);
194 virtual void UpdateView(CFreeView *view);
195
196protected:
197 virtual void OnChangedViewList(CFreeView *view, BOOL added);
198 virtual BOOL OnCreate(void);
199 virtual void OnDestroy(void);
200
201protected:
202 CString m_strTitle, m_strPathName;
203 BOOL m_bModified, m_bCreated;
204 CPtrList m_viewList;
205};
206
207
208/******************************************************************************
209** The "liberated document view" class
210*/
211
212#define AFX_FREEVIEW_ID 0xE888
213
214class CFreeView : public CWnd {
215 friend void CFreeDoc::AddView(CFreeView *view);
216 friend void CFreeDoc::RemoveView(CFreeView *view);
217
218protected:
219 DECLARE_DYNCREATE(CFreeView)
220 CFreeView();
221 virtual ~CFreeView();
222
223public:
224 virtual BOOL Create(CWnd *wnd, BOOL show = 1);
225 virtual void SetDocument(CFreeDoc *doc = NULL);
226 virtual CFreeDoc *GetDocument(void);
227
228 virtual void OnUpdate(CFreeDoc *doc);
229
230 //{{AFX_VIRTUAL(CFreeView)
231 protected:
232 virtual void OnDraw(CDC* pDC);
233 //}}AFX_VIRTUAL
234
235protected:
236 //{{AFX_MSG(CFreeView)
237 afx_msg void OnSize(UINT nType, int cx, int cy);
238 afx_msg void OnPaint();
239 //}}AFX_MSG
240
241protected:
242 DECLARE_MESSAGE_MAP()
243
244 int m_width, m_height; // Width and height of view
245 CFreeDoc *m_document; // Document
246};
247
248#endif