source: trunk/dll/dirsize.c@ 1533

Last change on this file since 1533 was 1533, checked in by Gregg Young, 15 years ago

Fixed possible loss of precision compiler warnings by casting the variables in question.

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