source: trunk/dll/dirsize.c@ 1347

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

More code cleanup

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