source: trunk/dll/dirsize.c@ 1017

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

fortify updates for threads dble free fix

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