source: trunk/dll/dirsize.c@ 1206

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

Ticket 187: Move datadevlarations/definitions out of fm3dll.h

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