source: trunk/dll/dirsize.c@ 1156

Last change on this file since 1156 was 1156, checked in by John Small, 17 years ago

Ticket 187: Draft 1: Functions only

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