source: trunk/dll/dirsize.c@ 1113

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

Use pszDisplayName for display in dirsize.c change free code to free it; fix memory leak in dirsize. (Ticket 269)

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