source: trunk/dll/dirsize.c@ 1335

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

Ticket 26: Add exception handlers to all threads using xbeginthread

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