source: trunk/dll/dirsize.c@ 1570

Last change on this file since 1570 was 1570, checked in by Gregg Young, 14 years ago

Added IdleIfNeeded to place load and free loops to idle priority when dealing with large numbers of items. Used SleepIfNeeded more places for a similar purpose.

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