source: trunk/dll/dirsize.c@ 985

Last change on this file since 985 was 985, checked in by Gregg Young, 17 years ago

Update sizes dialog (ticket 44); Make max command line length user settable (ticket 199); use xfree for free in most cases (ticket 212); initial code to check for valid ini file (ticket 102); Some additional refactoring and structure rework; Some documentation updates;

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.7 KB
Line 
1
2/***********************************************************************
3
4 $Id: dirsize.c 985 2008-03-01 01:37:14Z gyoung $
5
6 Directory sizes
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2001, 2007 Steven H. Levine
10
11 16 Oct 02 SHL Handle large partitions
12 12 Feb 03 SHL Use CBLIST_TO_EASIZE
13 21 Nov 03 SHL Avoid VAC \ after // bug (wierd)
14 21 Nov 03 SHL Correct minor typos
15 21 Nov 03 SHL Total drives >4GB better
16 24 May 05 SHL Rework for CNRITEM.szSubject
17 25 May 05 SHL Use ULONGLONG and CommaFmtULL
18 26 May 05 SHL More large file formatting updates
19 06 Jun 05 SHL Drop obsoletes
20 19 Jun 05 SHL More 64-bit math fixes
21 08 Aug 05 SHL Avoid Expand/Collapse hangs while working
22 17 Jul 06 SHL Use Runtime_Error
23 19 Oct 06 SHL Correct . and .. detect
24 18 Feb 07 GKY Add new drive type icons
25 22 Mar 07 GKY Use QWL_USER
26 23 Jul 07 SHL Sync with naming standards
27 03 Aug 07 GKY Enlarged and made setable everywhere Findbuf (speed file loading)
28 03 Aug 07 SHL DirSizeProc; correct sizing and positioning to be deterministic
29 06 Aug 07 GKY Reduce DosSleep times (ticket 148)
30 13 Aug 07 SHL ProcessDir: remove unneeded reallocs. Sanitize code
31 13 Aug 07 SHL Move #pragma alloc_text to end for OpenWatcom compat
32 26 Aug 07 GKY DosSleep(1) in loops changed to (0)
33 29 Feb 08 GKY Use xfree where appropriate
34 29 Feb 08 GKY Add presparams & update appearence of "Sizes" dialog
35
36***********************************************************************/
37
38#include <stdlib.h>
39#include <string.h>
40#include <ctype.h>
41#include <process.h> // _beginthread
42
43#define INCL_DOS
44#define INCL_DOSERRORS
45#define INCL_WIN
46#define INCL_GPI
47#define INCL_LONGLONG
48
49#include "fm3dlg.h"
50#include "fm3str.h"
51#include "dircnrs.h"
52#include "errutil.h" // Dos_Error...
53#include "strutil.h" // GetPString
54#include "fm3dll.h"
55
56typedef struct
57{
58 CHAR *pszFileName;
59 HWND hwndCnr;
60 CHAR *pchStopFlag;
61 DIRCNRDATA *pDCD;
62} DIRSIZE;
63
64typedef struct
65{
66 CHAR szDirName[CCHMAXPATH];
67 CHAR chStopFlag;
68 BOOL dying;
69 BOOL working;
70 HPOINTER hptr;
71} tState;
72
73static PSZ pszSrcFile = __FILE__;
74
75static SHORT APIENTRY SortSizeCnr(PMINIRECORDCORE p1,
76 PMINIRECORDCORE p2,
77 PVOID SortFlags)
78{
79 ULONGLONG size1;
80 ULONGLONG size2;
81
82 size1 = ((PCNRITEM) p1)->cbFile + ((PCNRITEM) p1)->easize;
83 size2 = ((PCNRITEM) p2)->cbFile + ((PCNRITEM) p2)->easize;
84 return (size1 < size2) ? 1 : (size1 == size2) ? 0 : -1;
85}
86
87static BOOL ProcessDir(HWND hwndCnr,
88 CHAR *pszFileName,
89 PCNRITEM pciParent,
90 CHAR *pchStopFlag,
91 BOOL top,
92 PULONGLONG pullTotalBytes)
93{
94 CHAR maskstr[CCHMAXPATH];
95 CHAR szBuf[CCHMAXPATH];
96 CHAR FileSystem[CCHMAXPATH];
97 CHAR *pEndMask;
98 register char *p;
99 register char *sp;
100 register char *pp;
101 ULONG ulFindCnt;
102 ULONGLONG ullCurDirBytes = 0;
103 ULONGLONG ullSubDirBytes = 0;
104 ULONGLONG ull;
105 HDIR hdir;
106 PFILEFINDBUF4L pffbArray;
107 APIRET rc;
108 RECORDINSERT ri;
109 PCNRITEM pci;
110 ULONG ulBufBytes;
111
112 *pullTotalBytes = 0; // In case we fail
113
114 CheckDrive(toupper(*pszFileName), FileSystem, NULL);
115 /*if (!stricmp(FileSystem, NTFS)) {
116 saymsg(MB_OK,
117 HWND_DESKTOP,
118 NullStr,
119 GetPString(IDS_NTFSDRIVERFAILSTEXT));
120 return FALSE;
121 } */
122 ulBufBytes = sizeof(FILEFINDBUF4L) * FilesToGet;
123 pffbArray = xmalloc(ulBufBytes, pszSrcFile, __LINE__);
124 if (!pffbArray)
125 return FALSE; // Error already reported
126
127 strcpy(maskstr, pszFileName);
128 if (maskstr[strlen(maskstr) - 1] != '\\')
129 strcat(maskstr, "\\");
130 pEndMask = &maskstr[strlen(maskstr)]; // Point after last backslash
131 strcat(maskstr, "*");
132
133 hdir = HDIR_CREATE;
134 ulFindCnt = 1;
135 // memset(pffbArray, 0, sizeof(FILEFINDBUF4L)); // 11 Aug 07 SHL bypass memset
136 DosError(FERR_DISABLEHARDERR);
137 // Check directory exists
138 rc = xDosFindFirst(pszFileName, &hdir,
139 FILE_NORMAL | FILE_READONLY | FILE_ARCHIVED |
140 FILE_SYSTEM | FILE_HIDDEN | MUST_HAVE_DIRECTORY,
141 pffbArray, ulBufBytes, &ulFindCnt, FIL_QUERYEASIZEL);
142
143 if (!rc)
144 DosFindClose(hdir);
145
146 /*
147 * the "|| strlen(pszFileName) < 4 below works around an OS/2 bug
148 * that prevents FAT root directories from being found when
149 * requesting EASIZE. sheesh.
150 */
151 if (((!rc || rc == ERROR_NO_MORE_FILES) && (pffbArray->attrFile & FILE_DIRECTORY)) ||
152 strlen(pszFileName) < 4) {
153 if (*pchStopFlag) {
154 xfree(pffbArray);
155 return FALSE;
156 }
157 pci = WinSendMsg(hwndCnr, CM_ALLOCRECORD, MPFROMLONG(EXTRA_RECORD_BYTES),
158 MPFROMLONG(1));
159 if (!pci) {
160 Win_Error(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__, "CM_ALLOCRECORD");
161 xfree(pffbArray);
162 return FALSE;
163 }
164 if (!rc) {
165 ullCurDirBytes = pffbArray->cbFile;
166 ullCurDirBytes += CBLIST_TO_EASIZE(pffbArray->cbList);
167 }
168 else
169 DosError(FERR_DISABLEHARDERR);
170 pci->rc.hptrIcon = hptrDir;
171 pci->attrFile = 0;
172 pci->pszDispAttr = NullStr;
173 pci->pszSubject = NullStr;
174 } // if got something
175 else {
176 // No match
177 xfree(pffbArray);
178 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
179 GetPString(IDS_CANTFINDDIRTEXT), pszFileName);
180 return FALSE;
181 }
182
183 if (strlen(pszFileName) < 4 || top)
184 pci->pszFileName = xstrdup(pszFileName, pszSrcFile, __LINE__);
185 else {
186 p = strrchr(pszFileName, '\\');
187 if (!p)
188 p = pszFileName;
189 else
190 p++; // After last backslash
191 // Handle quoted names
192 // fixme to understand this - why lose path prefix?
193 sp = strchr(pszFileName, ' ') != NULL ? "\"" : NullStr;
194 pp = szBuf;
195 if (*sp)
196 *pp++ = *sp; // Need quotes
197 strcpy(pp, p);
198 if (*sp)
199 strcat(pp, sp);
200 pci->pszFileName = xstrdup(szBuf, pszSrcFile, __LINE__);
201 }
202 // fixme to understand this - appears to be indirectly saving length, but why?
203 pci->pszDisplayName = pci->pszFileName + strlen(pci->pszFileName);
204 pci->pszLongName = pci->pszFileName; // fixme to be sure?
205 pci->rc.pszIcon = pci->pszFileName;
206 pci->rc.flRecordAttr |= CRA_RECORDREADONLY;
207 if (fForceUpper)
208 strupr(pci->pszFileName);
209 else if (fForceLower)
210 strlwr(pci->pszFileName);
211 pci->pszDisplayName = pci->pszFileName + strlen(pci->pszFileName);
212 memset(&ri, 0, sizeof(RECORDINSERT));
213 ri.cb = sizeof(RECORDINSERT);
214 ri.pRecordOrder = (PRECORDCORE) CMA_END;
215 ri.pRecordParent = (PRECORDCORE) pciParent;
216 ri.zOrder = (USHORT) CMA_TOP;
217 ri.cRecordsInsert = 1;
218 ri.fInvalidateRecord = TRUE;
219 if (!WinSendMsg(hwndCnr, CM_INSERTRECORD, MPFROMP(pci), MPFROMP(&ri))) {
220 xfree(pffbArray);
221 return FALSE;
222 }
223
224 // Find files and directories in this directory
225 hdir = HDIR_CREATE;
226 // 13 Aug 07 SHL fixme to know if need to support fRemoteBug here like objcnr.c?
227 ulFindCnt = FilesToGet;
228 rc = xDosFindFirst(maskstr, &hdir,
229 FILE_NORMAL | FILE_READONLY | FILE_ARCHIVED |
230 FILE_SYSTEM | FILE_HIDDEN | FILE_DIRECTORY,
231 pffbArray, ulBufBytes, &ulFindCnt, FIL_QUERYEASIZEL);
232 if (!rc) {
233 PFILEFINDBUF4L pffbFile;
234 ULONG x;
235
236 while (!rc) {
237
238 priority_normal();
239 pffbFile = pffbArray;
240 for (x = 0; x < ulFindCnt; x++) {
241 // Total size skipping . and ..
242 if ((~pffbFile->attrFile & FILE_DIRECTORY) ||
243 (pffbFile->achName[0] != '.' ||
244 (pffbFile->achName[1] &&
245 (pffbFile->achName[1] != '.' || pffbFile->achName[2])))) {
246 ullCurDirBytes += pffbFile->cbFile;
247 ullCurDirBytes += CBLIST_TO_EASIZE(pffbFile->cbList) & 0x3ff;
248
249 if (*pchStopFlag)
250 break;
251 if (~pffbFile->attrFile & FILE_DIRECTORY)
252 pci->attrFile++; // Bump file count
253 else {
254 // Recurse into subdir
255 strcpy(pEndMask, pffbFile->achName); // Append dirname to base dirname
256 ProcessDir(hwndCnr, maskstr, pci, pchStopFlag, FALSE, &ull);
257 ullSubDirBytes += ull;
258 }
259 }
260 if (!pffbFile->oNextEntryOffset)
261 break;
262 pffbFile = (PFILEFINDBUF4L)((PBYTE)pffbFile + pffbFile->oNextEntryOffset);
263
264 } // for matches
265 if (*pchStopFlag)
266 break;
267 DosSleep(0);
268 ulFindCnt = FilesToGet;
269 DosError(FERR_DISABLEHARDERR);
270 rc = xDosFindNext(hdir, pffbArray, ulBufBytes, &ulFindCnt, FIL_QUERYEASIZEL);
271 } // while more found
272
273 DosFindClose(hdir);
274 priority_normal();
275 } // if got files or directories
276
277 if (rc && rc != ERROR_NO_MORE_FILES) {
278 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
279 GetPString(IDS_CANTFINDDIRTEXT), pszFileName);
280 }
281
282 xfree(pffbArray);
283
284 pci->cbFile = ullCurDirBytes;
285 pci->easize = ullSubDirBytes; // hack cough
286 WinSendMsg(hwndCnr, CM_INVALIDATERECORD, MPFROMP(&pci),
287 MPFROM2SHORT(1, CMA_ERASE | CMA_TEXTCHANGED));
288
289 *pullTotalBytes = ullCurDirBytes + ullSubDirBytes;
290 return TRUE;
291}
292
293static VOID FillInRecSizes(HWND hwndCnr, PCNRITEM pciParent,
294 ULONGLONG ullTotalBytes, CHAR * pchStopFlag,
295 BOOL isroot)
296{
297 PCNRITEM pci = pciParent;
298 SHORT attrib = CMA_FIRSTCHILD;
299
300 if (pci) {
301
302 float fltPct = 0.0;
303 USHORT c;
304 CHAR szCurDir[80];
305 CHAR szSubDir[80];
306 CHAR szAllDir[80];
307 CHAR szBar[80];
308
309 // cbFile = currect directory usage in bytes
310 // easize = subdirectory usage in bytes
311 CommaFmtULL(szCurDir, sizeof(szCurDir), pci->cbFile, 'K');
312 *szBar = 0;
313
314 if (ullTotalBytes) {
315 register UINT cBar;
316
317 if (isroot) {
318 FSALLOCATE fsa;
319 APIRET rc;
320
321 memset(&fsa, 0, sizeof(fsa));
322 rc = DosQueryFSInfo(toupper(*pci->pszFileName) - '@', FSIL_ALLOC, &fsa,
323 sizeof(FSALLOCATE));
324 if (!rc) {
325 fltPct = (ullTotalBytes * 100.0) /
326 ((float)fsa.cUnit * (fsa.cSectorUnit * fsa.cbSector));
327 }
328 // Need unique buffer 23 Jul 07 SHL
329 pci->pszLongName = xmalloc(2, pszSrcFile, __LINE__);
330 pci->pszLongName[0] = 0; // Make null string
331 pci->pszLongName[1] = 1; // Flag root - hack cough
332 }
333 else
334 fltPct = (((float)pci->cbFile + pci->easize) * 100.0) / ullTotalBytes;
335
336 cBar = (UINT) fltPct / 2;
337 if (cBar)
338 memset(szBar, '#', cBar);
339 if (cBar * 2 != (UINT) fltPct) {
340 szBar[cBar] = '=';
341 cBar++;
342 }
343 if (cBar < 50)
344 memset(szBar + cBar, ' ', 50 - cBar);
345 szBar[50] = 0;
346 }
347
348 pci->flags = (ULONG) fltPct;
349 CommaFmtULL(szSubDir, sizeof(szSubDir), pci->easize, 'K');
350 CommaFmtULL(szAllDir, sizeof(szAllDir), pci->cbFile + pci->easize, 'K');
351 c = pci->pszDisplayName - pci->pszFileName;
352 pci->pszFileName = xrealloc(pci->pszFileName,
353 CCHMAXPATH,
354 pszSrcFile,
355 __LINE__); // 23 Jul 07 SHL
356 sprintf(pci->pszFileName + c,
357 " %s + %s = %s (%.02lf%%%s)\r%s",
358 szCurDir,
359 szSubDir,
360 szAllDir,
361 fltPct,
362 isroot ? GetPString(IDS_OFDRIVETEXT) : NullStr,
363 szBar);
364 pci->pszFileName = xrealloc(pci->pszFileName,
365 strlen(pci->pszFileName) + 1,
366 pszSrcFile,
367 __LINE__); // 23 Jul 07 SHL
368 pci->pszDisplayName = pci->pszFileName + c;
369 WinSendMsg(hwndCnr,
370 CM_INVALIDATERECORD, MPFROMP(&pci), MPFROM2SHORT(1, 0));
371 isroot = FALSE;
372 }
373 else
374 attrib = CMA_FIRST;
375 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
376 MPFROM2SHORT(attrib, CMA_ITEMORDER));
377 while (pci && (INT) pci != -1) {
378 if (*pchStopFlag)
379 break;
380 FillInRecSizes(hwndCnr, pci, ullTotalBytes, pchStopFlag, isroot);
381 isroot = FALSE;
382 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
383 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
384 }
385}
386
387static VOID PrintToFile(HWND hwndCnr, ULONG indent, PCNRITEM pciParent,
388 FILE * fp)
389{
390 PCNRITEM pci;
391 CHAR *p;
392
393 if (!pciParent) {
394 pciParent = WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(NULL),
395 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
396 indent = 0;
397 }
398 if (pciParent) {
399 p = strchr(pciParent->pszFileName, '\r');
400 if (p)
401 *p = 0;
402 fprintf(fp, "%*.*s%s %lu %s%s\n",
403 indent * 2, indent * 2, " ",
404 pciParent->pszFileName,
405 pciParent->attrFile,
406 GetPString(IDS_FILETEXT), &"s"[pciParent->attrFile == 1]);
407 if (p)
408 *p = '\r';
409 if (pciParent->rc.flRecordAttr & CRA_EXPANDED) {
410 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pciParent),
411 MPFROM2SHORT(CMA_FIRSTCHILD,
412 CMA_ITEMORDER));
413 while (pci && (INT) pci != -1) {
414 DosSleep(0); //26 Aug 07 GKY 1
415 PrintToFile(hwndCnr, indent + 1, pci, fp);
416 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
417 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
418 } //while
419 }
420 }
421}
422
423static VOID FillCnrThread(VOID *args)
424{
425 HAB hab;
426 HMQ hmq;
427 DIRSIZE *dirsize = (DIRSIZE *)args;
428 HWND hwndCnr;
429 ULONGLONG ull;
430
431 if (!dirsize) {
432 Runtime_Error(pszSrcFile, __LINE__, "no data");
433 return;
434 }
435
436 hwndCnr = dirsize->hwndCnr;
437
438 DosError(FERR_DISABLEHARDERR);
439
440 // priority_normal();
441 hab = WinInitialize(0);
442 if (hab) {
443 hmq = WinCreateMsgQueue(hab, 0);
444 if (hmq) {
445 WinCancelShutdown(hmq, TRUE);
446 ProcessDir(hwndCnr, dirsize->pszFileName,
447 (PCNRITEM) NULL, dirsize->pchStopFlag, TRUE, &ull);
448 DosPostEventSem(CompactSem);
449 WinEnableWindowUpdate(hwndCnr, FALSE);
450 FillInRecSizes(hwndCnr, NULL, ull, dirsize->pchStopFlag, TRUE);
451 WinEnableWindowUpdate(hwndCnr, TRUE);
452 WinSendMsg(hwndCnr, CM_INVALIDATERECORD, MPVOID,
453 MPFROM2SHORT(0, CMA_ERASE | CMA_TEXTCHANGED));
454 WinDestroyMsgQueue(hmq);
455 }
456 WinTerminate(hab);
457 }
458 PostMsg(WinQueryWindow(hwndCnr, QW_PARENT),
459 UM_CONTAINER_FILLED, MPVOID, MPVOID);
460 xfree(dirsize);
461}
462
463MRESULT EXPENTRY DirSizeProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
464{
465 tState *pState;
466 PCNRITEM pci;
467 CHAR szBytes[44];
468 CHAR sz[66];
469
470 switch (msg) {
471 case WM_INITDLG:
472 if (!mp2) {
473 WinDismissDlg(hwnd, 0);
474 break;
475 }
476 pState = xmallocz(sizeof(tState), pszSrcFile, __LINE__);
477 if (!pState) {
478 WinDismissDlg(hwnd, 0);
479 break;
480 }
481 strcpy(pState->szDirName, (CHAR *) mp2);
482 WinSetWindowPtr(hwnd, QWL_USER, (PVOID) pState);
483 pState->hptr = WinLoadPointer(HWND_DESKTOP, FM3ModHandle, DIRSIZE_ICON);
484 WinDefDlgProc(hwnd, WM_SETICON, MPFROMLONG(pState->hptr), MPVOID);
485 {
486 CHAR s[CCHMAXPATH + 81];
487 RestorePresParams(hwnd, "DirSizes");
488 sprintf(s, GetPString(IDS_DIRSIZETITLETEXT), pState->szDirName);
489 WinSetWindowText(hwnd, s);
490 }
491 {
492 SWP swp;
493 ULONG size = sizeof(SWP);
494
495 PrfQueryProfileData(fmprof, FM3Str, "DirSizes.Position", (PVOID) &swp, &size);
496 WinSetWindowPos(hwnd,
497 HWND_TOP,
498 swp.x,
499 swp.y,
500 swp.cx,
501 swp.cy,
502 swp.fl);
503 }
504 {
505 DIRSIZE *dirsize;
506
507 dirsize = xmalloc(sizeof(DIRSIZE), pszSrcFile, __LINE__);
508 if (!dirsize) {
509 WinDismissDlg(hwnd, 0);
510 break;
511 }
512 dirsize->pchStopFlag = (CHAR *)&pState->chStopFlag;
513 dirsize->pszFileName = pState->szDirName;
514 dirsize->hwndCnr = WinWindowFromID(hwnd, DSZ_CNR);
515 if (_beginthread(FillCnrThread, NULL, 122880L * 5, (PVOID)dirsize) ==
516 -1) {
517 Runtime_Error(pszSrcFile, __LINE__,
518 GetPString(IDS_COULDNTSTARTTHREADTEXT));
519 xfree(dirsize);
520 WinDismissDlg(hwnd, 0);
521 break;
522 }
523 pState->working = TRUE;
524 WinEnableWindow(WinWindowFromID(hwnd, DSZ_COLLAPSE), FALSE);
525 WinEnableWindow(WinWindowFromID(hwnd, DSZ_EXPAND), FALSE);
526 WinEnableWindow(WinWindowFromID(hwnd, DSZ_PRINT), FALSE);
527 }
528 PostMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
529 break;
530
531 case UM_SETUP:
532 {
533 CNRINFO cnri;
534 FSALLOCATE fsa;
535 APIRET rc;
536
537 memset(&cnri, 0, sizeof(CNRINFO));
538 cnri.cb = sizeof(CNRINFO);
539 WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_QUERYCNRINFO,
540 MPFROMP(&cnri), MPFROMLONG(sizeof(CNRINFO)));
541 cnri.cyLineSpacing = 0;
542 cnri.cxTreeIndent = 12;
543 cnri.flWindowAttr = CV_TREE | CV_FLOW | CA_TREELINE | CA_OWNERDRAW;
544 WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_SETCNRINFO, MPFROMP(&cnri),
545 MPFROMLONG(CMA_FLWINDOWATTR | CMA_TREEICON |
546 CMA_LINESPACING | CMA_CXTREEINDENT));
547 pState = INSTDATA(hwnd);
548 if (pState && isalpha(*pState->szDirName)) {
549 memset(&fsa, 0, sizeof(fsa));
550 rc =
551 DosQueryFSInfo(toupper(*pState->szDirName) - '@', FSIL_ALLOC, &fsa,
552 sizeof(FSALLOCATE));
553 if (!rc) {
554
555 CHAR s[132], tf[80], tb[80], tu[80];
556
557 CommaFmtULL(tf, sizeof(tf),
558 (ULONGLONG) fsa.cUnitAvail *
559 (fsa.cSectorUnit * fsa.cbSector), 'M');
560 CommaFmtULL(tb, sizeof(tb),
561 (ULONGLONG) fsa.cUnit *
562 (fsa.cSectorUnit * fsa.cbSector), 'M');
563 CommaFmtULL(tu, sizeof(tu),
564 (ULONGLONG) (fsa.cUnit - fsa.cUnitAvail) *
565 (fsa.cSectorUnit * fsa.cbSector), 'M');
566 sprintf(s, GetPString(IDS_FREESPACETEXT), tf, tb, tu);
567 WinSetDlgItemText(hwnd, DSZ_FREESPACE, s);
568 }
569 else
570 WinSetDlgItemText(hwnd,
571 DSZ_FREESPACE, GetPString(IDS_FREESPACEUTEXT));
572 }
573 }
574 return 0;
575
576 case UM_CONTAINER_FILLED:
577 pState = INSTDATA(hwnd);
578 if (!pState || pState->dying) {
579 if (pState)
580 pState->working = FALSE;
581 WinDismissDlg(hwnd, 0);
582 return 0;
583 }
584 pState->working = FALSE;
585 WinEnableWindow(WinWindowFromID(hwnd, DSZ_COLLAPSE), TRUE);
586 WinEnableWindow(WinWindowFromID(hwnd, DSZ_EXPAND), TRUE);
587 WinEnableWindow(WinWindowFromID(hwnd, DSZ_PRINT), TRUE);
588
589 pci = WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_QUERYRECORD, MPVOID,
590 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
591 if (pci && (INT) pci != -1)
592 WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_EXPANDTREE, MPFROMP(pci), MPVOID);
593 *sz = 0;
594 pci = WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_QUERYRECORDEMPHASIS,
595 MPFROMLONG(CMA_FIRST), MPFROMSHORT(CRA_CURSORED));
596 if (pci && (INT) pci != -1) {
597 commafmt(szBytes, sizeof(szBytes), pci->attrFile);
598 sprintf(sz,
599 "%s %s%s",
600 szBytes, GetPString(IDS_FILETEXT), &"s"[pci->attrFile == 1]);
601 }
602 WinSetDlgItemText(hwnd, DSZ_NUMFILES, sz);
603
604 WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_SORTRECORD, MPFROMP(SortSizeCnr),
605 MPVOID);
606 DosBeep(500, 25); // Wake up user
607 return 0;
608
609 case WM_ADJUSTWINDOWPOS:
610 PostMsg(hwnd, UM_STRETCH, MPVOID, MPVOID);
611 break;
612
613 case UM_STRETCH:
614 {
615 SWP swpC, swp;
616
617 WinQueryWindowPos(hwnd, &swp);
618 if (!(swp.fl & (SWP_HIDE | SWP_MINIMIZE))) {
619 WinQueryWindowPos(WinWindowFromID(hwnd, DSZ_CNR), &swpC);
620 WinSetWindowPos(WinWindowFromID(hwnd, DSZ_CNR), HWND_TOP,
621 SysVal(SV_CXSIZEBORDER),
622 swpC.y,
623 swp.cx - (SysVal(SV_CXSIZEBORDER) * 2),
624 (swp.cy - swpC.y) - (SysVal(SV_CYTITLEBAR) +
625 SysVal(SV_CYSIZEBORDER)),
626 SWP_MOVE | SWP_SIZE);
627 }
628 }
629 return 0;
630
631 case WM_PRESPARAMCHANGED:
632 PresParamChanged(hwnd, "DirSizes", mp1, mp2);
633 break;
634
635 case WM_DRAWITEM:
636 if (mp2) {
637
638 OWNERITEM *oi = mp2;
639 CNRDRAWITEMINFO *cnd;
640 PCNRITEM pci;
641
642 if (oi->idItem == CMA_TEXT) {
643
644 cnd = (CNRDRAWITEMINFO *)oi->hItem;
645
646 if (cnd) {
647 pci = (PCNRITEM)cnd->pRecord;
648
649 if (pci) {
650 POINTL aptl[TXTBOX_COUNT];
651 POINTL ptl;
652 PSZ p;
653 LONG clr;
654 LONG x;
655 LONG yBottom;
656 INT boxHeight;
657 p = strchr(pci->pszFileName, '\r');
658 if (p) {
659 // draw text
660 if (*(pci->pszLongName + 1) == 1) // is root record
661 GpiSetColor(oi->hps, CLR_DARKRED);
662 else if (!pci->cbFile) // no size
663 GpiSetColor(oi->hps, CLR_DARKGRAY);
664 else if (!pci->easize) // no size below
665 GpiSetColor(oi->hps, CLR_DARKBLUE);
666 else
667 GpiSetColor(oi->hps, CLR_BLACK);
668 GpiSetBackMix(oi->hps, BM_LEAVEALONE);
669 GpiSetMix(oi->hps, FM_OVERPAINT);
670
671 *p = 0; // Make 1 line high
672
673 // Calculate nominal graph box height based on font size
674 GpiQueryTextBox(oi->hps, strlen(pci->pszFileName),
675 pci->pszFileName, TXTBOX_COUNT, aptl);
676 boxHeight = aptl[TXTBOX_TOPRIGHT].y - aptl[TXTBOX_BOTTOMRIGHT].y;
677 boxHeight -= 4;
678
679 // Calculate nominal baseline of graph box
680 // rclItem.yBottom is at center of icon because it is
681 yBottom = oi->rclItem.yBottom - boxHeight + 3;
682
683 // Place text above graph box with a bit of whitespace between
684 ptl.x = oi->rclItem.xLeft;
685 ptl.y = yBottom + boxHeight + 6; // 03 Aug 07 SHL
686 // GpiMove(oi->hps, &ptl);
687 GpiCharStringAt(oi->hps, &ptl, strlen(pci->pszFileName),
688 pci->pszFileName);
689
690 *p = '\r'; // Restore
691
692 // draw the graph box
693 // GpiQueryTextBox(oi->hps, 1, "#", TXTBOX_COUNT, aptl); // 03 Aug 07 SHL
694 // draw black outline
695 GpiSetColor(oi->hps, CLR_BLACK);
696 ptl.x = oi->rclItem.xLeft;
697 ptl.y = yBottom + 2;
698 GpiMove(oi->hps, &ptl);
699 ptl.x = oi->rclItem.xLeft + 201;
700 ptl.y = yBottom + boxHeight;
701 GpiBox(oi->hps, DRO_OUTLINE, &ptl, 0, 0);
702 // fill with gray
703 GpiSetColor(oi->hps, CLR_PALEGRAY);
704 ptl.x = oi->rclItem.xLeft + 1;
705 ptl.y = yBottom + 3;
706 GpiMove(oi->hps, &ptl);
707 ptl.x = oi->rclItem.xLeft + 200;
708 ptl.y = yBottom + boxHeight - 1;
709 GpiBox(oi->hps, DRO_OUTLINEFILL, &ptl, 0, 0);
710
711 // draw shadow at bottom & right sides
712 GpiSetColor(oi->hps, CLR_DARKGRAY);
713 ptl.x = oi->rclItem.xLeft + 1;
714 ptl.y = yBottom + 3;
715 GpiMove(oi->hps, &ptl);
716 ptl.x = oi->rclItem.xLeft + 200;
717 GpiLine(oi->hps, &ptl);
718 ptl.y = yBottom + boxHeight - 1;
719 GpiLine(oi->hps, &ptl);
720
721 // draw highlight at top and left sides
722 GpiSetColor(oi->hps, CLR_WHITE);
723 ptl.x = oi->rclItem.xLeft + 1;
724 GpiLine(oi->hps, &ptl);
725 ptl.y = yBottom + 3;
726 GpiLine(oi->hps, &ptl);
727
728 // draw shadow of box
729 GpiSetColor(oi->hps, CLR_DARKGRAY);
730 ptl.x = oi->rclItem.xLeft + 2;
731 ptl.y = yBottom + boxHeight;
732 GpiMove(oi->hps, &ptl);
733 ptl.x = oi->rclItem.xLeft + 203;
734 GpiLine(oi->hps, &ptl);
735 ptl.y = yBottom + boxHeight - 2;
736 GpiLine(oi->hps, &ptl);
737 ptl.x--;
738 GpiMove(oi->hps, &ptl);
739 ptl.y = yBottom + 1;
740 GpiLine(oi->hps, &ptl);
741 ptl.x = oi->rclItem.xLeft + 2;
742 GpiLine(oi->hps, &ptl);
743
744 // fill box with graph bar, flags is integer %
745 if (pci->flags) {
746 if (*(pci->pszLongName + 1) == 1) // is root record
747 GpiSetColor(oi->hps, CLR_DARKGREEN);
748 else
749 GpiSetColor(oi->hps, CLR_RED);
750 ptl.x = oi->rclItem.xLeft + 2;
751 ptl.y = yBottom + 3;
752 GpiMove(oi->hps, &ptl);
753 ptl.x = oi->rclItem.xLeft + pci->flags * 2;
754 ptl.y = yBottom + boxHeight - 1;
755 GpiBox(oi->hps, DRO_OUTLINEFILL, &ptl, 0, 0);
756
757 // draw highlights and shadows on graph
758 if (*(pci->pszLongName + 1) == 1)
759 GpiSetColor(oi->hps, CLR_GREEN);
760 else
761 GpiSetColor(oi->hps, CLR_PALEGRAY);
762 if (pci->flags > 5) {
763 ptl.x = oi->rclItem.xLeft + 1;
764 ptl.y = yBottom + 3;
765 GpiMove(oi->hps, &ptl);
766 ptl.y = yBottom + boxHeight - 1;
767 GpiLine(oi->hps, &ptl);
768 }
769 else {
770 ptl.y = yBottom + boxHeight - 1;
771 GpiMove(oi->hps, &ptl);
772 }
773 ptl.x = oi->rclItem.xLeft + pci->flags * 2;
774 GpiLine(oi->hps, &ptl);
775 if (*(pci->pszLongName + 1) != 1) {
776 GpiSetColor(oi->hps, CLR_DARKRED);
777 ptl.x = oi->rclItem.xLeft + 2;
778 ptl.y = yBottom + 3;
779 GpiMove(oi->hps, &ptl);
780 ptl.x = oi->rclItem.xLeft + pci->flags * 2;
781 GpiLine(oi->hps, &ptl);
782 }
783 }
784
785 // draw hash marks in box
786 GpiSetColor(oi->hps, CLR_WHITE);
787 clr = CLR_WHITE;
788 for (x = 1; x < 20; x++) {
789 if (clr == CLR_WHITE && x * 10 > pci->flags * 2) {
790 clr = CLR_BLACK;
791 GpiSetColor(oi->hps, CLR_BLACK);
792 }
793 ptl.x = oi->rclItem.xLeft + 1 + x * 10;
794 ptl.y = yBottom + boxHeight - 1;
795 GpiMove(oi->hps, &ptl);
796 switch (x) {
797 case 1:
798 case 3:
799 case 5:
800 case 7:
801 case 9:
802 case 11:
803 case 13:
804 case 15:
805 case 17:
806 case 19:
807 ptl.y -= 1;
808 break;
809 case 10:
810 ptl.y -= 4;
811 break;
812 case 2:
813 case 4:
814 case 6:
815 case 8:
816 case 12:
817 case 14:
818 case 16:
819 case 18:
820 ptl.y -= 2;
821 break;
822 }
823 GpiLine(oi->hps, &ptl);
824 } // for x
825 return MRFROMLONG(TRUE);
826 }
827 }
828 }
829 }
830 }
831 return FALSE; // Let PM draw
832
833 case WM_CONTROL:
834 switch (SHORT2FROMMP(mp1)) {
835 case CN_ENTER:
836 if (mp2) {
837 PCNRITEM pci = (PCNRITEM)((PNOTIFYRECORDENTER)mp2)->pRecord;
838 CHAR szFileName[CCHMAXPATH]; // 23 Jul 07 SHL
839 CHAR szTemp[CCHMAXPATH];
840
841 if (pci) {
842 *szFileName = 0;
843 while (pci && (INT) pci != -1) {
844 memset(szTemp, 0, sizeof(szTemp));
845 strncpy(szTemp, pci->pszFileName,
846 pci->pszDisplayName - pci->pszFileName);
847 strrev(szTemp);
848 if (*szFileName && *szTemp != '\\')
849 strcat(szFileName, "\\");
850 strcat(szFileName, szTemp);
851 pci = WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_QUERYRECORD,
852 MPFROMP(pci),
853 MPFROM2SHORT(CMA_PARENT, CMA_ITEMORDER));
854 }
855 strrev(szFileName);
856 if (!fVTreeOpensWPS)
857 OpenDirCnr((HWND)0,
858 hwndMain ? hwndMain : HWND_DESKTOP,
859 hwnd,
860 FALSE,
861 szFileName);
862 else {
863
864 ULONG size = sizeof(ULONG);
865 ULONG flWindowAttr = CV_ICON;
866 CHAR s[33];
867
868 strcpy(s, "ICON");
869 PrfQueryProfileData(fmprof, appname, "DirflWindowAttr",
870 (PVOID) & flWindowAttr, &size);
871 if (flWindowAttr & CV_DETAIL) {
872 if (IsRoot(szFileName))
873 strcpy(s, "TREE");
874 else
875 strcpy(s, "DETAILS");
876 }
877 OpenObject(szFileName, s, hwnd);
878 }
879 }
880 }
881 break;
882 case CN_EMPHASIS:
883 pState = INSTDATA(hwnd);
884 if (pState && !pState->working && mp2) {
885
886 PNOTIFYRECORDEMPHASIS pre = mp2;
887
888 pci = (PCNRITEM) ((pre) ? pre->pRecord : NULL);
889 if (pci && (pre->fEmphasisMask & CRA_SELECTED) &&
890 (pci->rc.flRecordAttr & CRA_SELECTED)) {
891 commafmt(szBytes, sizeof(szBytes), pci->attrFile);
892 sprintf(sz,
893 "%s %s%s",
894 szBytes,
895 GetPString(IDS_FILETEXT), &"s"[pci->attrFile == 1]);
896 WinSetDlgItemText(hwnd, DSZ_NUMFILES, sz);
897 }
898 }
899 break;
900 }
901 return 0;
902
903 case WM_COMMAND:
904 switch (SHORT1FROMMP(mp1)) {
905 case IDM_HELP:
906 if (hwndHelp)
907 WinSendMsg(hwndHelp, HM_DISPLAY_HELP,
908 MPFROM2SHORT(HELP_DIRSIZE, 0), MPFROMSHORT(HM_RESOURCEID));
909 break;
910
911 case DSZ_PRINT:
912 // Save button
913 pState = INSTDATA(hwnd);
914 if (!pState)
915 Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
916 else {
917
918 CHAR szFileName[CCHMAXPATH];
919 FILE *fp;
920
921 save_dir2(szFileName);
922 sprintf(&szFileName[strlen(szFileName)], "\\%csizes.Rpt",
923 (pState) ? toupper(*pState->szDirName) : '+');
924 if (export_filename(hwnd, szFileName, FALSE) && *szFileName) {
925 if (stricmp(szFileName, "PRN") &&
926 strnicmp(szFileName, "\\DEV\\LPT", 8) &&
927 !strchr(szFileName, '.'))
928 strcat(szFileName, ".RPT");
929 fp = fopen(szFileName, "a+");
930 if (!fp) {
931 saymsg(MB_CANCEL,
932 hwnd,
933 GetPString(IDS_ERRORTEXT),
934 GetPString(IDS_COMPCANTOPENTEXT), szFileName);
935 }
936 else {
937 WinSetPointer(HWND_DESKTOP, hptrBusy);
938 PrintToFile(WinWindowFromID(hwnd, DSZ_CNR), 0, NULL, fp);
939 fclose(fp);
940 WinSetPointer(HWND_DESKTOP, hptrArrow);
941 }
942 }
943 }
944 break;
945
946 case DSZ_EXPAND:
947 case DSZ_COLLAPSE:
948 pState = INSTDATA(hwnd);
949 if (pState) {
950 pci = (PCNRITEM) WinSendDlgItemMsg(hwnd, DSZ_CNR,
951 CM_QUERYRECORDEMPHASIS,
952 MPFROMLONG(CMA_FIRST),
953 MPFROMSHORT(CRA_CURSORED));
954 if (pci) {
955 WinEnableWindow(WinWindowFromID(hwnd, DID_OK), FALSE);
956 WinEnableWindow(WinWindowFromID(hwnd, IDM_HELP), FALSE);
957 WinEnableWindow(WinWindowFromID(hwnd, DSZ_COLLAPSE), FALSE);
958 WinEnableWindow(WinWindowFromID(hwnd, DSZ_EXPAND), FALSE);
959 WinEnableWindow(WinWindowFromID(hwnd, DSZ_PRINT), FALSE);
960 WinEnableWindow(WinWindowFromID(hwnd, DID_CANCEL), FALSE);
961 // fixme to use thread - too slow on large trees
962 ExpandAll(WinWindowFromID(hwnd, DSZ_CNR),
963 (SHORT1FROMMP(mp1) == DSZ_EXPAND), pci);
964 WinEnableWindow(WinWindowFromID(hwnd, DID_OK), TRUE);
965 WinEnableWindow(WinWindowFromID(hwnd, IDM_HELP), TRUE);
966 WinEnableWindow(WinWindowFromID(hwnd, DSZ_COLLAPSE), TRUE);
967 WinEnableWindow(WinWindowFromID(hwnd, DSZ_EXPAND), TRUE);
968 WinEnableWindow(WinWindowFromID(hwnd, DSZ_PRINT), TRUE);
969 WinEnableWindow(WinWindowFromID(hwnd, DID_CANCEL), TRUE);
970 }
971 }
972 break;
973
974 case DID_OK:
975 case DID_CANCEL:
976 {
977 SWP swp;
978 ULONG size = sizeof(SWP);
979
980 WinQueryWindowPos(hwnd, &swp);
981 PrfWriteProfileData(fmprof, FM3Str, "DirSizes.Position", (PVOID) &swp,
982 size);
983 }
984 pState = INSTDATA(hwnd);
985 if (!pState)
986 Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
987 else {
988 if (pState->working) {
989 pState->dying = TRUE;
990 pState->chStopFlag = (BYTE)0xff;
991 DosBeep(1000, 100); // Complain?
992 }
993 else
994 WinDismissDlg(hwnd, 0);
995 }
996 break;
997 } // switch mp1
998 return 0;
999
1000 case WM_CLOSE:
1001 pState = INSTDATA(hwnd);
1002 if (pState)
1003 pState->chStopFlag = (BYTE)0xff;
1004 DosSleep(1);
1005 break;
1006
1007 case WM_DESTROY:
1008 pState = INSTDATA(hwnd);
1009 if (pState) {
1010 pState->chStopFlag = (BYTE)0xff;
1011 if (pState->hptr)
1012 WinDestroyPointer(pState->hptr);
1013 DosSleep(16); //05 Aug 07 GKY 33
1014 xfree(pState); // Let's hope no one is still looking
1015 }
1016 DosPostEventSem(CompactSem);
1017 break;
1018 }
1019 return WinDefDlgProc(hwnd, msg, mp1, mp2);
1020}
1021
1022#pragma alloc_text(DIRSIZE,ProcessDir,FillCnrThread,DirSizeProc)
1023#pragma alloc_text(DIRSIZE2,PrintToFile,FillInRecSizes,SortSizeCnr)
1024
Note: See TracBrowser for help on using the repository browser.