source: trunk/dll/dirsize.c@ 1036

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

More fortify changes eliminated the leave scope wrapper except in mainwnd.c Wrapper only unlaods stuuff (archivers, commands, etc

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