source: trunk/dll/dirsize.c@ 1114

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

Comments for CS 1113

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