source: trunk/dll/dirsize.c@ 1048

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

Fix for trap related to pci->pszLongName flag

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 29.2 KB
Line 
1
2/***********************************************************************
3
4 $Id: dirsize.c 1048 2008-07-07 04:01:04Z 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 free(pffbArray);
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(3, pszSrcFile, __LINE__);
332 if (pci->pszLongName) {
333 pci->pszLongName[0] = 0; // Make null string
334 pci->pszLongName[1] = 1; // Flag root - hack cough
335 pci->pszLongName[2] = 0; // terminate anyway
336 }
337 }
338 else
339 fltPct = (((float)pci->cbFile + pci->easize) * 100.0) / ullTotalBytes;
340
341 cBar = (UINT) fltPct / 2;
342 if (cBar)
343 memset(szBar, '#', cBar);
344 if (cBar * 2 != (UINT) fltPct) {
345 szBar[cBar] = '=';
346 cBar++;
347 }
348 if (cBar < 50)
349 memset(szBar + cBar, ' ', 50 - cBar);
350 szBar[50] = 0;
351 }
352
353 pci->flags = (ULONG) fltPct;
354 CommaFmtULL(szSubDir, sizeof(szSubDir), pci->easize, 'K');
355 CommaFmtULL(szAllDir, sizeof(szAllDir), pci->cbFile + pci->easize, 'K');
356 c = pci->pszDisplayName - pci->pszFileName;
357 pci->pszFileName = xrealloc(pci->pszFileName,
358 CCHMAXPATH,
359 pszSrcFile,
360 __LINE__); // 23 Jul 07 SHL
361 sprintf(pci->pszFileName + c,
362 " %s + %s = %s (%.02lf%%%s)\r%s",
363 szCurDir,
364 szSubDir,
365 szAllDir,
366 fltPct,
367 isroot ? GetPString(IDS_OFDRIVETEXT) : NullStr,
368 szBar);
369 pci->pszFileName = xrealloc(pci->pszFileName,
370 strlen(pci->pszFileName) + 1,
371 pszSrcFile,
372 __LINE__); // 23 Jul 07 SHL
373 pci->pszDisplayName = pci->pszFileName + c;
374 WinSendMsg(hwndCnr,
375 CM_INVALIDATERECORD, MPFROMP(&pci), MPFROM2SHORT(1, 0));
376 isroot = FALSE;
377 }
378 else
379 attrib = CMA_FIRST;
380 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
381 MPFROM2SHORT(attrib, CMA_ITEMORDER));
382 while (pci && (INT) pci != -1) {
383 if (*pchStopFlag)
384 break;
385 FillInRecSizes(hwndCnr, pci, ullTotalBytes, pchStopFlag, isroot);
386 isroot = FALSE;
387 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
388 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
389 }
390}
391
392static VOID PrintToFile(HWND hwndCnr, ULONG indent, PCNRITEM pciParent,
393 FILE * fp)
394{
395 PCNRITEM pci;
396 CHAR *p;
397
398 if (!pciParent) {
399 pciParent = WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(NULL),
400 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
401 indent = 0;
402 }
403 if (pciParent) {
404 p = strchr(pciParent->pszFileName, '\r');
405 if (p)
406 *p = 0;
407 fprintf(fp, "%*.*s%s %lu %s%s\n",
408 indent * 2, indent * 2, " ",
409 pciParent->pszFileName,
410 pciParent->attrFile,
411 GetPString(IDS_FILETEXT), &"s"[pciParent->attrFile == 1]);
412 if (p)
413 *p = '\r';
414 if (pciParent->rc.flRecordAttr & CRA_EXPANDED) {
415 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pciParent),
416 MPFROM2SHORT(CMA_FIRSTCHILD,
417 CMA_ITEMORDER));
418 while (pci && (INT) pci != -1) {
419 DosSleep(0); //26 Aug 07 GKY 1
420 PrintToFile(hwndCnr, indent + 1, pci, fp);
421 pci = (PCNRITEM) WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
422 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
423 } //while
424 }
425 }
426}
427
428static VOID FillCnrThread(VOID *args)
429{
430 HAB hab;
431 HMQ hmq;
432 DIRSIZE *dirsize = (DIRSIZE *)args;
433 HWND hwndCnr;
434 ULONGLONG ull;
435
436 if (!dirsize) {
437 Runtime_Error(pszSrcFile, __LINE__, "no data");
438 return;
439 }
440# ifdef FORTIFY
441 Fortify_EnterScope();
442# endif
443
444 hwndCnr = dirsize->hwndCnr;
445
446 DosError(FERR_DISABLEHARDERR);
447
448 // priority_normal();
449 hab = WinInitialize(0);
450 if (hab) {
451 hmq = WinCreateMsgQueue(hab, 0);
452 if (hmq) {
453 WinCancelShutdown(hmq, TRUE);
454 ProcessDir(hwndCnr, dirsize->pszFileName,
455 (PCNRITEM) NULL, dirsize->pchStopFlag, TRUE, &ull);
456 DosPostEventSem(CompactSem);
457 WinEnableWindowUpdate(hwndCnr, FALSE);
458 FillInRecSizes(hwndCnr, NULL, ull, dirsize->pchStopFlag, TRUE);
459 WinEnableWindowUpdate(hwndCnr, TRUE);
460 WinSendMsg(hwndCnr, CM_INVALIDATERECORD, MPVOID,
461 MPFROM2SHORT(0, CMA_ERASE | CMA_TEXTCHANGED));
462 WinDestroyMsgQueue(hmq);
463 }
464 WinTerminate(hab);
465 }
466
467 xfree(dirsize, pszSrcFile, __LINE__);
468 PostMsg(WinQueryWindow(hwndCnr, QW_PARENT),
469 UM_CONTAINER_FILLED, MPVOID, MPVOID);
470# ifdef FORTIFY
471 Fortify_LeaveScope();
472# endif
473}
474
475MRESULT EXPENTRY DirSizeProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
476{
477 tState *pState;
478 PCNRITEM pci;
479 CHAR szBytes[44];
480 CHAR sz[66];
481
482 switch (msg) {
483 case WM_INITDLG:
484 if (!mp2) {
485 WinDismissDlg(hwnd, 0);
486 break;
487 }
488# ifdef FORTIFY
489 Fortify_EnterScope();
490# endif
491 pState = xmallocz(sizeof(tState), pszSrcFile, __LINE__);
492 if (!pState) {
493 WinDismissDlg(hwnd, 0);
494 break;
495 }
496 strcpy(pState->szDirName, (CHAR *)mp2);
497 WinSetWindowPtr(hwnd, QWL_USER, (PVOID) pState);
498 pState->hptr = WinLoadPointer(HWND_DESKTOP, FM3ModHandle, DIRSIZE_ICON);
499 WinDefDlgProc(hwnd, WM_SETICON, MPFROMLONG(pState->hptr), MPVOID);
500 {
501 CHAR s[CCHMAXPATH + 81];
502 RestorePresParams(hwnd, "DirSizes");
503 sprintf(s, GetPString(IDS_DIRSIZETITLETEXT), pState->szDirName);
504 WinSetWindowText(hwnd, s);
505 }
506 {
507 SWP swp;
508 ULONG size = sizeof(SWP);
509
510 PrfQueryProfileData(fmprof, FM3Str, "DirSizes.Position", (PVOID) &swp, &size);
511 WinSetWindowPos(hwnd,
512 HWND_TOP,
513 swp.x,
514 swp.y,
515 swp.cx,
516 swp.cy,
517 swp.fl);
518 }
519 {
520 DIRSIZE *dirsize;
521
522 dirsize = xmalloc(sizeof(DIRSIZE), pszSrcFile, __LINE__);
523 if (!dirsize) {
524 WinDismissDlg(hwnd, 0);
525 break;
526 }
527 dirsize->pchStopFlag = (CHAR *)&pState->chStopFlag;
528 dirsize->pszFileName = pState->szDirName;
529 dirsize->hwndCnr = WinWindowFromID(hwnd, DSZ_CNR);
530 if (_beginthread(FillCnrThread, NULL, 122880L * 5, (PVOID)dirsize) ==
531 -1) {
532 Runtime_Error(pszSrcFile, __LINE__,
533 GetPString(IDS_COULDNTSTARTTHREADTEXT));
534 xfree(dirsize, pszSrcFile, __LINE__);
535 WinDismissDlg(hwnd, 0);
536 break;
537 }
538 pState->working = TRUE;
539 WinEnableWindow(WinWindowFromID(hwnd, DSZ_COLLAPSE), FALSE);
540 WinEnableWindow(WinWindowFromID(hwnd, DSZ_EXPAND), FALSE);
541 WinEnableWindow(WinWindowFromID(hwnd, DSZ_PRINT), FALSE);
542 }
543 PostMsg(hwnd, UM_SETUP, MPVOID, MPVOID);
544 break;
545
546 case UM_SETUP:
547 {
548 CNRINFO cnri;
549 FSALLOCATE fsa;
550 APIRET rc;
551
552 memset(&cnri, 0, sizeof(CNRINFO));
553 cnri.cb = sizeof(CNRINFO);
554 WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_QUERYCNRINFO,
555 MPFROMP(&cnri), MPFROMLONG(sizeof(CNRINFO)));
556 cnri.cyLineSpacing = 0;
557 cnri.cxTreeIndent = 12;
558 cnri.flWindowAttr = CV_TREE | CV_FLOW | CA_TREELINE | CA_OWNERDRAW;
559 WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_SETCNRINFO, MPFROMP(&cnri),
560 MPFROMLONG(CMA_FLWINDOWATTR | CMA_TREEICON |
561 CMA_LINESPACING | CMA_CXTREEINDENT));
562 pState = INSTDATA(hwnd);
563 if (pState && isalpha(*pState->szDirName)) {
564 memset(&fsa, 0, sizeof(fsa));
565 rc =
566 DosQueryFSInfo(toupper(*pState->szDirName) - '@', FSIL_ALLOC, &fsa,
567 sizeof(FSALLOCATE));
568 if (!rc) {
569
570 CHAR s[132], tf[80], tb[80], tu[80];
571
572 CommaFmtULL(tf, sizeof(tf),
573 (ULONGLONG) fsa.cUnitAvail *
574 (fsa.cSectorUnit * fsa.cbSector), 'M');
575 CommaFmtULL(tb, sizeof(tb),
576 (ULONGLONG) fsa.cUnit *
577 (fsa.cSectorUnit * fsa.cbSector), 'M');
578 CommaFmtULL(tu, sizeof(tu),
579 (ULONGLONG) (fsa.cUnit - fsa.cUnitAvail) *
580 (fsa.cSectorUnit * fsa.cbSector), 'M');
581 sprintf(s, GetPString(IDS_FREESPACETEXT), tf, tb, tu);
582 WinSetDlgItemText(hwnd, DSZ_FREESPACE, s);
583 }
584 else
585 WinSetDlgItemText(hwnd,
586 DSZ_FREESPACE, GetPString(IDS_FREESPACEUTEXT));
587 }
588 }
589 return 0;
590
591 case UM_CONTAINER_FILLED:
592 pState = INSTDATA(hwnd);
593 if (!pState || pState->dying) {
594 if (pState)
595 pState->working = FALSE;
596 WinDismissDlg(hwnd, 0);
597 return 0;
598 }
599 pState->working = FALSE;
600 WinEnableWindow(WinWindowFromID(hwnd, DSZ_COLLAPSE), TRUE);
601 WinEnableWindow(WinWindowFromID(hwnd, DSZ_EXPAND), TRUE);
602 WinEnableWindow(WinWindowFromID(hwnd, DSZ_PRINT), TRUE);
603
604 pci = WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_QUERYRECORD, MPVOID,
605 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
606 if (pci && (INT) pci != -1)
607 WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_EXPANDTREE, MPFROMP(pci), MPVOID);
608 *sz = 0;
609 pci = WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_QUERYRECORDEMPHASIS,
610 MPFROMLONG(CMA_FIRST), MPFROMSHORT(CRA_CURSORED));
611 if (pci && (INT) pci != -1) {
612 commafmt(szBytes, sizeof(szBytes), pci->attrFile);
613 sprintf(sz,
614 "%s %s%s",
615 szBytes, GetPString(IDS_FILETEXT), &"s"[pci->attrFile == 1]);
616 }
617 WinSetDlgItemText(hwnd, DSZ_NUMFILES, sz);
618
619 WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_SORTRECORD, MPFROMP(SortSizeCnr),
620 MPVOID);
621 DosBeep(500, 25); // Wake up user
622 return 0;
623
624 case WM_ADJUSTWINDOWPOS:
625 PostMsg(hwnd, UM_STRETCH, MPVOID, MPVOID);
626 break;
627
628 case UM_STRETCH:
629 {
630 SWP swpC, swp;
631
632 WinQueryWindowPos(hwnd, &swp);
633 if (!(swp.fl & (SWP_HIDE | SWP_MINIMIZE))) {
634 WinQueryWindowPos(WinWindowFromID(hwnd, DSZ_CNR), &swpC);
635 WinSetWindowPos(WinWindowFromID(hwnd, DSZ_CNR), HWND_TOP,
636 SysVal(SV_CXSIZEBORDER),
637 swpC.y,
638 swp.cx - (SysVal(SV_CXSIZEBORDER) * 2),
639 (swp.cy - swpC.y) - (SysVal(SV_CYTITLEBAR) +
640 SysVal(SV_CYSIZEBORDER)),
641 SWP_MOVE | SWP_SIZE);
642 }
643 }
644 return 0;
645
646 case WM_PRESPARAMCHANGED:
647 PresParamChanged(hwnd, "DirSizes", mp1, mp2);
648 break;
649
650 case WM_DRAWITEM:
651 if (mp2) {
652
653 OWNERITEM *oi = mp2;
654 CNRDRAWITEMINFO *cnd;
655 PCNRITEM pci;
656
657 if (oi->idItem == CMA_TEXT) {
658
659 cnd = (CNRDRAWITEMINFO *)oi->hItem;
660
661 if (cnd) {
662 pci = (PCNRITEM)cnd->pRecord;
663
664 if (pci) {
665 POINTL aptl[TXTBOX_COUNT];
666 POINTL ptl;
667 PSZ p;
668 LONG clr;
669 LONG x;
670 LONG yBottom;
671 INT boxHeight;
672 p = strchr(pci->pszFileName, '\r');
673 if (p) {
674 // draw text
675 if (*(pci->pszLongName + 1) == 1) // is root record
676 GpiSetColor(oi->hps, CLR_DARKRED);
677 else if (!pci->cbFile) // no size
678 GpiSetColor(oi->hps, CLR_DARKGRAY);
679 else if (!pci->easize) // no size below
680 GpiSetColor(oi->hps, CLR_DARKBLUE);
681 else
682 GpiSetColor(oi->hps, CLR_BLACK);
683 GpiSetBackMix(oi->hps, BM_LEAVEALONE);
684 GpiSetMix(oi->hps, FM_OVERPAINT);
685
686 *p = 0; // Make 1 line high
687
688 // Calculate nominal graph box height based on font size
689 GpiQueryTextBox(oi->hps, strlen(pci->pszFileName),
690 pci->pszFileName, TXTBOX_COUNT, aptl);
691 boxHeight = aptl[TXTBOX_TOPRIGHT].y - aptl[TXTBOX_BOTTOMRIGHT].y;
692 boxHeight -= 4;
693
694 // Calculate nominal baseline of graph box
695 // rclItem.yBottom is at center of icon because it is
696 yBottom = oi->rclItem.yBottom - boxHeight + 3;
697
698 // Place text above graph box with a bit of whitespace between
699 ptl.x = oi->rclItem.xLeft;
700 ptl.y = yBottom + boxHeight + 6; // 03 Aug 07 SHL
701 // GpiMove(oi->hps, &ptl);
702 GpiCharStringAt(oi->hps, &ptl, strlen(pci->pszFileName),
703 pci->pszFileName);
704
705 *p = '\r'; // Restore
706
707 // draw the graph box
708 // GpiQueryTextBox(oi->hps, 1, "#", TXTBOX_COUNT, aptl); // 03 Aug 07 SHL
709 // draw black outline
710 GpiSetColor(oi->hps, CLR_BLACK);
711 ptl.x = oi->rclItem.xLeft;
712 ptl.y = yBottom + 2;
713 GpiMove(oi->hps, &ptl);
714 ptl.x = oi->rclItem.xLeft + 201;
715 ptl.y = yBottom + boxHeight;
716 GpiBox(oi->hps, DRO_OUTLINE, &ptl, 0, 0);
717 // fill with gray
718 GpiSetColor(oi->hps, CLR_PALEGRAY);
719 ptl.x = oi->rclItem.xLeft + 1;
720 ptl.y = yBottom + 3;
721 GpiMove(oi->hps, &ptl);
722 ptl.x = oi->rclItem.xLeft + 200;
723 ptl.y = yBottom + boxHeight - 1;
724 GpiBox(oi->hps, DRO_OUTLINEFILL, &ptl, 0, 0);
725
726 // draw shadow at bottom & right sides
727 GpiSetColor(oi->hps, CLR_DARKGRAY);
728 ptl.x = oi->rclItem.xLeft + 1;
729 ptl.y = yBottom + 3;
730 GpiMove(oi->hps, &ptl);
731 ptl.x = oi->rclItem.xLeft + 200;
732 GpiLine(oi->hps, &ptl);
733 ptl.y = yBottom + boxHeight - 1;
734 GpiLine(oi->hps, &ptl);
735
736 // draw highlight at top and left sides
737 GpiSetColor(oi->hps, CLR_WHITE);
738 ptl.x = oi->rclItem.xLeft + 1;
739 GpiLine(oi->hps, &ptl);
740 ptl.y = yBottom + 3;
741 GpiLine(oi->hps, &ptl);
742
743 // draw shadow of box
744 GpiSetColor(oi->hps, CLR_DARKGRAY);
745 ptl.x = oi->rclItem.xLeft + 2;
746 ptl.y = yBottom + boxHeight;
747 GpiMove(oi->hps, &ptl);
748 ptl.x = oi->rclItem.xLeft + 203;
749 GpiLine(oi->hps, &ptl);
750 ptl.y = yBottom + boxHeight - 2;
751 GpiLine(oi->hps, &ptl);
752 ptl.x--;
753 GpiMove(oi->hps, &ptl);
754 ptl.y = yBottom + 1;
755 GpiLine(oi->hps, &ptl);
756 ptl.x = oi->rclItem.xLeft + 2;
757 GpiLine(oi->hps, &ptl);
758
759 // fill box with graph bar, flags is integer %
760 if (pci->flags) {
761 if (*(pci->pszLongName + 1) == 1) // is root record
762 GpiSetColor(oi->hps, CLR_DARKGREEN);
763 else
764 GpiSetColor(oi->hps, CLR_RED);
765 ptl.x = oi->rclItem.xLeft + 2;
766 ptl.y = yBottom + 3;
767 GpiMove(oi->hps, &ptl);
768 ptl.x = oi->rclItem.xLeft + pci->flags * 2;
769 ptl.y = yBottom + boxHeight - 1;
770 GpiBox(oi->hps, DRO_OUTLINEFILL, &ptl, 0, 0);
771
772 // draw highlights and shadows on graph
773 if (*(pci->pszLongName + 1) == 1)
774 GpiSetColor(oi->hps, CLR_GREEN);
775 else
776 GpiSetColor(oi->hps, CLR_PALEGRAY);
777 if (pci->flags > 5) {
778 ptl.x = oi->rclItem.xLeft + 1;
779 ptl.y = yBottom + 3;
780 GpiMove(oi->hps, &ptl);
781 ptl.y = yBottom + boxHeight - 1;
782 GpiLine(oi->hps, &ptl);
783 }
784 else {
785 ptl.y = yBottom + boxHeight - 1;
786 GpiMove(oi->hps, &ptl);
787 }
788 ptl.x = oi->rclItem.xLeft + pci->flags * 2;
789 GpiLine(oi->hps, &ptl);
790 if (*(pci->pszLongName + 1) != 1) {
791 GpiSetColor(oi->hps, CLR_DARKRED);
792 ptl.x = oi->rclItem.xLeft + 2;
793 ptl.y = yBottom + 3;
794 GpiMove(oi->hps, &ptl);
795 ptl.x = oi->rclItem.xLeft + pci->flags * 2;
796 GpiLine(oi->hps, &ptl);
797 }
798 }
799
800 // draw hash marks in box
801 GpiSetColor(oi->hps, CLR_WHITE);
802 clr = CLR_WHITE;
803 for (x = 1; x < 20; x++) {
804 if (clr == CLR_WHITE && x * 10 > pci->flags * 2) {
805 clr = CLR_BLACK;
806 GpiSetColor(oi->hps, CLR_BLACK);
807 }
808 ptl.x = oi->rclItem.xLeft + 1 + x * 10;
809 ptl.y = yBottom + boxHeight - 1;
810 GpiMove(oi->hps, &ptl);
811 switch (x) {
812 case 1:
813 case 3:
814 case 5:
815 case 7:
816 case 9:
817 case 11:
818 case 13:
819 case 15:
820 case 17:
821 case 19:
822 ptl.y -= 1;
823 break;
824 case 10:
825 ptl.y -= 4;
826 break;
827 case 2:
828 case 4:
829 case 6:
830 case 8:
831 case 12:
832 case 14:
833 case 16:
834 case 18:
835 ptl.y -= 2;
836 break;
837 }
838 GpiLine(oi->hps, &ptl);
839 } // for x
840 return MRFROMLONG(TRUE);
841 }
842 }
843 }
844 }
845 }
846 return FALSE; // Let PM draw
847
848 case WM_CONTROL:
849 switch (SHORT2FROMMP(mp1)) {
850 case CN_ENTER:
851 if (mp2) {
852 PCNRITEM pci = (PCNRITEM)((PNOTIFYRECORDENTER)mp2)->pRecord;
853 CHAR szFileName[CCHMAXPATH]; // 23 Jul 07 SHL
854 CHAR szTemp[CCHMAXPATH];
855
856 if (pci) {
857 *szFileName = 0;
858 while (pci && (INT) pci != -1) {
859 memset(szTemp, 0, sizeof(szTemp));
860 strncpy(szTemp, pci->pszFileName,
861 pci->pszDisplayName - pci->pszFileName);
862 strrev(szTemp);
863 if (*szFileName && *szTemp != '\\')
864 strcat(szFileName, "\\");
865 strcat(szFileName, szTemp);
866 pci = WinSendDlgItemMsg(hwnd, DSZ_CNR, CM_QUERYRECORD,
867 MPFROMP(pci),
868 MPFROM2SHORT(CMA_PARENT, CMA_ITEMORDER));
869 }
870 strrev(szFileName);
871 if (!fVTreeOpensWPS)
872 OpenDirCnr((HWND)0,
873 hwndMain ? hwndMain : HWND_DESKTOP,
874 hwnd,
875 FALSE,
876 szFileName);
877 else {
878
879 ULONG size = sizeof(ULONG);
880 ULONG flWindowAttr = CV_ICON;
881 CHAR s[33];
882
883 strcpy(s, "ICON");
884 PrfQueryProfileData(fmprof, appname, "DirflWindowAttr",
885 (PVOID) & flWindowAttr, &size);
886 if (flWindowAttr & CV_DETAIL) {
887 if (IsRoot(szFileName))
888 strcpy(s, "TREE");
889 else
890 strcpy(s, "DETAILS");
891 }
892 OpenObject(szFileName, s, hwnd);
893 }
894 }
895 }
896 break;
897 case CN_EMPHASIS:
898 pState = INSTDATA(hwnd);
899 if (pState && !pState->working && mp2) {
900
901 PNOTIFYRECORDEMPHASIS pre = mp2;
902
903 pci = (PCNRITEM) ((pre) ? pre->pRecord : NULL);
904 if (pci && (pre->fEmphasisMask & CRA_SELECTED) &&
905 (pci->rc.flRecordAttr & CRA_SELECTED)) {
906 commafmt(szBytes, sizeof(szBytes), pci->attrFile);
907 sprintf(sz,
908 "%s %s%s",
909 szBytes,
910 GetPString(IDS_FILETEXT), &"s"[pci->attrFile == 1]);
911 WinSetDlgItemText(hwnd, DSZ_NUMFILES, sz);
912 }
913 }
914 break;
915 }
916 return 0;
917
918 case WM_COMMAND:
919 switch (SHORT1FROMMP(mp1)) {
920 case IDM_HELP:
921 if (hwndHelp)
922 WinSendMsg(hwndHelp, HM_DISPLAY_HELP,
923 MPFROM2SHORT(HELP_DIRSIZE, 0), MPFROMSHORT(HM_RESOURCEID));
924 break;
925
926 case DSZ_PRINT:
927 // Save button
928 pState = INSTDATA(hwnd);
929 if (!pState)
930 Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
931 else {
932
933 CHAR szFileName[CCHMAXPATH];
934 FILE *fp;
935
936 save_dir2(szFileName);
937 sprintf(&szFileName[strlen(szFileName)], "\\%csizes.Rpt",
938 (pState) ? toupper(*pState->szDirName) : '+');
939 if (export_filename(hwnd, szFileName, FALSE) && *szFileName) {
940 if (stricmp(szFileName, "PRN") &&
941 strnicmp(szFileName, "\\DEV\\LPT", 8) &&
942 !strchr(szFileName, '.'))
943 strcat(szFileName, ".RPT");
944 fp = fopen(szFileName, "a+");
945 if (!fp) {
946 saymsg(MB_CANCEL,
947 hwnd,
948 GetPString(IDS_ERRORTEXT),
949 GetPString(IDS_COMPCANTOPENTEXT), szFileName);
950 }
951 else {
952 WinSetPointer(HWND_DESKTOP, hptrBusy);
953 PrintToFile(WinWindowFromID(hwnd, DSZ_CNR), 0, NULL, fp);
954 fclose(fp);
955 WinSetPointer(HWND_DESKTOP, hptrArrow);
956 }
957 }
958 }
959 break;
960
961 case DSZ_EXPAND:
962 case DSZ_COLLAPSE:
963 pState = INSTDATA(hwnd);
964 if (pState) {
965 pci = (PCNRITEM) WinSendDlgItemMsg(hwnd, DSZ_CNR,
966 CM_QUERYRECORDEMPHASIS,
967 MPFROMLONG(CMA_FIRST),
968 MPFROMSHORT(CRA_CURSORED));
969 if (pci) {
970 WinEnableWindow(WinWindowFromID(hwnd, DID_OK), FALSE);
971 WinEnableWindow(WinWindowFromID(hwnd, IDM_HELP), FALSE);
972 WinEnableWindow(WinWindowFromID(hwnd, DSZ_COLLAPSE), FALSE);
973 WinEnableWindow(WinWindowFromID(hwnd, DSZ_EXPAND), FALSE);
974 WinEnableWindow(WinWindowFromID(hwnd, DSZ_PRINT), FALSE);
975 WinEnableWindow(WinWindowFromID(hwnd, DID_CANCEL), FALSE);
976 // fixme to use thread - too slow on large trees
977 ExpandAll(WinWindowFromID(hwnd, DSZ_CNR),
978 (SHORT1FROMMP(mp1) == DSZ_EXPAND), pci);
979 WinEnableWindow(WinWindowFromID(hwnd, DID_OK), TRUE);
980 WinEnableWindow(WinWindowFromID(hwnd, IDM_HELP), TRUE);
981 WinEnableWindow(WinWindowFromID(hwnd, DSZ_COLLAPSE), TRUE);
982 WinEnableWindow(WinWindowFromID(hwnd, DSZ_EXPAND), TRUE);
983 WinEnableWindow(WinWindowFromID(hwnd, DSZ_PRINT), TRUE);
984 WinEnableWindow(WinWindowFromID(hwnd, DID_CANCEL), TRUE);
985 }
986 }
987 break;
988
989 case DID_OK:
990 case DID_CANCEL:
991 {
992 SWP swp;
993 ULONG size = sizeof(SWP);
994
995 WinQueryWindowPos(hwnd, &swp);
996 PrfWriteProfileData(fmprof, FM3Str, "DirSizes.Position", (PVOID) &swp,
997 size);
998 }
999 pState = INSTDATA(hwnd);
1000 if (!pState)
1001 Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
1002 else {
1003 if (pState->working) {
1004 pState->dying = TRUE;
1005 pState->chStopFlag = (BYTE)0xff;
1006 DosBeep(1000, 100); // Complain?
1007 }
1008 else
1009 WinDismissDlg(hwnd, 0);
1010 }
1011 break;
1012 } // switch mp1
1013 return 0;
1014
1015 case WM_CLOSE:
1016 pState = INSTDATA(hwnd);
1017 if (pState)
1018 pState->chStopFlag = (BYTE)0xff;
1019 DosSleep(1);
1020 break;
1021
1022 case WM_DESTROY:
1023 pState = INSTDATA(hwnd);
1024 if (pState) {
1025 pState->chStopFlag = (BYTE)0xff;
1026 if (pState->hptr)
1027 WinDestroyPointer(pState->hptr);
1028 DosSleep(16); //05 Aug 07 GKY 33
1029 xfree(pState, pszSrcFile, __LINE__); // Let's hope no one is still looking
1030# ifdef FORTIFY
1031 Fortify_LeaveScope();
1032# endif
1033 }
1034 DosPostEventSem(CompactSem);
1035 break;
1036 }
1037 return WinDefDlgProc(hwnd, msg, mp1, mp2);
1038}
1039
1040#pragma alloc_text(DIRSIZE,ProcessDir,FillCnrThread,DirSizeProc)
1041#pragma alloc_text(DIRSIZE2,PrintToFile,FillInRecSizes,SortSizeCnr)
1042
Note: See TracBrowser for help on using the repository browser.