source: trunk/dll/dirsize.c@ 1482

Last change on this file since 1482 was 1482, checked in by Gregg Young, 16 years ago

Fixed separate parameters; added the ability to set it either globally or for just one app; some files only contain white space changes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 30.5 KB
Line 
1
2/***********************************************************************
3
4 $Id: dirsize.c 1482 2009-12-13 19:59:47Z gyoung $
5
6 Directory sizes
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2001, 2009 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
54***********************************************************************/
55
56#include <stdlib.h>
57#include <string.h>
58#include <ctype.h>
59// #include <process.h> // _beginthread
60
61#define INCL_DOS
62#define INCL_DOSERRORS
63#define INCL_WIN
64#define INCL_GPI
65#define INCL_LONGLONG
66
67#include "fm3dll.h"
68#include "fm3dll2.h" // #define's for UM_*, control id's, etc.
69#include "draglist.h" // Data declaration(s)
70#include "init.h" // Data declaration(s)
71#include "notebook.h" // Data declaration(s)
72#include "mainwnd.h" // Data declaration(s)
73#include "newview.h" // Data declarations
74#include "fm3dlg.h"
75#include "fm3str.h"
76#include "dircnrs.h"
77#include "errutil.h" // Dos_Error...
78#include "strutil.h" // GetPString
79#include "filldir.h" // EmptyCnr...
80#include "dirsize.h"
81#include "select.h" // ExpandAll
82#include "valid.h" // CheckDrive
83#include "common.h" // OpenDirCnr
84#include "shadow.h" // OpenObject
85#include "presparm.h" // PresParamChanged
86#include "i18nutil.h" // commafmt
87#include "getnames.h" // export_filename
88#include "wrappers.h" // xDosFindNext
89#include "dirs.h" // save_dir2
90#include "misc.h" // PostMsg
91#include "fortify.h"
92#include "excputil.h" // xbeginthread
93#include "pathutil.h" // AddBackslashToPath
94
95typedef struct
96{
97 CHAR *pszFileName;
98 HWND hwndCnr;
99 CHAR *pchStopFlag;
100 DIRCNRDATA *pDCD;
101} DIRSIZE;
102
103typedef struct
104{
105 CHAR szDirName[CCHMAXPATH];
106 CHAR chStopFlag;
107 BOOL dying;
108 BOOL working;
109 HPOINTER hptr;
110} tState;
111
112static PSZ pszSrcFile = __FILE__;
113
114static SHORT APIENTRY SortSizeCnr(PMINIRECORDCORE p1,
115 PMINIRECORDCORE p2,
116 PVOID SortFlags)
117{
118 ULONGLONG size1;
119 ULONGLONG size2;
120
121 size1 = ((PCNRITEM) p1)->cbFile + ((PCNRITEM) p1)->easize;
122 size2 = ((PCNRITEM) p2)->cbFile + ((PCNRITEM) p2)->easize;
123 return (size1 < size2) ? 1 : (size1 == size2) ? 0 : -1;
124}
125
126static BOOL ProcessDir(HWND hwndCnr,
127 CHAR *pszFileName,
128 PCNRITEM pciParent,
129 CHAR *pchStopFlag,
130 BOOL top,
131 PULONGLONG pullTotalBytes)
132{
133 CHAR maskstr[CCHMAXPATH];
134 CHAR szBuf[CCHMAXPATH];
135 CHAR FileSystem[CCHMAXPATH];
136 CHAR *pEndMask;
137 register char *p;
138 register char *sp;
139 register char *pp;
140 ULONG ulFindCnt;
141 ULONGLONG ullCurDirBytes = 0;
142 ULONGLONG ullSubDirBytes = 0;
143 ULONGLONG ull;
144 HDIR hdir;
145 PFILEFINDBUF4L pffbArray;
146 APIRET rc;
147 RECORDINSERT ri;
148 PCNRITEM pci;
149 ULONG ulBufBytes;
150
151 *pullTotalBytes = 0; // In case we fail
152
153 CheckDrive(toupper(*pszFileName), FileSystem, NULL);
154 ulBufBytes = sizeof(FILEFINDBUF4L) * FilesToGet;
155 pffbArray = xmalloc(ulBufBytes, pszSrcFile, __LINE__);
156 if (!pffbArray)
157 return FALSE; // Error already reported
158
159 strcpy(maskstr, pszFileName);
160 AddBackslashToPath(maskstr);
161 //if (maskstr[strlen(maskstr) - 1] != '\\')
162 // strcat(maskstr, "\\");
163 pEndMask = &maskstr[strlen(maskstr)]; // Point after last backslash
164 strcat(maskstr, "*");
165
166 hdir = HDIR_CREATE;
167 ulFindCnt = 1;
168 DosError(FERR_DISABLEHARDERR);
169 // Check directory exists
170 rc = xDosFindFirst(pszFileName, &hdir,
171 FILE_NORMAL | FILE_READONLY | FILE_ARCHIVED |
172 FILE_SYSTEM | FILE_HIDDEN | MUST_HAVE_DIRECTORY,
173 pffbArray, ulBufBytes, &ulFindCnt, FIL_QUERYEASIZEL);
174
175 if (!rc)
176 DosFindClose(hdir);
177
178 /*
179 * the "|| strlen(pszFileName) < 4 below works around an OS/2 bug
180 * that prevents FAT root directories from being found when
181 * requesting EASIZE. sheesh.
182 */
183 if (((!rc || rc == ERROR_NO_MORE_FILES) && (pffbArray->attrFile & FILE_DIRECTORY)) ||
184 strlen(pszFileName) < 4) {
185 if (*pchStopFlag) {
186 free(pffbArray);
187 return FALSE;
188 }
189 pci = WinSendMsg(hwndCnr, CM_ALLOCRECORD, MPFROMLONG(EXTRA_RECORD_BYTES),
190 MPFROMLONG(1));
191 if (!pci) {
192 Win_Error(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__, PCSZ_CM_ALLOCRECORD);
193 xfree(pffbArray, pszSrcFile, __LINE__);
194 return FALSE;
195 }
196 if (!rc) {
197 ullCurDirBytes = pffbArray->cbFile;
198 ullCurDirBytes += CBLIST_TO_EASIZE(pffbArray->cbList);
199 }
200 else
201 DosError(FERR_DISABLEHARDERR);
202 pci->rc.hptrIcon = hptrDir;
203 pci->attrFile = 0;
204 pci->pszDispAttr = NULL;
205 pci->pszSubject = NULL;
206 } // if got something
207 else {
208 // No match
209 xfree(pffbArray, pszSrcFile, __LINE__);
210 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
211 GetPString(IDS_CANTFINDDIRTEXT), pszFileName);
212 return FALSE;
213 }
214
215 if (strlen(pszFileName) < 4 || top)
216 pci->pszFileName = xstrdup(pszFileName, pszSrcFile, __LINE__);
217 else {
218 p = strrchr(pszFileName, '\\');
219 if (!p)
220 p = pszFileName;
221 else
222 p++; // After last backslash
223 // Handle quoted names
224 // fixme to understand this - why lose path prefix?
225 sp = strchr(pszFileName, ' ') != NULL ? "\"" : NullStr;
226 pp = szBuf;
227 if (*sp)
228 *pp++ = *sp; // Need quotes
229 strcpy(pp, p);
230 if (*sp)
231 strcat(pp, sp);
232 pci->pszFileName = xstrdup(szBuf, pszSrcFile, __LINE__);
233 }
234 // Use pszDisplayname for display so no need to save length of pszFileName 03 Aug 08 GKY
235 pci->pszDisplayName = pci->pszFileName;
236 pci->rc.pszIcon = pci->pszFileName;
237 pci->rc.flRecordAttr |= CRA_RECORDREADONLY;
238 if (fForceUpper)
239 strupr(pci->pszFileName);
240 else if (fForceLower)
241 strlwr(pci->pszFileName);
242 memset(&ri, 0, sizeof(RECORDINSERT));
243 ri.cb = sizeof(RECORDINSERT);
244 ri.pRecordOrder = (PRECORDCORE) CMA_END;
245 ri.pRecordParent = (PRECORDCORE) pciParent;
246 ri.zOrder = (USHORT) CMA_TOP;
247 ri.cRecordsInsert = 1;
248 ri.fInvalidateRecord = TRUE;
249 if (!WinSendMsg(hwndCnr, CM_INSERTRECORD, MPFROMP(pci), MPFROMP(&ri))) {
250 xfree(pffbArray, pszSrcFile, __LINE__);
251 return FALSE;
252 }
253
254 // Find files and directories in this directory
255 hdir = HDIR_CREATE;
256 // 13 Aug 07 SHL fixme to know if need to support fRemoteBug here like objcnr.c?
257 ulFindCnt = FilesToGet;
258 rc = xDosFindFirst(maskstr, &hdir,
259 FILE_NORMAL | FILE_READONLY | FILE_ARCHIVED |
260 FILE_SYSTEM | FILE_HIDDEN | FILE_DIRECTORY,
261 pffbArray, ulBufBytes, &ulFindCnt, FIL_QUERYEASIZEL);
262 if (!rc) {
263 PFILEFINDBUF4L pffbFile;
264 ULONG x;
265
266 while (!rc) {
267
268 priority_normal();
269 pffbFile = pffbArray;
270 for (x = 0; x < ulFindCnt; x++) {
271 // Total size skipping . and ..
272 if ((~pffbFile->attrFile & FILE_DIRECTORY) ||
273 (pffbFile->achName[0] != '.' ||
274 (pffbFile->achName[1] &&
275 (pffbFile->achName[1] != '.' || pffbFile->achName[2])))) {
276 ullCurDirBytes += pffbFile->cbFile;
277 ullCurDirBytes += CBLIST_TO_EASIZE(pffbFile->cbList) & 0x3ff;
278
279 if (*pchStopFlag)
280 break;
281 if (~pffbFile->attrFile & FILE_DIRECTORY)
282 pci->attrFile++; // Bump file count
283 else {
284 // Recurse into subdir
285 strcpy(pEndMask, pffbFile->achName); // Append dirname to base dirname
286 ProcessDir(hwndCnr, maskstr, pci, pchStopFlag, FALSE, &ull);
287 ullSubDirBytes += ull;
288 }
289 }
290 if (!pffbFile->oNextEntryOffset)
291 break;
292 pffbFile = (PFILEFINDBUF4L)((PBYTE)pffbFile + pffbFile->oNextEntryOffset);
293
294 } // for matches
295 if (*pchStopFlag)
296 break;
297 DosSleep(0);
298 ulFindCnt = FilesToGet;
299 DosError(FERR_DISABLEHARDERR);
300 rc = xDosFindNext(hdir, pffbArray, ulBufBytes, &ulFindCnt, FIL_QUERYEASIZEL);
301 } // while more found
302
303 DosFindClose(hdir);
304 priority_normal();
305 } // if got files or directories
306
307 if (rc && rc != ERROR_NO_MORE_FILES) {
308 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
309 GetPString(IDS_CANTFINDDIRTEXT), pszFileName);
310 }
311
312 xfree(pffbArray, pszSrcFile, __LINE__);
313
314 pci->cbFile = ullCurDirBytes;
315 pci->easize = ullSubDirBytes; // hack cough
316 WinSendMsg(hwndCnr, CM_INVALIDATERECORD, MPFROMP(&pci),
317 MPFROM2SHORT(1, CMA_ERASE | CMA_TEXTCHANGED));
318
319 *pullTotalBytes = ullCurDirBytes + ullSubDirBytes;
320 return TRUE;
321}
322
323static VOID FillInRecSizes(HWND hwndCnr, PCNRITEM pciParent,
324 ULONGLONG ullTotalBytes, CHAR * pchStopFlag,
325 BOOL isroot)
326{
327 PCNRITEM pci = pciParent;
328 SHORT attrib = CMA_FIRSTCHILD;
329
330 if (pci) {
331
332 float fltPct = 0.0;
333 CHAR szCurDir[80];
334 CHAR szSubDir[80];
335 CHAR szAllDir[80];
336 CHAR szBar[101];
337 CHAR szBuf[CCHMAXPATH + 341];
338
339 // cbFile = currect directory usage in bytes
340 // easize = subdirectory usage in bytes
341 CommaFmtULL(szCurDir, sizeof(szCurDir), pci->cbFile, 'K');
342 *szBar = 0;
343 pci->pszLongName = NULL;
344 memset(szBuf, 0, sizeof(szBuf));
345 if (ullTotalBytes) {
346 UINT cBar;
347
348 if (isroot) {
349 FSALLOCATE fsa;
350 APIRET rc;
351
352
353 memset(&fsa, 0, sizeof(fsa));
354 rc = DosQueryFSInfo(toupper(*pci->pszFileName) - '@', FSIL_ALLOC, &fsa,
355 sizeof(FSALLOCATE));
356 if (!rc) {
357 fltPct = (ullTotalBytes * 100.0) /
358 ((float)fsa.cUnit * (fsa.cSectorUnit * fsa.cbSector));
359 }
360 // Need unique buffer 23 Jul 07 SHL
361 pci->pszLongName = NullStr;
362 }
363 else
364 fltPct = (((float)pci->cbFile + pci->easize) * 100.0) / ullTotalBytes;
365
366 //Second line for graph reworked 03 AUG 08 GKY
367 memset(szBar, ' ', sizeof(szBar));
368 cBar = (UINT) fltPct / 2;
369 if (cBar && cBar * 2 != (UINT) fltPct)
370 szBar[cBar] = '=';
371 szBar[100] = 0;
372 }
373
374 pci->flags = (ULONG) fltPct;
375 CommaFmtULL(szSubDir, sizeof(szSubDir), pci->easize, 'K');
376 CommaFmtULL(szAllDir, sizeof(szAllDir), pci->cbFile + pci->easize, 'K');
377 sprintf(szBuf,
378 "%s %s + %s = %s (%.02lf%%%s)\r%s",
379 pci->pszFileName,
380 szCurDir,
381 szSubDir,
382 szAllDir,
383 fltPct,
384 isroot ? GetPString(IDS_OFDRIVETEXT) : NullStr,
385 szBar);
386 pci->pszDisplayName = xstrdup(szBuf, pszSrcFile, __LINE__);
387 // use DisplayName for display hopefully fixes "strlen" trap 02 AUG 08 GKY
388 if (pci->pszDisplayName) {
389# ifdef FORTIFY
390 Fortify_ChangeScope(pci->pszDisplayName, -1);
391 Fortify_ChangeScope(pci->pszFileName, -1);
392# endif
393 WinSendMsg(hwndCnr, CM_INVALIDATERECORD, MPFROMP(&pci), MPFROM2SHORT(1, 0));
394 }
395 isroot = FALSE;
396 }
397 else
398 attrib = CMA_FIRST;
399 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
400 MPFROM2SHORT(attrib, CMA_ITEMORDER));
401 while (pci && (INT) pci != -1) {
402 if (*pchStopFlag)
403 break;
404 FillInRecSizes(hwndCnr, pci, ullTotalBytes, pchStopFlag, isroot);
405 isroot = FALSE;
406 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
407 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
408 }
409}
410
411static VOID PrintToFile(HWND hwndCnr, ULONG indent, PCNRITEM pciParent,
412 FILE * fp)
413{
414 PCNRITEM pci;
415 CHAR *p;
416
417 if (!pciParent) {
418 pciParent = WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(NULL),
419 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
420 indent = 0;
421 }
422 if (pciParent) {
423 p = strchr(pciParent->pszDisplayName, '\r'); // GKY use display name for display
424 if (p)
425 *p = 0;
426 fprintf(fp, "%*.*s%s %lu %s%s\n",
427 indent * 2, indent * 2, " ",
428 pciParent->pszDisplayName, //
429 pciParent->attrFile,
430 GetPString(IDS_FILETEXT), &"s"[pciParent->attrFile == 1]);
431 if (p)
432 *p = '\r';
433 if (pciParent->rc.flRecordAttr & CRA_EXPANDED) {
434 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pciParent),
435 MPFROM2SHORT(CMA_FIRSTCHILD,
436 CMA_ITEMORDER));
437 while (pci && (INT) pci != -1) {
438 DosSleep(0); //26 Aug 07 GKY 1
439 PrintToFile(hwndCnr, indent + 1, pci, fp);
440 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
441 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
442 } //while
443 }
444 }
445}
446
447static VOID FillCnrThread(VOID *args)
448{
449 HAB hab;
450 HMQ hmq;
451 DIRSIZE *dirsize = (DIRSIZE *)args;
452 HWND hwndCnr;
453 ULONGLONG ull;
454
455 if (!dirsize) {
456 Runtime_Error(pszSrcFile, __LINE__, NULL);
457 return;
458 }
459# ifdef FORTIFY
460 Fortify_EnterScope();
461 Fortify_BecomeOwner(dirsize); // We free dirsize
462# endif
463
464 hwndCnr = dirsize->hwndCnr;
465
466 DosError(FERR_DISABLEHARDERR);
467
468 // priority_normal();
469 hab = WinInitialize(0);
470 if (hab) {
471 hmq = WinCreateMsgQueue(hab, 0);
472 if (hmq) {
473 WinCancelShutdown(hmq, TRUE);
474 ProcessDir(hwndCnr, dirsize->pszFileName,
475 (PCNRITEM) NULL, dirsize->pchStopFlag, TRUE, &ull);
476 DosPostEventSem(CompactSem);
477 WinEnableWindowUpdate(hwndCnr, FALSE);
478 FillInRecSizes(hwndCnr, NULL, ull, dirsize->pchStopFlag, TRUE);
479 WinEnableWindowUpdate(hwndCnr, TRUE);
480 WinSendMsg(hwndCnr, CM_INVALIDATERECORD, MPVOID,
481 MPFROM2SHORT(0, CMA_ERASE | CMA_TEXTCHANGED));
482 WinDestroyMsgQueue(hmq);
483 }
484 WinTerminate(hab);
485 }
486
487 xfree(dirsize, pszSrcFile, __LINE__);
488 PostMsg(WinQueryWindow(hwndCnr, QW_PARENT),
489 UM_CONTAINER_FILLED, MPVOID, MPVOID);
490# ifdef FORTIFY
491 Fortify_LeaveScope();
492# endif
493}
494
495MRESULT EXPENTRY DirSizeProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
496{
497 tState *pState;
498 PCNRITEM pci;
499 CHAR szBytes[44];
500 CHAR sz[66];
501
502 switch (msg) {
503 case WM_INITDLG:
504 if (!mp2) {
505 WinDismissDlg(hwnd, 0);
506 break;
507 }
508# ifdef FORTIFY
509 Fortify_EnterScope();
510# endif
511 pState = xmallocz(sizeof(tState), pszSrcFile, __LINE__);
512 if (!pState) {
513 WinDismissDlg(hwnd, 0);
514 break;
515 }
516 strcpy(pState->szDirName, (CHAR *)mp2);
517 WinSetWindowPtr(hwnd, QWL_USER, (PVOID) pState);
518 pState->hptr = WinLoadPointer(HWND_DESKTOP, FM3ModHandle, DIRSIZE_ICON);
519 WinDefDlgProc(hwnd, WM_SETICON, MPFROMLONG(pState->hptr), MPVOID);
520 {
521 CHAR s[CCHMAXPATH + 81];
522 RestorePresParams(hwnd, PCSZ_DIRSIZES);
523 sprintf(s, GetPString(IDS_DIRSIZETITLETEXT), pState->szDirName);
524 WinSetWindowText(hwnd, s);
525 }
526 {
527 SWP swp;
528 ULONG size = sizeof(SWP);
529
530 PrfQueryProfileData(fmprof, FM3Str, "DirSizes.Position", (PVOID) &swp, &size);
531 swp.fl &= ~SWP_SIZE; // 04 Feb 09 SHL ignore saved size
532 WinSetWindowPos(hwnd,
533 HWND_TOP,
534 swp.x,
535 swp.y,
536 swp.cx,
537 swp.cy,
538 swp.fl);
539 }
540 {
541 DIRSIZE *dirsize;
542
543 dirsize = xmalloc(sizeof(DIRSIZE), pszSrcFile, __LINE__);
544 if (!dirsize) {
545 WinDismissDlg(hwnd, 0);
546 break;
547 }
548 dirsize->pchStopFlag = (CHAR *)&pState->chStopFlag;
549 dirsize->pszFileName = pState->szDirName;
550 dirsize->hwndCnr = WinWindowFromID(hwnd, DSZ_CNR);
551 if (xbeginthread(FillCnrThread,
552 122880 * 5,
553 dirsize,
554 pszSrcFile,
555 __LINE__) == -1)
556 {
557 xfree(dirsize, pszSrcFile, __LINE__);
558 WinDismissDlg(hwnd, 0);
559 break;
560 }
561 pState->working = TRUE;
562 WinEnableWindow(WinWindowFromID(hwnd, DSZ_COLLAPSE), FALSE);
563 WinEnableWindow(WinWindowFromID(hwnd, DSZ_EXPAND), FALSE);
564 WinEnableWindow(WinWindowFromID(hwnd, DSZ_PRINT), FALSE);
565 }
566 PostMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
567 break;
568
569 case UM_SETUP:
570 {
571 CNRINFO cnri;
572 FSALLOCATE fsa;
573 APIRET rc;
574
575 memset(&cnri, 0, sizeof(CNRINFO));
576 cnri.cb = sizeof(CNRINFO);
577 WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_QUERYCNRINFO,
578 MPFROMP(&cnri), MPFROMLONG(sizeof(CNRINFO)));
579 cnri.cyLineSpacing = 0;
580 cnri.cxTreeIndent = 12;
581 cnri.flWindowAttr = CV_TREE | CV_FLOW | CA_TREELINE | CA_OWNERDRAW;
582 WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_SETCNRINFO, MPFROMP(&cnri),
583 MPFROMLONG(CMA_FLWINDOWATTR | CMA_TREEICON |
584 CMA_LINESPACING | CMA_CXTREEINDENT));
585 pState = INSTDATA(hwnd);
586 if (pState && isalpha(*pState->szDirName)) {
587 memset(&fsa, 0, sizeof(fsa));
588 rc =
589 DosQueryFSInfo(toupper(*pState->szDirName) - '@', FSIL_ALLOC, &fsa,
590 sizeof(FSALLOCATE));
591 if (!rc) {
592
593 CHAR s[132], tf[80], tb[80], tu[80];
594
595 CommaFmtULL(tf, sizeof(tf),
596 (ULONGLONG) fsa.cUnitAvail *
597 (fsa.cSectorUnit * fsa.cbSector), 'M');
598 CommaFmtULL(tb, sizeof(tb),
599 (ULONGLONG) fsa.cUnit *
600 (fsa.cSectorUnit * fsa.cbSector), 'M');
601 CommaFmtULL(tu, sizeof(tu),
602 (ULONGLONG) (fsa.cUnit - fsa.cUnitAvail) *
603 (fsa.cSectorUnit * fsa.cbSector), 'M');
604 sprintf(s, GetPString(IDS_FREESPACETEXT), tf, tb, tu);
605 WinSetDlgItemText(hwnd, DSZ_FREESPACE, s);
606 }
607 else
608 WinSetDlgItemText(hwnd,
609 DSZ_FREESPACE, 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,
1022 size);
1023 }
1024 pState = INSTDATA(hwnd);
1025 if (!pState)
1026 Runtime_Error(pszSrcFile, __LINE__, NULL);
1027 else {
1028 if (pState->working) {
1029 pState->dying = TRUE;
1030 pState->chStopFlag = (CHAR)0xff;
1031 if (!fAlertBeepOff)
1032 DosBeep(1000, 100); // Complain?
1033 }
1034 else
1035 WinDismissDlg(hwnd, 0);
1036 }
1037 break;
1038 } // switch mp1
1039 return 0;
1040
1041 case WM_CLOSE:
1042 pState = INSTDATA(hwnd);
1043 if (pState)
1044 pState->chStopFlag = (CHAR)0xff;
1045 DosSleep(1);
1046 break;
1047
1048 case WM_DESTROY:
1049 pState = INSTDATA(hwnd);
1050 EmptyCnr(hwnd);
1051 if (pState) {
1052 pState->chStopFlag = (CHAR)0xff;
1053 if (pState->hptr)
1054 WinDestroyPointer(pState->hptr);
1055 DosSleep(16); //05 Aug 07 GKY 33
1056 xfree(pState, pszSrcFile, __LINE__); // Let's hope no one is still looking
1057# ifdef FORTIFY
1058 Fortify_LeaveScope();
1059# endif
1060 }
1061 DosPostEventSem(CompactSem);
1062 break;
1063 }
1064 return WinDefDlgProc(hwnd, msg, mp1, mp2);
1065}
1066
1067#pragma alloc_text(DIRSIZE,ProcessDir,FillCnrThread,DirSizeProc)
1068#pragma alloc_text(DIRSIZE2,PrintToFile,FillInRecSizes,SortSizeCnr)
1069
Note: See TracBrowser for help on using the repository browser.