source: trunk/dll/dirsize.c@ 1394

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

Ticket 340: Convert GetPString to use STRINGTABLE.

Drop fm3dll.str and mkstr.exe from makefiles and wpi builders

Convert many functions to expect PCSZ arguments.
Correct walk, compare and dirsizes dialog setups to ignore saved dialog size
Drop copyright.c logic from makefile

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