source: trunk/dll/dirsize.c@ 1554

Last change on this file since 1554 was 1554, checked in by Gregg Young, 15 years ago

Check that pTmpDir IsValid and recreate if not found; Fixes hangs caused by temp file creation failures. (Ticket 440)

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