source: trunk/dll/dirsize.c@ 920

Last change on this file since 920 was 920, checked in by Gregg Young, 18 years ago

Cleanup of NormalizeCmdLine moved to pathutil.c

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