source: trunk/dll/dirsize.c@ 1177

Last change on this file since 1177 was 1177, checked in by John Small, 17 years ago

Ticket 187: Draft 2: Move remaining function declarations

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