source: trunk/dll/dirsize.c@ 1438

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

Improved drivebar changes; Added AddBackslashToPath() to remove repeatative code. replaced "
" with PCSZ variable; ANY_OBJ added the DosAlloc... (experimental)

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