source: trunk/dll/dirsize.c@ 1321

Last change on this file since 1321 was 1321, checked in by Steven Levine, 17 years ago

Rework casts variable types for OpenWatcom 1.8 compatibility
Add more FORTIFY support

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