source: trunk/dll/dirsize.c@ 841

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

This implements large file support; The wrappers to allow WARP3 compatibility are not done so this will not run on Warp3or Warp 4 pre fixpack 12(?)

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