source: trunk/dll/dirsize.c@ 1398

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

Move embeded strings to PCSZ variables or string table; Eliminate Error2 functions Runtime_Error with NULL format string returns "No data" error. Change declares from PSZ to PCSZ in functions where the variable isn't changed. Added btm as an executable file type in several additional places. Use fProtectOnly to prevent attempt to execute Dos and Win programs on "Protect only" installs in several additional places.

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