source: trunk/dll/dirsize.c@ 1400

Last change on this file since 1400 was 1400, checked in by Gregg Young, 16 years ago

Remainder of changes to rename commafmt.h/c (Ticket 28, 82); Additional strings moved to PCSZs in init.c (Ticket 6); Added WriteDetailsSwitches used it and LoadDetailsSwitches to consolidate inline code (Ticket 343, 344)

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