source: trunk/dll/dirsize.c@ 1105

Last change on this file since 1105 was 1105, checked in by Gregg Young, 17 years ago

Reworked FillInRecSizes cleaned up string formatting and now use pszDisplayName for the display names; It appears to have finally fixed the strlen trap.

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